aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-04-17 16:38:16 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-17 16:43:46 -0400
commit584c5e2ad3ada1a5ccfffa68347b79c3681cc36e (patch)
tree462835521cf30f6ceb29471bc2cb6cf37dd9bc94
parent7b56f76edf2da7ab3e356cc0db16f9af4c6a26e2 (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.h15
-rw-r--r--arch/sparc/net/bpf_jit_asm.S6
-rw-r--r--arch/sparc/net/bpf_jit_comp.c107
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 */
43extern u32 bpf_jit_load_word[];
44extern u32 bpf_jit_load_half[];
45extern u32 bpf_jit_load_byte[];
46extern u32 bpf_jit_load_byte_msh[];
47extern u32 bpf_jit_load_word_positive_offset[];
48extern u32 bpf_jit_load_half_positive_offset[];
49extern u32 bpf_jit_load_byte_positive_offset[];
50extern u32 bpf_jit_load_byte_msh_positive_offset[];
51extern u32 bpf_jit_load_word_negative_offset[];
52extern u32 bpf_jit_load_half_negative_offset[];
53extern u32 bpf_jit_load_byte_negative_offset[];
54extern 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
197bpf_error: 197bpf_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
12int bpf_jit_enable __read_mostly; 12int bpf_jit_enable __read_mostly;
13 13
14/* assembly code in arch/sparc/net/bpf_jit_asm.S */
15extern u32 bpf_jit_load_word[];
16extern u32 bpf_jit_load_half[];
17extern u32 bpf_jit_load_byte[];
18extern u32 bpf_jit_load_byte_msh[];
19extern u32 bpf_jit_load_word_positive_offset[];
20extern u32 bpf_jit_load_half_positive_offset[];
21extern u32 bpf_jit_load_byte_positive_offset[];
22extern u32 bpf_jit_load_byte_msh_positive_offset[];
23extern u32 bpf_jit_load_word_negative_offset[];
24extern u32 bpf_jit_load_half_negative_offset[];
25extern u32 bpf_jit_load_byte_negative_offset[];
26extern u32 bpf_jit_load_byte_msh_negative_offset[];
27
28static inline bool is_simm13(unsigned int value) 14static 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) \
178do { \ 164do { \
@@ -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) \
198do { \ 184do { \
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 { \
222do { unsigned int _off = offsetof(STRUCT, FIELD); \ 208do { 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) \
228do { unsigned int _off = offsetof(STRUCT, FIELD); \ 214do { 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) \
234do { unsigned int _off = offsetof(STRUCT, FIELD); \ 220do { 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) \
240do { unsigned int _off = offsetof(STRUCT, FIELD); \ 226do { 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) \
245do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \ 231do { 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) \
250do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST); \ 236do { *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) \
254do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC); \ 240do { *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) \
293do { unsigned int _here = addrs[i] - 8; \ 279do { 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) \
298do { *prog++ = BR_OPC | WDISP22(OFF); \ 284do { *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
336void bpf_jit_compile(struct sk_filter *fp) 351void 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();