Skip to content

Commit e1cf4be

Browse files
borkmannAlexei Starovoitov
authored andcommitted
bpf, s390x: remove ld_abs/ld_ind
Since LD_ABS/LD_IND instructions are now removed from the core and reimplemented through a combination of inlined BPF instructions and a slow-path helper, we can get rid of the complexity from s390x JIT. Tested on s390x instance on LinuxONE. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Cc: Michael Holzheu <holzheu@linux.vnet.ibm.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent dbf44da commit e1cf4be

File tree

4 files changed

+13
-252
lines changed

4 files changed

+13
-252
lines changed

arch/s390/net/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
#
33
# Arch-specific network modules
44
#
5-
obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o
5+
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o

arch/s390/net/bpf_jit.S

Lines changed: 0 additions & 116 deletions
This file was deleted.

arch/s390/net/bpf_jit.h

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
#include <linux/filter.h>
1717
#include <linux/types.h>
1818

19-
extern u8 sk_load_word_pos[], sk_load_half_pos[], sk_load_byte_pos[];
20-
extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
21-
2219
#endif /* __ASSEMBLY__ */
2320

2421
/*
@@ -36,15 +33,6 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
3633
* | | |
3734
* | BPF stack | |
3835
* | | |
39-
* +---------------+ |
40-
* | 8 byte skbp | |
41-
* R15+176 -> +---------------+ |
42-
* | 8 byte hlen | |
43-
* R15+168 -> +---------------+ |
44-
* | 4 byte align | |
45-
* +---------------+ |
46-
* | 4 byte temp | |
47-
* | for bpf_jit.S | |
4836
* R15+160 -> +---------------+ |
4937
* | new backchain | |
5038
* R15+152 -> +---------------+ |
@@ -57,17 +45,11 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
5745
* The stack size used by the BPF program ("BPF stack" above) is passed
5846
* via "aux->stack_depth".
5947
*/
60-
#define STK_SPACE_ADD (8 + 8 + 4 + 4 + 160)
48+
#define STK_SPACE_ADD (160)
6149
#define STK_160_UNUSED (160 - 12 * 8)
6250
#define STK_OFF (STK_SPACE_ADD - STK_160_UNUSED)
63-
#define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */
64-
#define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */
65-
#define STK_OFF_SKBP 176 /* Offset of SKB pointer on stack */
6651

6752
#define STK_OFF_R6 (160 - 11 * 8) /* Offset of r6 on stack */
6853
#define STK_OFF_TCCNT (160 - 12 * 8) /* Offset of tail_call_cnt on stack */
6954

70-
/* Offset to skip condition code check */
71-
#define OFF_OK 4
72-
7355
#endif /* __ARCH_S390_NET_BPF_JIT_H */

arch/s390/net/bpf_jit_comp.c

Lines changed: 11 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,21 @@ struct bpf_jit {
4747

4848
#define BPF_SIZE_MAX 0xffff /* Max size for program (16 bit branches) */
4949

50-
#define SEEN_SKB 1 /* skb access */
51-
#define SEEN_MEM 2 /* use mem[] for temporary storage */
52-
#define SEEN_RET0 4 /* ret0_ip points to a valid return 0 */
53-
#define SEEN_LITERAL 8 /* code uses literals */
54-
#define SEEN_FUNC 16 /* calls C functions */
55-
#define SEEN_TAIL_CALL 32 /* code uses tail calls */
56-
#define SEEN_REG_AX 64 /* code uses constant blinding */
57-
#define SEEN_STACK (SEEN_FUNC | SEEN_MEM | SEEN_SKB)
50+
#define SEEN_MEM (1 << 0) /* use mem[] for temporary storage */
51+
#define SEEN_RET0 (1 << 1) /* ret0_ip points to a valid return 0 */
52+
#define SEEN_LITERAL (1 << 2) /* code uses literals */
53+
#define SEEN_FUNC (1 << 3) /* calls C functions */
54+
#define SEEN_TAIL_CALL (1 << 4) /* code uses tail calls */
55+
#define SEEN_REG_AX (1 << 5) /* code uses constant blinding */
56+
#define SEEN_STACK (SEEN_FUNC | SEEN_MEM)
5857

5958
/*
6059
* s390 registers
6160
*/
6261
#define REG_W0 (MAX_BPF_JIT_REG + 0) /* Work register 1 (even) */
6362
#define REG_W1 (MAX_BPF_JIT_REG + 1) /* Work register 2 (odd) */
64-
#define REG_SKB_DATA (MAX_BPF_JIT_REG + 2) /* SKB data register */
65-
#define REG_L (MAX_BPF_JIT_REG + 3) /* Literal pool register */
66-
#define REG_15 (MAX_BPF_JIT_REG + 4) /* Register 15 */
63+
#define REG_L (MAX_BPF_JIT_REG + 2) /* Literal pool register */
64+
#define REG_15 (MAX_BPF_JIT_REG + 3) /* Register 15 */
6765
#define REG_0 REG_W0 /* Register 0 */
6866
#define REG_1 REG_W1 /* Register 1 */
6967
#define REG_2 BPF_REG_1 /* Register 2 */
@@ -88,10 +86,8 @@ static const int reg2hex[] = {
8886
[BPF_REG_9] = 10,
8987
/* BPF stack pointer */
9088
[BPF_REG_FP] = 13,
91-
/* Register for blinding (shared with REG_SKB_DATA) */
89+
/* Register for blinding */
9290
[BPF_REG_AX] = 12,
93-
/* SKB data pointer */
94-
[REG_SKB_DATA] = 12,
9591
/* Work registers for s390x backend */
9692
[REG_W0] = 0,
9793
[REG_W1] = 1,
@@ -384,27 +380,6 @@ static void save_restore_regs(struct bpf_jit *jit, int op, u32 stack_depth)
384380
} while (re <= 15);
385381
}
386382

387-
/*
388-
* For SKB access %b1 contains the SKB pointer. For "bpf_jit.S"
389-
* we store the SKB header length on the stack and the SKB data
390-
* pointer in REG_SKB_DATA if BPF_REG_AX is not used.
391-
*/
392-
static void emit_load_skb_data_hlen(struct bpf_jit *jit)
393-
{
394-
/* Header length: llgf %w1,<len>(%b1) */
395-
EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_1,
396-
offsetof(struct sk_buff, len));
397-
/* s %w1,<data_len>(%b1) */
398-
EMIT4_DISP(0x5b000000, REG_W1, BPF_REG_1,
399-
offsetof(struct sk_buff, data_len));
400-
/* stg %w1,ST_OFF_HLEN(%r0,%r15) */
401-
EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15, STK_OFF_HLEN);
402-
if (!(jit->seen & SEEN_REG_AX))
403-
/* lg %skb_data,data_off(%b1) */
404-
EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
405-
BPF_REG_1, offsetof(struct sk_buff, data));
406-
}
407-
408383
/*
409384
* Emit function prologue
410385
*
@@ -445,12 +420,6 @@ static void bpf_jit_prologue(struct bpf_jit *jit, u32 stack_depth)
445420
EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0,
446421
REG_15, 152);
447422
}
448-
if (jit->seen & SEEN_SKB) {
449-
emit_load_skb_data_hlen(jit);
450-
/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
451-
EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15,
452-
STK_OFF_SKBP);
453-
}
454423
}
455424

456425
/*
@@ -483,12 +452,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
483452
{
484453
struct bpf_insn *insn = &fp->insnsi[i];
485454
int jmp_off, last, insn_count = 1;
486-
unsigned int func_addr, mask;
487455
u32 dst_reg = insn->dst_reg;
488456
u32 src_reg = insn->src_reg;
489457
u32 *addrs = jit->addrs;
490458
s32 imm = insn->imm;
491459
s16 off = insn->off;
460+
unsigned int mask;
492461

493462
if (dst_reg == BPF_REG_AX || src_reg == BPF_REG_AX)
494463
jit->seen |= SEEN_REG_AX;
@@ -970,13 +939,6 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
970939
EMIT2(0x0d00, REG_14, REG_W1);
971940
/* lgr %b0,%r2: load return value into %b0 */
972941
EMIT4(0xb9040000, BPF_REG_0, REG_2);
973-
if ((jit->seen & SEEN_SKB) &&
974-
bpf_helper_changes_pkt_data((void *)func)) {
975-
/* lg %b1,ST_OFF_SKBP(%r15) */
976-
EMIT6_DISP_LH(0xe3000000, 0x0004, BPF_REG_1, REG_0,
977-
REG_15, STK_OFF_SKBP);
978-
emit_load_skb_data_hlen(jit);
979-
}
980942
break;
981943
}
982944
case BPF_JMP | BPF_TAIL_CALL:
@@ -1176,73 +1138,6 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
11761138
jmp_off = addrs[i + off + 1] - (addrs[i + 1] - 4);
11771139
EMIT4_PCREL(0xa7040000 | mask << 8, jmp_off);
11781140
break;
1179-
/*
1180-
* BPF_LD
1181-
*/
1182-
case BPF_LD | BPF_ABS | BPF_B: /* b0 = *(u8 *) (skb->data+imm) */
1183-
case BPF_LD | BPF_IND | BPF_B: /* b0 = *(u8 *) (skb->data+imm+src) */
1184-
if ((BPF_MODE(insn->code) == BPF_ABS) && (imm >= 0))
1185-
func_addr = __pa(sk_load_byte_pos);
1186-
else
1187-
func_addr = __pa(sk_load_byte);
1188-
goto call_fn;
1189-
case BPF_LD | BPF_ABS | BPF_H: /* b0 = *(u16 *) (skb->data+imm) */
1190-
case BPF_LD | BPF_IND | BPF_H: /* b0 = *(u16 *) (skb->data+imm+src) */
1191-
if ((BPF_MODE(insn->code) == BPF_ABS) && (imm >= 0))
1192-
func_addr = __pa(sk_load_half_pos);
1193-
else
1194-
func_addr = __pa(sk_load_half);
1195-
goto call_fn;
1196-
case BPF_LD | BPF_ABS | BPF_W: /* b0 = *(u32 *) (skb->data+imm) */
1197-
case BPF_LD | BPF_IND | BPF_W: /* b0 = *(u32 *) (skb->data+imm+src) */
1198-
if ((BPF_MODE(insn->code) == BPF_ABS) && (imm >= 0))
1199-
func_addr = __pa(sk_load_word_pos);
1200-
else
1201-
func_addr = __pa(sk_load_word);
1202-
goto call_fn;
1203-
call_fn:
1204-
jit->seen |= SEEN_SKB | SEEN_RET0 | SEEN_FUNC;
1205-
REG_SET_SEEN(REG_14); /* Return address of possible func call */
1206-
1207-
/*
1208-
* Implicit input:
1209-
* BPF_REG_6 (R7) : skb pointer
1210-
* REG_SKB_DATA (R12): skb data pointer (if no BPF_REG_AX)
1211-
*
1212-
* Calculated input:
1213-
* BPF_REG_2 (R3) : offset of byte(s) to fetch in skb
1214-
* BPF_REG_5 (R6) : return address
1215-
*
1216-
* Output:
1217-
* BPF_REG_0 (R14): data read from skb
1218-
*
1219-
* Scratch registers (BPF_REG_1-5)
1220-
*/
1221-
1222-
/* Call function: llilf %w1,func_addr */
1223-
EMIT6_IMM(0xc00f0000, REG_W1, func_addr);
1224-
1225-
/* Offset: lgfi %b2,imm */
1226-
EMIT6_IMM(0xc0010000, BPF_REG_2, imm);
1227-
if (BPF_MODE(insn->code) == BPF_IND)
1228-
/* agfr %b2,%src (%src is s32 here) */
1229-
EMIT4(0xb9180000, BPF_REG_2, src_reg);
1230-
1231-
/* Reload REG_SKB_DATA if BPF_REG_AX is used */
1232-
if (jit->seen & SEEN_REG_AX)
1233-
/* lg %skb_data,data_off(%b6) */
1234-
EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
1235-
BPF_REG_6, offsetof(struct sk_buff, data));
1236-
/* basr %b5,%w1 (%b5 is call saved) */
1237-
EMIT2(0x0d00, BPF_REG_5, REG_W1);
1238-
1239-
/*
1240-
* Note: For fast access we jump directly after the
1241-
* jnz instruction from bpf_jit.S
1242-
*/
1243-
/* jnz <ret0> */
1244-
EMIT4_PCREL(0xa7740000, jit->ret0_ip - jit->prg);
1245-
break;
12461141
default: /* too complex, give up */
12471142
pr_err("Unknown opcode %02x\n", insn->code);
12481143
return -1;

0 commit comments

Comments
 (0)