1
2
3
4
5
6
7
8
9
10
11
12
13#include <asm/asm.h>
14#include <asm/isa-rev.h>
15#include <asm/regdef.h>
16#include "bpf_jit.h"
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40#define skb a0
41#define offset a1
42#define SKF_LL_OFF (-0x200000)
43
44
45 .set noreorder
46
47#define is_offset_negative(TYPE) \
48 \
49 slti t0, offset, 0; \
50 bgtz t0, bpf_slow_path_
51
52
53#define is_offset_in_header(SIZE, TYPE) \
54 \
55 addiu $r_s0, $r_skb_hl, -SIZE; \
56 slt t0, $r_s0, offset; \
57 bgtz t0, bpf_slow_path_
58
59LEAF(sk_load_word)
60 is_offset_negative(word)
61FEXPORT(sk_load_word_positive)
62 is_offset_in_header(4, word)
63
64 PTR_ADDU t1, $r_skb_data, offset
65 .set reorder
66 lw $r_A, 0(t1)
67 .set noreorder
68#ifdef CONFIG_CPU_LITTLE_ENDIAN
69
70 wsbh t0, $r_A
71 rotr $r_A, t0, 16
72# else
73 sll t0, $r_A, 24
74 srl t1, $r_A, 24
75 srl t2, $r_A, 8
76 or t0, t0, t1
77 andi t2, t2, 0xff00
78 andi t1, $r_A, 0xff00
79 or t0, t0, t2
80 sll t1, t1, 8
81 or $r_A, t0, t1
82# endif
83#endif
84 jr $r_ra
85 move $r_ret, zero
86 END(sk_load_word)
87
88LEAF(sk_load_half)
89 is_offset_negative(half)
90FEXPORT(sk_load_half_positive)
91 is_offset_in_header(2, half)
92
93 PTR_ADDU t1, $r_skb_data, offset
94 lhu $r_A, 0(t1)
95#ifdef CONFIG_CPU_LITTLE_ENDIAN
96
97 wsbh $r_A, $r_A
98# else
99 sll t0, $r_A, 8
100 srl t1, $r_A, 8
101 andi t0, t0, 0xff00
102 or $r_A, t0, t1
103# endif
104#endif
105 jr $r_ra
106 move $r_ret, zero
107 END(sk_load_half)
108
109LEAF(sk_load_byte)
110 is_offset_negative(byte)
111FEXPORT(sk_load_byte_positive)
112 is_offset_in_header(1, byte)
113
114 PTR_ADDU t1, $r_skb_data, offset
115 lbu $r_A, 0(t1)
116 jr $r_ra
117 move $r_ret, zero
118 END(sk_load_byte)
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139#ifdef CONFIG_CPU_LITTLE_ENDIAN
140#define DS_OFFSET(SIZE) (4 * SZREG)
141#else
142#define DS_OFFSET(SIZE) ((4 * SZREG) + (4 - SIZE))
143#endif
144#define bpf_slow_path_common(SIZE) \
145 \
146 LONG_ADDIU $r_s1, $r_skb_len, -SIZE; \
147 sltu $r_s0, offset, $r_s1; \
148 beqz $r_s0, fault; \
149 \
150 LONG_ADDIU a3, zero, SIZE; \
151 PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \
152 PTR_LA t0, skb_copy_bits; \
153 PTR_S $r_ra, (5 * SZREG)($r_sp); \
154 \
155 PTR_ADDIU a2, $r_sp, DS_OFFSET(SIZE); \
156 jalr t0; \
157 \
158 INT_S zero, (4 * SZREG)($r_sp); \
159
160
161
162
163 \
164 \
165 PTR_L $r_ra, (5 * SZREG)($r_sp); \
166 INT_L $r_s0, (4 * SZREG)($r_sp); \
167 bltz v0, fault; \
168 PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \
169 move $r_ret, zero; \
170
171NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp)
172 bpf_slow_path_common(4)
173#ifdef CONFIG_CPU_LITTLE_ENDIAN
174
175 wsbh t0, $r_s0
176 jr $r_ra
177 rotr $r_A, t0, 16
178# else
179 sll t0, $r_s0, 24
180 srl t1, $r_s0, 24
181 srl t2, $r_s0, 8
182 or t0, t0, t1
183 andi t2, t2, 0xff00
184 andi t1, $r_s0, 0xff00
185 or t0, t0, t2
186 sll t1, t1, 8
187 jr $r_ra
188 or $r_A, t0, t1
189# endif
190#else
191 jr $r_ra
192 move $r_A, $r_s0
193#endif
194
195 END(bpf_slow_path_word)
196
197NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp)
198 bpf_slow_path_common(2)
199#ifdef CONFIG_CPU_LITTLE_ENDIAN
200
201 jr $r_ra
202 wsbh $r_A, $r_s0
203# else
204 sll t0, $r_s0, 8
205 andi t1, $r_s0, 0xff00
206 andi t0, t0, 0xff00
207 srl t1, t1, 8
208 jr $r_ra
209 or $r_A, t0, t1
210# endif
211#else
212 jr $r_ra
213 move $r_A, $r_s0
214#endif
215
216 END(bpf_slow_path_half)
217
218NESTED(bpf_slow_path_byte, (6 * SZREG), $r_sp)
219 bpf_slow_path_common(1)
220 jr $r_ra
221 move $r_A, $r_s0
222
223 END(bpf_slow_path_byte)
224
225
226
227
228 .macro bpf_is_end_of_data
229 li t0, SKF_LL_OFF
230
231 slt t1, offset, t0
232 bgtz t1, fault
233
234 .endm
235
236
237
238
239
240
241
242
243
244#define bpf_negative_common(SIZE) \
245 PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \
246 PTR_LA t0, bpf_internal_load_pointer_neg_helper; \
247 PTR_S $r_ra, (5 * SZREG)($r_sp); \
248 jalr t0; \
249 li a2, SIZE; \
250 PTR_L $r_ra, (5 * SZREG)($r_sp); \
251 \
252 beqz v0, fault; \
253 PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \
254 \
255 move $r_s0, v0; \
256 \
257 move $r_ret, zero; \
258
259bpf_slow_path_word_neg:
260 bpf_is_end_of_data
261NESTED(sk_load_word_negative, (6 * SZREG), $r_sp)
262 bpf_negative_common(4)
263 jr $r_ra
264 lw $r_A, 0($r_s0)
265 END(sk_load_word_negative)
266
267bpf_slow_path_half_neg:
268 bpf_is_end_of_data
269NESTED(sk_load_half_negative, (6 * SZREG), $r_sp)
270 bpf_negative_common(2)
271 jr $r_ra
272 lhu $r_A, 0($r_s0)
273 END(sk_load_half_negative)
274
275bpf_slow_path_byte_neg:
276 bpf_is_end_of_data
277NESTED(sk_load_byte_negative, (6 * SZREG), $r_sp)
278 bpf_negative_common(1)
279 jr $r_ra
280 lbu $r_A, 0($r_s0)
281 END(sk_load_byte_negative)
282
283fault:
284 jr $r_ra
285 addiu $r_ret, zero, 1
286