Skip to content

Commit 9db7f2b

Browse files
Michael Holzheudavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent cde66c2 commit 9db7f2b

File tree

2 files changed

+37
-23
lines changed

2 files changed

+37
-23
lines changed

arch/s390/net/bpf_jit.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
3636
* | BPF stack | |
3737
* | | |
3838
* +---------------+ |
39+
* | 8 byte skbp | |
40+
* R15+170 -> +---------------+ |
3941
* | 8 byte hlen | |
4042
* R15+168 -> +---------------+ |
4143
* | 4 byte align | |
@@ -51,11 +53,12 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
5153
* We get 160 bytes stack space from calling function, but only use
5254
* 12 * 8 byte for old backchain, r15..r6, and tail_call_cnt.
5355
*/
54-
#define STK_SPACE (MAX_BPF_STACK + 8 + 4 + 4 + 160)
56+
#define STK_SPACE (MAX_BPF_STACK + 8 + 8 + 4 + 4 + 160)
5557
#define STK_160_UNUSED (160 - 12 * 8)
5658
#define STK_OFF (STK_SPACE - STK_160_UNUSED)
5759
#define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */
5860
#define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */
61+
#define STK_OFF_SKBP 170 /* Offset of SKB pointer on stack */
5962

6063
#define STK_OFF_R6 (160 - 11 * 8) /* Offset of r6 on stack */
6164
#define STK_OFF_TCCNT (160 - 12 * 8) /* Offset of tail_call_cnt on stack */

arch/s390/net/bpf_jit_comp.c

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct bpf_jit {
5353
#define SEEN_LITERAL 8 /* code uses literals */
5454
#define SEEN_FUNC 16 /* calls C functions */
5555
#define SEEN_TAIL_CALL 32 /* code uses tail calls */
56+
#define SEEN_SKB_CHANGE 64 /* code changes skb data */
5657
#define SEEN_STACK (SEEN_FUNC | SEEN_MEM | SEEN_SKB)
5758

5859
/*
@@ -381,6 +382,26 @@ static void save_restore_regs(struct bpf_jit *jit, int op)
381382
} while (re <= 15);
382383
}
383384

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+
*/
390+
static 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+
384405
/*
385406
* Emit function prologue
386407
*
@@ -421,25 +442,12 @@ static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic)
421442
EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0,
422443
REG_15, 152);
423444
}
424-
/*
425-
* For SKB access %b1 contains the SKB pointer. For "bpf_jit.S"
426-
* we store the SKB header length on the stack and the SKB data
427-
* pointer in REG_SKB_DATA.
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) */
445+
if (jit->seen & SEEN_SKB)
446+
emit_load_skb_data_hlen(jit);
447+
if (jit->seen & SEEN_SKB_CHANGE)
448+
/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
437449
EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
438-
STK_OFF_HLEN);
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-
}
450+
STK_OFF_SKBP);
443451
/* Clear A (%b0) and X (%b7) registers for converted BPF programs */
444452
if (is_classic) {
445453
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
967975
*/
968976
const u64 func = (u64)__bpf_call_base + imm;
969977

970-
if (bpf_helper_changes_skb_data((void *)func))
971-
/* TODO reload skb->data, hlen */
972-
return -1;
973-
974978
REG_SET_SEEN(BPF_REG_5);
975979
jit->seen |= SEEN_FUNC;
976980
/* 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
980984
EMIT2(0x0d00, REG_14, REG_W1);
981985
/* lgr %b0,%r2: load return value into %b0 */
982986
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+
}
983994
break;
984995
}
985996
case BPF_JMP | BPF_CALL | BPF_X:

0 commit comments

Comments
 (0)