aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/net
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2015-07-29 15:15:18 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-29 17:59:58 -0400
commit9db7f2b818809ef2c40fbd64cfcf5ccb0107d7e8 (patch)
treee4d0b2ed3dc2e6900106edff81e834f063007e1c /arch/s390/net
parentcde66c2d88da1d73d755109c80ce4c34b917596b (diff)
s390/bpf: recache skb->data/hlen for skb_vlan_push/pop
Allow eBPF programs attached to TC qdiscs call skb_vlan_push/pop via helper functions. These functions may change skb->data/hlen. This data is cached by s390 JIT to improve performance of ld_abs/ld_ind instructions. Therefore after a change we have to reload the data. In case of usage of skb_vlan_push/pop, in the prologue we store the SKB pointer on the stack and restore it after BPF_JMP_CALL to skb_vlan_push/pop. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/s390/net')
-rw-r--r--arch/s390/net/bpf_jit.h5
-rw-r--r--arch/s390/net/bpf_jit_comp.c55
2 files changed, 37 insertions, 23 deletions
diff --git a/arch/s390/net/bpf_jit.h b/arch/s390/net/bpf_jit.h
index f6498eec9ee1..f010c93a88b1 100644
--- a/arch/s390/net/bpf_jit.h
+++ b/arch/s390/net/bpf_jit.h
@@ -36,6 +36,8 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
36 * | BPF stack | | 36 * | BPF stack | |
37 * | | | 37 * | | |
38 * +---------------+ | 38 * +---------------+ |
39 * | 8 byte skbp | |
40 * R15+170 -> +---------------+ |
39 * | 8 byte hlen | | 41 * | 8 byte hlen | |
40 * R15+168 -> +---------------+ | 42 * R15+168 -> +---------------+ |
41 * | 4 byte align | | 43 * | 4 byte align | |
@@ -51,11 +53,12 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
51 * We get 160 bytes stack space from calling function, but only use 53 * We get 160 bytes stack space from calling function, but only use
52 * 12 * 8 byte for old backchain, r15..r6, and tail_call_cnt. 54 * 12 * 8 byte for old backchain, r15..r6, and tail_call_cnt.
53 */ 55 */
54#define STK_SPACE (MAX_BPF_STACK + 8 + 4 + 4 + 160) 56#define STK_SPACE (MAX_BPF_STACK + 8 + 8 + 4 + 4 + 160)
55#define STK_160_UNUSED (160 - 12 * 8) 57#define STK_160_UNUSED (160 - 12 * 8)
56#define STK_OFF (STK_SPACE - STK_160_UNUSED) 58#define STK_OFF (STK_SPACE - STK_160_UNUSED)
57#define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */ 59#define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */
58#define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */ 60#define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */
61#define STK_OFF_SKBP 170 /* Offset of SKB pointer on stack */
59 62
60#define STK_OFF_R6 (160 - 11 * 8) /* Offset of r6 on stack */ 63#define STK_OFF_R6 (160 - 11 * 8) /* Offset of r6 on stack */
61#define STK_OFF_TCCNT (160 - 12 * 8) /* Offset of tail_call_cnt on stack */ 64#define STK_OFF_TCCNT (160 - 12 * 8) /* Offset of tail_call_cnt on stack */
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 3dd01637f83a..bbbac6da37af 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -53,6 +53,7 @@ struct bpf_jit {
53#define SEEN_LITERAL 8 /* code uses literals */ 53#define SEEN_LITERAL 8 /* code uses literals */
54#define SEEN_FUNC 16 /* calls C functions */ 54#define SEEN_FUNC 16 /* calls C functions */
55#define SEEN_TAIL_CALL 32 /* code uses tail calls */ 55#define SEEN_TAIL_CALL 32 /* code uses tail calls */
56#define SEEN_SKB_CHANGE 64 /* code changes skb data */
56#define SEEN_STACK (SEEN_FUNC | SEEN_MEM | SEEN_SKB) 57#define SEEN_STACK (SEEN_FUNC | SEEN_MEM | SEEN_SKB)
57 58
58/* 59/*
@@ -382,6 +383,26 @@ static void save_restore_regs(struct bpf_jit *jit, int op)
382} 383}
383 384
384/* 385/*
386 * For SKB access %b1 contains the SKB pointer. For "bpf_jit.S"
387 * we store the SKB header length on the stack and the SKB data
388 * pointer in REG_SKB_DATA.
389 */
390static void emit_load_skb_data_hlen(struct bpf_jit *jit)
391{
392 /* Header length: llgf %w1,<len>(%b1) */
393 EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_1,
394 offsetof(struct sk_buff, len));
395 /* s %w1,<data_len>(%b1) */
396 EMIT4_DISP(0x5b000000, REG_W1, BPF_REG_1,
397 offsetof(struct sk_buff, data_len));
398 /* stg %w1,ST_OFF_HLEN(%r0,%r15) */
399 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15, STK_OFF_HLEN);
400 /* lg %skb_data,data_off(%b1) */
401 EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
402 BPF_REG_1, offsetof(struct sk_buff, data));
403}
404
405/*
385 * Emit function prologue 406 * Emit function prologue
386 * 407 *
387 * Save registers and create stack frame if necessary. 408 * Save registers and create stack frame if necessary.
@@ -421,25 +442,12 @@ static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic)
421 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, 442 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0,
422 REG_15, 152); 443 REG_15, 152);
423 } 444 }
424 /* 445 if (jit->seen & SEEN_SKB)
425 * For SKB access %b1 contains the SKB pointer. For "bpf_jit.S" 446 emit_load_skb_data_hlen(jit);
426 * we store the SKB header length on the stack and the SKB data 447 if (jit->seen & SEEN_SKB_CHANGE)
427 * pointer in REG_SKB_DATA. 448 /* stg %b1,ST_OFF_SKBP(%r0,%r15) */
428 */
429 if (jit->seen & SEEN_SKB) {
430 /* Header length: llgf %w1,<len>(%b1) */
431 EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_1,
432 offsetof(struct sk_buff, len));
433 /* s %w1,<data_len>(%b1) */
434 EMIT4_DISP(0x5b000000, REG_W1, BPF_REG_1,
435 offsetof(struct sk_buff, data_len));
436 /* stg %w1,ST_OFF_HLEN(%r0,%r15) */
437 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15, 449 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
438 STK_OFF_HLEN); 450 STK_OFF_SKBP);
439 /* lg %skb_data,data_off(%b1) */
440 EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
441 BPF_REG_1, offsetof(struct sk_buff, data));
442 }
443 /* Clear A (%b0) and X (%b7) registers for converted BPF programs */ 451 /* Clear A (%b0) and X (%b7) registers for converted BPF programs */
444 if (is_classic) { 452 if (is_classic) {
445 if (REG_SEEN(BPF_REG_A)) 453 if (REG_SEEN(BPF_REG_A))
@@ -967,10 +975,6 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
967 */ 975 */
968 const u64 func = (u64)__bpf_call_base + imm; 976 const u64 func = (u64)__bpf_call_base + imm;
969 977
970 if (bpf_helper_changes_skb_data((void *)func))
971 /* TODO reload skb->data, hlen */
972 return -1;
973
974 REG_SET_SEEN(BPF_REG_5); 978 REG_SET_SEEN(BPF_REG_5);
975 jit->seen |= SEEN_FUNC; 979 jit->seen |= SEEN_FUNC;
976 /* lg %w1,<d(imm)>(%l) */ 980 /* lg %w1,<d(imm)>(%l) */
@@ -980,6 +984,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
980 EMIT2(0x0d00, REG_14, REG_W1); 984 EMIT2(0x0d00, REG_14, REG_W1);
981 /* lgr %b0,%r2: load return value into %b0 */ 985 /* lgr %b0,%r2: load return value into %b0 */
982 EMIT4(0xb9040000, BPF_REG_0, REG_2); 986 EMIT4(0xb9040000, BPF_REG_0, REG_2);
987 if (bpf_helper_changes_skb_data((void *)func)) {
988 jit->seen |= SEEN_SKB_CHANGE;
989 /* lg %b1,ST_OFF_SKBP(%r15) */
990 EMIT6_DISP_LH(0xe3000000, 0x0004, BPF_REG_1, REG_0,
991 REG_15, STK_OFF_SKBP);
992 emit_load_skb_data_hlen(jit);
993 }
983 break; 994 break;
984 } 995 }
985 case BPF_JMP | BPF_CALL | BPF_X: 996 case BPF_JMP | BPF_CALL | BPF_X: