2 * bpf_jit_asm64.S: Packet/header access helper functions
3 * for PPC64 BPF compiler.
5 * Copyright 2016, Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
8 * Based on bpf_jit_asm.S by Matt Evans
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; version 2
16 #include <asm/ppc_asm.h>
17 #include <asm/ptrace.h>
18 #include "bpf_jit64.h"
21 * All of these routines are called directly from generated code,
22 * with the below register usage:
23 * r27 skb pointer (ctx)
24 * r25 skb header length
25 * r26 skb->data pointer
28 * Result is passed back in:
29 * r8 data read in host endian format (accumulator)
31 * r9 is used as a temporary register
41 _GLOBAL_TOC(sk_load_word)
43 blt bpf_slow_path_word_neg
44 b sk_load_word_positive_offset
46 _GLOBAL_TOC(sk_load_word_positive_offset)
47 /* Are we accessing past headlen? */
50 blt bpf_slow_path_word
51 /* Nope, just hitting the header. cr0 here is eq or gt! */
52 LWZX_BE r_val, r_data, r_off
53 blr /* Return success, cr0 != LT */
55 _GLOBAL_TOC(sk_load_half)
57 blt bpf_slow_path_half_neg
58 b sk_load_half_positive_offset
60 _GLOBAL_TOC(sk_load_half_positive_offset)
63 blt bpf_slow_path_half
64 LHZX_BE r_val, r_data, r_off
67 _GLOBAL_TOC(sk_load_byte)
69 blt bpf_slow_path_byte_neg
70 b sk_load_byte_positive_offset
72 _GLOBAL_TOC(sk_load_byte_positive_offset)
74 ble bpf_slow_path_byte
75 lbzx r_val, r_data, r_off
79 * Call out to skb_copy_bits:
80 * Allocate a new stack frame here to remain ABI-compliant in
83 #define bpf_slow_path_common(SIZE) \
85 std r0, PPC_LR_STKOFF(r1); \
86 stdu r1, -(STACK_FRAME_MIN_SIZE + BPF_PPC_STACK_LOCALS)(r1); \
88 /* r4 = r_off as passed */ \
89 addi r5, r1, STACK_FRAME_MIN_SIZE; \
94 addi r5, r1, STACK_FRAME_MIN_SIZE; \
95 /* r3 = 0 on success */ \
96 addi r1, r1, STACK_FRAME_MIN_SIZE + BPF_PPC_STACK_LOCALS; \
97 ld r0, PPC_LR_STKOFF(r1); \
100 blt bpf_error; /* cr0 = LT */
103 bpf_slow_path_common(4)
104 /* Data value is on stack, and cr0 != LT */
109 bpf_slow_path_common(2)
114 bpf_slow_path_common(1)
119 * Call out to bpf_internal_load_pointer_neg_helper
121 #define sk_negative_common(SIZE) \
123 std r0, PPC_LR_STKOFF(r1); \
124 stdu r1, -STACK_FRAME_MIN_SIZE(r1); \
126 /* r4 = r_off, as passed */ \
128 bl bpf_internal_load_pointer_neg_helper; \
130 addi r1, r1, STACK_FRAME_MIN_SIZE; \
131 ld r0, PPC_LR_STKOFF(r1); \
133 /* R3 != 0 on success */ \
135 beq bpf_error_slow; /* cr0 = EQ */
137 bpf_slow_path_word_neg:
138 lis r_tmp, -32 /* SKF_LL_OFF */
139 cmpd r_off, r_tmp /* addr < SKF_* */
140 blt bpf_error /* cr0 = LT */
141 b sk_load_word_negative_offset
143 _GLOBAL_TOC(sk_load_word_negative_offset)
144 sk_negative_common(4)
148 bpf_slow_path_half_neg:
149 lis r_tmp, -32 /* SKF_LL_OFF */
150 cmpd r_off, r_tmp /* addr < SKF_* */
151 blt bpf_error /* cr0 = LT */
152 b sk_load_half_negative_offset
154 _GLOBAL_TOC(sk_load_half_negative_offset)
155 sk_negative_common(2)
159 bpf_slow_path_byte_neg:
160 lis r_tmp, -32 /* SKF_LL_OFF */
161 cmpd r_off, r_tmp /* addr < SKF_* */
162 blt bpf_error /* cr0 = LT */
163 b sk_load_byte_negative_offset
165 _GLOBAL_TOC(sk_load_byte_negative_offset)
166 sk_negative_common(1)
171 /* fabricate a cr0 = lt */
176 * Entered with cr0 = lt
177 * Generated code will 'blt epilogue', returning 0.