diff options
author | David S. Miller <davem@davemloft.net> | 2012-04-17 16:38:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-17 16:43:46 -0400 |
commit | 584c5e2ad3ada1a5ccfffa68347b79c3681cc36e (patch) | |
tree | 462835521cf30f6ceb29471bc2cb6cf37dd9bc94 | |
parent | 7b56f76edf2da7ab3e356cc0db16f9af4c6a26e2 (diff) |
net: filter: Fix some more small issues in sparc JIT.
Fix mixed space and tabs.
Put bpf_jit_load_*[] externs into bpf_jit.h
"while(0)" --> "while (0)"
"COND (X)" --> "COND(X)"
Document branch offset calculations, and bpf_error's return
sequence.
Document the reason we need to emit three nops between the
%y register write and the divide instruction.
Remove erroneous trailing semicolons from emit_read_y() and
emit_write_y().
Based upon feedback from Sam Ravnborg.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/net/bpf_jit.h | 15 | ||||
-rw-r--r-- | arch/sparc/net/bpf_jit_asm.S | 6 | ||||
-rw-r--r-- | arch/sparc/net/bpf_jit_comp.c | 107 |
3 files changed, 84 insertions, 44 deletions
diff --git a/arch/sparc/net/bpf_jit.h b/arch/sparc/net/bpf_jit.h index 05175be442fb..33d6b375ff12 100644 --- a/arch/sparc/net/bpf_jit.h +++ b/arch/sparc/net/bpf_jit.h | |||
@@ -38,6 +38,21 @@ | |||
38 | #define r_TMP G1 | 38 | #define r_TMP G1 |
39 | #define r_TMP2 G2 | 39 | #define r_TMP2 G2 |
40 | #define r_OFF G3 | 40 | #define r_OFF G3 |
41 | |||
42 | /* assembly code in arch/sparc/net/bpf_jit_asm.S */ | ||
43 | extern u32 bpf_jit_load_word[]; | ||
44 | extern u32 bpf_jit_load_half[]; | ||
45 | extern u32 bpf_jit_load_byte[]; | ||
46 | extern u32 bpf_jit_load_byte_msh[]; | ||
47 | extern u32 bpf_jit_load_word_positive_offset[]; | ||
48 | extern u32 bpf_jit_load_half_positive_offset[]; | ||
49 | extern u32 bpf_jit_load_byte_positive_offset[]; | ||
50 | extern u32 bpf_jit_load_byte_msh_positive_offset[]; | ||
51 | extern u32 bpf_jit_load_word_negative_offset[]; | ||
52 | extern u32 bpf_jit_load_half_negative_offset[]; | ||
53 | extern u32 bpf_jit_load_byte_negative_offset[]; | ||
54 | extern u32 bpf_jit_load_byte_msh_negative_offset[]; | ||
55 | |||
41 | #else | 56 | #else |
42 | #define r_SKB %o0 | 57 | #define r_SKB %o0 |
43 | #define r_A %o1 | 58 | #define r_A %o1 |
diff --git a/arch/sparc/net/bpf_jit_asm.S b/arch/sparc/net/bpf_jit_asm.S index 46d8f59f14c5..9d016c7017f7 100644 --- a/arch/sparc/net/bpf_jit_asm.S +++ b/arch/sparc/net/bpf_jit_asm.S | |||
@@ -195,5 +195,11 @@ bpf_jit_load_byte_msh_negative_offset: | |||
195 | sll r_OFF, 2, r_X | 195 | sll r_OFF, 2, r_X |
196 | 196 | ||
197 | bpf_error: | 197 | bpf_error: |
198 | /* Make the JIT program return zero. The JIT epilogue | ||
199 | * stores away the original %o7 into r_saved_O7. The | ||
200 | * normal leaf function return is to use "retl" which | ||
201 | * would evalute to "jmpl %o7 + 8, %g0" but we want to | ||
202 | * use the saved value thus the sequence you see here. | ||
203 | */ | ||
198 | jmpl r_saved_O7 + 8, %g0 | 204 | jmpl r_saved_O7 + 8, %g0 |
199 | clr %o0 | 205 | clr %o0 |
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index ebc89809f585..4ce0296575eb 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c | |||
@@ -11,20 +11,6 @@ | |||
11 | 11 | ||
12 | int bpf_jit_enable __read_mostly; | 12 | int bpf_jit_enable __read_mostly; |
13 | 13 | ||
14 | /* assembly code in arch/sparc/net/bpf_jit_asm.S */ | ||
15 | extern u32 bpf_jit_load_word[]; | ||
16 | extern u32 bpf_jit_load_half[]; | ||
17 | extern u32 bpf_jit_load_byte[]; | ||
18 | extern u32 bpf_jit_load_byte_msh[]; | ||
19 | extern u32 bpf_jit_load_word_positive_offset[]; | ||
20 | extern u32 bpf_jit_load_half_positive_offset[]; | ||
21 | extern u32 bpf_jit_load_byte_positive_offset[]; | ||
22 | extern u32 bpf_jit_load_byte_msh_positive_offset[]; | ||
23 | extern u32 bpf_jit_load_word_negative_offset[]; | ||
24 | extern u32 bpf_jit_load_half_negative_offset[]; | ||
25 | extern u32 bpf_jit_load_byte_negative_offset[]; | ||
26 | extern u32 bpf_jit_load_byte_msh_negative_offset[]; | ||
27 | |||
28 | static inline bool is_simm13(unsigned int value) | 14 | static inline bool is_simm13(unsigned int value) |
29 | { | 15 | { |
30 | return value + 0x1000 < 0x2000; | 16 | return value + 0x1000 < 0x2000; |
@@ -65,22 +51,22 @@ static void bpf_flush_icache(void *start_, void *end_) | |||
65 | #define F2(X, Y) (OP(X) | OP2(Y)) | 51 | #define F2(X, Y) (OP(X) | OP2(Y)) |
66 | #define F3(X, Y) (OP(X) | OP3(Y)) | 52 | #define F3(X, Y) (OP(X) | OP3(Y)) |
67 | 53 | ||
68 | #define CONDN COND (0x0) | 54 | #define CONDN COND(0x0) |
69 | #define CONDE COND (0x1) | 55 | #define CONDE COND(0x1) |
70 | #define CONDLE COND (0x2) | 56 | #define CONDLE COND(0x2) |
71 | #define CONDL COND (0x3) | 57 | #define CONDL COND(0x3) |
72 | #define CONDLEU COND (0x4) | 58 | #define CONDLEU COND(0x4) |
73 | #define CONDCS COND (0x5) | 59 | #define CONDCS COND(0x5) |
74 | #define CONDNEG COND (0x6) | 60 | #define CONDNEG COND(0x6) |
75 | #define CONDVC COND (0x7) | 61 | #define CONDVC COND(0x7) |
76 | #define CONDA COND (0x8) | 62 | #define CONDA COND(0x8) |
77 | #define CONDNE COND (0x9) | 63 | #define CONDNE COND(0x9) |
78 | #define CONDG COND (0xa) | 64 | #define CONDG COND(0xa) |
79 | #define CONDGE COND (0xb) | 65 | #define CONDGE COND(0xb) |
80 | #define CONDGU COND (0xc) | 66 | #define CONDGU COND(0xc) |
81 | #define CONDCC COND (0xd) | 67 | #define CONDCC COND(0xd) |
82 | #define CONDPOS COND (0xe) | 68 | #define CONDPOS COND(0xe) |
83 | #define CONDVS COND (0xf) | 69 | #define CONDVS COND(0xf) |
84 | 70 | ||
85 | #define CONDGEU CONDCC | 71 | #define CONDGEU CONDCC |
86 | #define CONDLU CONDCS | 72 | #define CONDLU CONDCS |
@@ -172,7 +158,7 @@ do { /* sethi %hi(K), REG */ \ | |||
172 | 158 | ||
173 | /* Emit | 159 | /* Emit |
174 | * | 160 | * |
175 | * OP r_A, r_X, r_A | 161 | * OP r_A, r_X, r_A |
176 | */ | 162 | */ |
177 | #define emit_alu_X(OPCODE) \ | 163 | #define emit_alu_X(OPCODE) \ |
178 | do { \ | 164 | do { \ |
@@ -195,7 +181,7 @@ do { \ | |||
195 | * is zero. | 181 | * is zero. |
196 | */ | 182 | */ |
197 | #define emit_alu_K(OPCODE, K) \ | 183 | #define emit_alu_K(OPCODE, K) \ |
198 | do { \ | 184 | do { \ |
199 | if (K) { \ | 185 | if (K) { \ |
200 | unsigned int _insn = OPCODE; \ | 186 | unsigned int _insn = OPCODE; \ |
201 | _insn |= RS1(r_A) | RD(r_A); \ | 187 | _insn |= RS1(r_A) | RD(r_A); \ |
@@ -204,7 +190,7 @@ do { \ | |||
204 | } else { \ | 190 | } else { \ |
205 | emit_set_const(K, r_TMP); \ | 191 | emit_set_const(K, r_TMP); \ |
206 | *prog++ = _insn | RS2(r_TMP); \ | 192 | *prog++ = _insn | RS2(r_TMP); \ |
207 | } \ | 193 | } \ |
208 | } \ | 194 | } \ |
209 | } while (0) | 195 | } while (0) |
210 | 196 | ||
@@ -222,37 +208,37 @@ do { \ | |||
222 | do { unsigned int _off = offsetof(STRUCT, FIELD); \ | 208 | do { unsigned int _off = offsetof(STRUCT, FIELD); \ |
223 | BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(void *)); \ | 209 | BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(void *)); \ |
224 | *prog++ = LDPTRI | RS1(BASE) | S13(_off) | RD(DEST); \ | 210 | *prog++ = LDPTRI | RS1(BASE) | S13(_off) | RD(DEST); \ |
225 | } while(0) | 211 | } while (0) |
226 | 212 | ||
227 | #define emit_load32(BASE, STRUCT, FIELD, DEST) \ | 213 | #define emit_load32(BASE, STRUCT, FIELD, DEST) \ |
228 | do { unsigned int _off = offsetof(STRUCT, FIELD); \ | 214 | do { unsigned int _off = offsetof(STRUCT, FIELD); \ |
229 | BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u32)); \ | 215 | BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u32)); \ |
230 | *prog++ = LD32I | RS1(BASE) | S13(_off) | RD(DEST); \ | 216 | *prog++ = LD32I | RS1(BASE) | S13(_off) | RD(DEST); \ |
231 | } while(0) | 217 | } while (0) |
232 | 218 | ||
233 | #define emit_load16(BASE, STRUCT, FIELD, DEST) \ | 219 | #define emit_load16(BASE, STRUCT, FIELD, DEST) \ |
234 | do { unsigned int _off = offsetof(STRUCT, FIELD); \ | 220 | do { unsigned int _off = offsetof(STRUCT, FIELD); \ |
235 | BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u16)); \ | 221 | BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u16)); \ |
236 | *prog++ = LD16I | RS1(BASE) | S13(_off) | RD(DEST); \ | 222 | *prog++ = LD16I | RS1(BASE) | S13(_off) | RD(DEST); \ |
237 | } while(0) | 223 | } while (0) |
238 | 224 | ||
239 | #define __emit_load8(BASE, STRUCT, FIELD, DEST) \ | 225 | #define __emit_load8(BASE, STRUCT, FIELD, DEST) \ |
240 | do { unsigned int _off = offsetof(STRUCT, FIELD); \ | 226 | do { unsigned int _off = offsetof(STRUCT, FIELD); \ |
241 | *prog++ = LD8I | RS1(BASE) | S13(_off) | RD(DEST); \ | 227 | *prog++ = LD8I | RS1(BASE) | S13(_off) | RD(DEST); \ |
242 | } while(0) | 228 | } while (0) |
243 | 229 | ||
244 | #define emit_load8(BASE, STRUCT, FIELD, DEST) \ | 230 | #define emit_load8(BASE, STRUCT, FIELD, DEST) \ |
245 | do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \ | 231 | do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \ |
246 | __emit_load8(BASE, STRUCT, FIELD, DEST); \ | 232 | __emit_load8(BASE, STRUCT, FIELD, DEST); \ |
247 | } while(0) | 233 | } while (0) |
248 | 234 | ||
249 | #define emit_ldmem(OFF, DEST) \ | 235 | #define emit_ldmem(OFF, DEST) \ |
250 | do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST); \ | 236 | do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST); \ |
251 | } while(0) | 237 | } while (0) |
252 | 238 | ||
253 | #define emit_stmem(OFF, SRC) \ | 239 | #define emit_stmem(OFF, SRC) \ |
254 | do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC); \ | 240 | do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC); \ |
255 | } while(0) | 241 | } while (0) |
256 | 242 | ||
257 | #define cpu_off offsetof(struct thread_info, cpu) | 243 | #define cpu_off offsetof(struct thread_info, cpu) |
258 | 244 | ||
@@ -292,16 +278,16 @@ do { void *_here = image + addrs[i] - 8; \ | |||
292 | #define emit_branch(BR_OPC, DEST) \ | 278 | #define emit_branch(BR_OPC, DEST) \ |
293 | do { unsigned int _here = addrs[i] - 8; \ | 279 | do { unsigned int _here = addrs[i] - 8; \ |
294 | *prog++ = BR_OPC | WDISP22((DEST) - _here); \ | 280 | *prog++ = BR_OPC | WDISP22((DEST) - _here); \ |
295 | } while(0) | 281 | } while (0) |
296 | 282 | ||
297 | #define emit_branch_off(BR_OPC, OFF) \ | 283 | #define emit_branch_off(BR_OPC, OFF) \ |
298 | do { *prog++ = BR_OPC | WDISP22(OFF); \ | 284 | do { *prog++ = BR_OPC | WDISP22(OFF); \ |
299 | } while(0) | 285 | } while (0) |
300 | 286 | ||
301 | #define emit_jump(DEST) emit_branch(BA, DEST) | 287 | #define emit_jump(DEST) emit_branch(BA, DEST) |
302 | 288 | ||
303 | #define emit_read_y(REG) *prog++ = RD_Y | RD(REG); | 289 | #define emit_read_y(REG) *prog++ = RD_Y | RD(REG) |
304 | #define emit_write_y(REG) *prog++ = WR_Y | IMMED | RS1(REG) | S13(0); | 290 | #define emit_write_y(REG) *prog++ = WR_Y | IMMED | RS1(REG) | S13(0) |
305 | 291 | ||
306 | #define emit_cmp(R1, R2) \ | 292 | #define emit_cmp(R1, R2) \ |
307 | *prog++ = (SUBCC | RS1(R1) | RS2(R2) | RD(G0)) | 293 | *prog++ = (SUBCC | RS1(R1) | RS2(R2) | RD(G0)) |
@@ -333,6 +319,35 @@ do { *prog++ = BR_OPC | WDISP22(OFF); \ | |||
333 | #define emit_release_stack(SZ) \ | 319 | #define emit_release_stack(SZ) \ |
334 | *prog++ = (ADD | IMMED | RS1(SP) | S13(SZ) | RD(SP)) | 320 | *prog++ = (ADD | IMMED | RS1(SP) | S13(SZ) | RD(SP)) |
335 | 321 | ||
322 | /* A note about branch offset calculations. The addrs[] array, | ||
323 | * indexed by BPF instruction, records the address after all the | ||
324 | * sparc instructions emitted for that BPF instruction. | ||
325 | * | ||
326 | * The most common case is to emit a branch at the end of such | ||
327 | * a code sequence. So this would be two instructions, the | ||
328 | * branch and it's delay slot. | ||
329 | * | ||
330 | * Therefore by default the branch emitters calculate the branch | ||
331 | * offset field as: | ||
332 | * | ||
333 | * destination - (addrs[i] - 8) | ||
334 | * | ||
335 | * This "addrs[i] - 8" is the address of the branch itself or | ||
336 | * what "." would be in assembler notation. The "8" part is | ||
337 | * how we take into consideration the branch and it's delay | ||
338 | * slot mentioned above. | ||
339 | * | ||
340 | * Sometimes we need to emit a branch earlier in the code | ||
341 | * sequence. And in these situations we adjust "destination" | ||
342 | * to accomodate this difference. For example, if we needed | ||
343 | * to emit a branch (and it's delay slot) right before the | ||
344 | * final instruction emitted for a BPF opcode, we'd use | ||
345 | * "destination + 4" instead of just plain "destination" above. | ||
346 | * | ||
347 | * This is why you see all of these funny emit_branch() and | ||
348 | * emit_jump() calls with adjusted offsets. | ||
349 | */ | ||
350 | |||
336 | void bpf_jit_compile(struct sk_filter *fp) | 351 | void bpf_jit_compile(struct sk_filter *fp) |
337 | { | 352 | { |
338 | unsigned int cleanup_addr, proglen, oldproglen = 0; | 353 | unsigned int cleanup_addr, proglen, oldproglen = 0; |
@@ -493,6 +508,10 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
493 | } | 508 | } |
494 | emit_write_y(G0); | 509 | emit_write_y(G0); |
495 | #ifdef CONFIG_SPARC32 | 510 | #ifdef CONFIG_SPARC32 |
511 | /* The Sparc v8 architecture requires | ||
512 | * three instructions between a %y | ||
513 | * register write and the first use. | ||
514 | */ | ||
496 | emit_nop(); | 515 | emit_nop(); |
497 | emit_nop(); | 516 | emit_nop(); |
498 | emit_nop(); | 517 | emit_nop(); |