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