Merge branch 'implement-cpuv4-support-for-s390x'
Ilya Leoshkevich says: ==================== Implement cpuv4 support for s390x v1: https://lore.kernel.org/bpf/20230830011128.1415752-1-iii@linux.ibm.com/ v1 -> v2: - Redo Disable zero-extension for BPF_MEMSX as Puranjay and Alexei suggested. - Drop the bpf_ct_insert_entry() patch, it went in via the bpf tree. - Rebase, don't apply A-bs because there were fixed conflicts. Hi, This series adds the cpuv4 support to the s390x eBPF JIT. Patches 1-3 are preliminary bugfixes. Patches 4-8 implement the new instructions. Patches 9-10 enable the tests. Best regards, Ilya ==================== Link: https://lore.kernel.org/r/20230919101336.2223655-1-iii@linux.ibm.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
cf67d28de3
|
@ -670,15 +670,18 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
|
|||
static int get_probe_mem_regno(const u8 *insn)
|
||||
{
|
||||
/*
|
||||
* insn must point to llgc, llgh, llgf or lg, which have destination
|
||||
* register at the same position.
|
||||
* insn must point to llgc, llgh, llgf, lg, lgb, lgh or lgf, which have
|
||||
* destination register at the same position.
|
||||
*/
|
||||
if (insn[0] != 0xe3) /* common llgc, llgh, llgf and lg prefix */
|
||||
if (insn[0] != 0xe3) /* common prefix */
|
||||
return -1;
|
||||
if (insn[5] != 0x90 && /* llgc */
|
||||
insn[5] != 0x91 && /* llgh */
|
||||
insn[5] != 0x16 && /* llgf */
|
||||
insn[5] != 0x04) /* lg */
|
||||
insn[5] != 0x04 && /* lg */
|
||||
insn[5] != 0x77 && /* lgb */
|
||||
insn[5] != 0x15 && /* lgh */
|
||||
insn[5] != 0x14) /* lgf */
|
||||
return -1;
|
||||
return insn[1] >> 4;
|
||||
}
|
||||
|
@ -776,6 +779,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
int i, bool extra_pass, u32 stack_depth)
|
||||
{
|
||||
struct bpf_insn *insn = &fp->insnsi[i];
|
||||
s16 branch_oc_off = insn->off;
|
||||
u32 dst_reg = insn->dst_reg;
|
||||
u32 src_reg = insn->src_reg;
|
||||
int last, insn_count = 1;
|
||||
|
@ -788,22 +792,55 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
int err;
|
||||
|
||||
if (BPF_CLASS(insn->code) == BPF_LDX &&
|
||||
BPF_MODE(insn->code) == BPF_PROBE_MEM)
|
||||
(BPF_MODE(insn->code) == BPF_PROBE_MEM ||
|
||||
BPF_MODE(insn->code) == BPF_PROBE_MEMSX))
|
||||
probe_prg = jit->prg;
|
||||
|
||||
switch (insn->code) {
|
||||
/*
|
||||
* BPF_MOV
|
||||
*/
|
||||
case BPF_ALU | BPF_MOV | BPF_X: /* dst = (u32) src */
|
||||
/* llgfr %dst,%src */
|
||||
EMIT4(0xb9160000, dst_reg, src_reg);
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
case BPF_ALU | BPF_MOV | BPF_X:
|
||||
switch (insn->off) {
|
||||
case 0: /* DST = (u32) SRC */
|
||||
/* llgfr %dst,%src */
|
||||
EMIT4(0xb9160000, dst_reg, src_reg);
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
case 8: /* DST = (u32)(s8) SRC */
|
||||
/* lbr %dst,%src */
|
||||
EMIT4(0xb9260000, dst_reg, src_reg);
|
||||
/* llgfr %dst,%dst */
|
||||
EMIT4(0xb9160000, dst_reg, dst_reg);
|
||||
break;
|
||||
case 16: /* DST = (u32)(s16) SRC */
|
||||
/* lhr %dst,%src */
|
||||
EMIT4(0xb9270000, dst_reg, src_reg);
|
||||
/* llgfr %dst,%dst */
|
||||
EMIT4(0xb9160000, dst_reg, dst_reg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BPF_ALU64 | BPF_MOV | BPF_X: /* dst = src */
|
||||
/* lgr %dst,%src */
|
||||
EMIT4(0xb9040000, dst_reg, src_reg);
|
||||
case BPF_ALU64 | BPF_MOV | BPF_X:
|
||||
switch (insn->off) {
|
||||
case 0: /* DST = SRC */
|
||||
/* lgr %dst,%src */
|
||||
EMIT4(0xb9040000, dst_reg, src_reg);
|
||||
break;
|
||||
case 8: /* DST = (s8) SRC */
|
||||
/* lgbr %dst,%src */
|
||||
EMIT4(0xb9060000, dst_reg, src_reg);
|
||||
break;
|
||||
case 16: /* DST = (s16) SRC */
|
||||
/* lghr %dst,%src */
|
||||
EMIT4(0xb9070000, dst_reg, src_reg);
|
||||
break;
|
||||
case 32: /* DST = (s32) SRC */
|
||||
/* lgfr %dst,%src */
|
||||
EMIT4(0xb9140000, dst_reg, src_reg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BPF_ALU | BPF_MOV | BPF_K: /* dst = (u32) imm */
|
||||
/* llilf %dst,imm */
|
||||
|
@ -912,66 +949,115 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
/*
|
||||
* BPF_DIV / BPF_MOD
|
||||
*/
|
||||
case BPF_ALU | BPF_DIV | BPF_X: /* dst = (u32) dst / (u32) src */
|
||||
case BPF_ALU | BPF_MOD | BPF_X: /* dst = (u32) dst % (u32) src */
|
||||
case BPF_ALU | BPF_DIV | BPF_X:
|
||||
case BPF_ALU | BPF_MOD | BPF_X:
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
/* lhi %w0,0 */
|
||||
EMIT4_IMM(0xa7080000, REG_W0, 0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
/* dlr %w0,%src */
|
||||
EMIT4(0xb9970000, REG_W0, src_reg);
|
||||
switch (off) {
|
||||
case 0: /* dst = (u32) dst {/,%} (u32) src */
|
||||
/* xr %w0,%w0 */
|
||||
EMIT2(0x1700, REG_W0, REG_W0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
/* dlr %w0,%src */
|
||||
EMIT4(0xb9970000, REG_W0, src_reg);
|
||||
break;
|
||||
case 1: /* dst = (u32) ((s32) dst {/,%} (s32) src) */
|
||||
/* lgfr %r1,%dst */
|
||||
EMIT4(0xb9140000, REG_W1, dst_reg);
|
||||
/* dsgfr %r0,%src */
|
||||
EMIT4(0xb91d0000, REG_W0, src_reg);
|
||||
break;
|
||||
}
|
||||
/* llgfr %dst,%rc */
|
||||
EMIT4(0xb9160000, dst_reg, rc_reg);
|
||||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
}
|
||||
case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / src */
|
||||
case BPF_ALU64 | BPF_MOD | BPF_X: /* dst = dst % src */
|
||||
case BPF_ALU64 | BPF_DIV | BPF_X:
|
||||
case BPF_ALU64 | BPF_MOD | BPF_X:
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dlgr %w0,%dst */
|
||||
EMIT4(0xb9870000, REG_W0, src_reg);
|
||||
switch (off) {
|
||||
case 0: /* dst = dst {/,%} src */
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dlgr %w0,%src */
|
||||
EMIT4(0xb9870000, REG_W0, src_reg);
|
||||
break;
|
||||
case 1: /* dst = (s64) dst {/,%} (s64) src */
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dsgr %w0,%src */
|
||||
EMIT4(0xb90d0000, REG_W0, src_reg);
|
||||
break;
|
||||
}
|
||||
/* lgr %dst,%rc */
|
||||
EMIT4(0xb9040000, dst_reg, rc_reg);
|
||||
break;
|
||||
}
|
||||
case BPF_ALU | BPF_DIV | BPF_K: /* dst = (u32) dst / (u32) imm */
|
||||
case BPF_ALU | BPF_MOD | BPF_K: /* dst = (u32) dst % (u32) imm */
|
||||
case BPF_ALU | BPF_DIV | BPF_K:
|
||||
case BPF_ALU | BPF_MOD | BPF_K:
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
if (imm == 1) {
|
||||
if (BPF_OP(insn->code) == BPF_MOD)
|
||||
/* lhgi %dst,0 */
|
||||
/* lghi %dst,0 */
|
||||
EMIT4_IMM(0xa7090000, dst_reg, 0);
|
||||
else
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
}
|
||||
/* lhi %w0,0 */
|
||||
EMIT4_IMM(0xa7080000, REG_W0, 0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
if (!is_first_pass(jit) && can_use_ldisp_for_lit32(jit)) {
|
||||
/* dl %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0097, REG_W0, REG_0, REG_L,
|
||||
EMIT_CONST_U32(imm));
|
||||
switch (off) {
|
||||
case 0: /* dst = (u32) dst {/,%} (u32) imm */
|
||||
/* xr %w0,%w0 */
|
||||
EMIT2(0x1700, REG_W0, REG_W0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
/* dl %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0097, REG_W0, REG_0,
|
||||
REG_L, EMIT_CONST_U32(imm));
|
||||
break;
|
||||
case 1: /* dst = (s32) dst {/,%} (s32) imm */
|
||||
/* lgfr %r1,%dst */
|
||||
EMIT4(0xb9140000, REG_W1, dst_reg);
|
||||
/* dsgf %r0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x001d, REG_W0, REG_0,
|
||||
REG_L, EMIT_CONST_U32(imm));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* lgfrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc40c0000, dst_reg,
|
||||
_EMIT_CONST_U32(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dlr %w0,%dst */
|
||||
EMIT4(0xb9970000, REG_W0, dst_reg);
|
||||
switch (off) {
|
||||
case 0: /* dst = (u32) dst {/,%} (u32) imm */
|
||||
/* xr %w0,%w0 */
|
||||
EMIT2(0x1700, REG_W0, REG_W0);
|
||||
/* lr %w1,%dst */
|
||||
EMIT2(0x1800, REG_W1, dst_reg);
|
||||
/* lrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc40d0000, dst_reg,
|
||||
_EMIT_CONST_U32(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dlr %w0,%dst */
|
||||
EMIT4(0xb9970000, REG_W0, dst_reg);
|
||||
break;
|
||||
case 1: /* dst = (s32) dst {/,%} (s32) imm */
|
||||
/* lgfr %w1,%dst */
|
||||
EMIT4(0xb9140000, REG_W1, dst_reg);
|
||||
/* lgfrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc40c0000, dst_reg,
|
||||
_EMIT_CONST_U32(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dsgr %w0,%dst */
|
||||
EMIT4(0xb90d0000, REG_W0, dst_reg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* llgfr %dst,%rc */
|
||||
EMIT4(0xb9160000, dst_reg, rc_reg);
|
||||
|
@ -979,8 +1065,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
insn_count = 2;
|
||||
break;
|
||||
}
|
||||
case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / imm */
|
||||
case BPF_ALU64 | BPF_MOD | BPF_K: /* dst = dst % imm */
|
||||
case BPF_ALU64 | BPF_DIV | BPF_K:
|
||||
case BPF_ALU64 | BPF_MOD | BPF_K:
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
|
@ -990,21 +1076,50 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
EMIT4_IMM(0xa7090000, dst_reg, 0);
|
||||
break;
|
||||
}
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
if (!is_first_pass(jit) && can_use_ldisp_for_lit64(jit)) {
|
||||
/* dlg %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L,
|
||||
EMIT_CONST_U64(imm));
|
||||
switch (off) {
|
||||
case 0: /* dst = dst {/,%} imm */
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dlg %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0,
|
||||
REG_L, EMIT_CONST_U64(imm));
|
||||
break;
|
||||
case 1: /* dst = (s64) dst {/,%} (s64) imm */
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* dsg %w0,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x000d, REG_W0, REG_0,
|
||||
REG_L, EMIT_CONST_U64(imm));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* lgrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc4080000, dst_reg,
|
||||
_EMIT_CONST_U64(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dlgr %w0,%dst */
|
||||
EMIT4(0xb9870000, REG_W0, dst_reg);
|
||||
switch (off) {
|
||||
case 0: /* dst = dst {/,%} imm */
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* lgrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc4080000, dst_reg,
|
||||
_EMIT_CONST_U64(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dlgr %w0,%dst */
|
||||
EMIT4(0xb9870000, REG_W0, dst_reg);
|
||||
break;
|
||||
case 1: /* dst = (s64) dst {/,%} (s64) imm */
|
||||
/* lgr %w1,%dst */
|
||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||
/* lgrl %dst,imm */
|
||||
EMIT6_PCREL_RILB(0xc4080000, dst_reg,
|
||||
_EMIT_CONST_U64(imm));
|
||||
jit->seen |= SEEN_LITERAL;
|
||||
/* dsgr %w0,%dst */
|
||||
EMIT4(0xb90d0000, REG_W0, dst_reg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* lgr %dst,%rc */
|
||||
EMIT4(0xb9040000, dst_reg, rc_reg);
|
||||
|
@ -1217,6 +1332,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
}
|
||||
break;
|
||||
case BPF_ALU | BPF_END | BPF_FROM_LE:
|
||||
case BPF_ALU64 | BPF_END | BPF_FROM_LE:
|
||||
switch (imm) {
|
||||
case 16: /* dst = (u16) cpu_to_le16(dst) */
|
||||
/* lrvr %dst,%dst */
|
||||
|
@ -1374,6 +1490,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEMSX | BPF_B: /* dst = *(s8 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
|
||||
/* lgb %dst,0(off,%src) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0077, dst_reg, src_reg, REG_0, off);
|
||||
jit->seen |= SEEN_MEM;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEM | BPF_H:
|
||||
/* llgh %dst,0(off,%src) */
|
||||
|
@ -1382,6 +1504,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEMSX | BPF_H: /* dst = *(s16 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
|
||||
/* lgh %dst,0(off,%src) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0015, dst_reg, src_reg, REG_0, off);
|
||||
jit->seen |= SEEN_MEM;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEM | BPF_W:
|
||||
/* llgf %dst,off(%src) */
|
||||
|
@ -1390,6 +1518,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
if (insn_is_zext(&insn[1]))
|
||||
insn_count = 2;
|
||||
break;
|
||||
case BPF_LDX | BPF_MEMSX | BPF_W: /* dst = *(s32 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
|
||||
/* lgf %dst,off(%src) */
|
||||
jit->seen |= SEEN_MEM;
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0014, dst_reg, src_reg, REG_0, off);
|
||||
break;
|
||||
case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
|
||||
case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
|
||||
/* lg %dst,0(off,%src) */
|
||||
|
@ -1570,6 +1704,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
* instruction itself (loop) and for BPF with offset 0 we
|
||||
* branch to the instruction behind the branch.
|
||||
*/
|
||||
case BPF_JMP32 | BPF_JA: /* if (true) */
|
||||
branch_oc_off = imm;
|
||||
fallthrough;
|
||||
case BPF_JMP | BPF_JA: /* if (true) */
|
||||
mask = 0xf000; /* j */
|
||||
goto branch_oc;
|
||||
|
@ -1738,14 +1875,16 @@ branch_xu:
|
|||
break;
|
||||
branch_oc:
|
||||
if (!is_first_pass(jit) &&
|
||||
can_use_rel(jit, addrs[i + off + 1])) {
|
||||
can_use_rel(jit, addrs[i + branch_oc_off + 1])) {
|
||||
/* brc mask,off */
|
||||
EMIT4_PCREL_RIC(0xa7040000,
|
||||
mask >> 12, addrs[i + off + 1]);
|
||||
mask >> 12,
|
||||
addrs[i + branch_oc_off + 1]);
|
||||
} else {
|
||||
/* brcl mask,off */
|
||||
EMIT6_PCREL_RILC(0xc0040000,
|
||||
mask >> 12, addrs[i + off + 1]);
|
||||
mask >> 12,
|
||||
addrs[i + branch_oc_off + 1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -3114,7 +3114,7 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
|
|||
|
||||
if (class == BPF_LDX) {
|
||||
if (t != SRC_OP)
|
||||
return BPF_SIZE(code) == BPF_DW;
|
||||
return BPF_SIZE(code) == BPF_DW || BPF_MODE(code) == BPF_MEMSX;
|
||||
/* LDX source must be ptr. */
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,30 +1,5 @@
|
|||
# TEMPORARY
|
||||
# Alphabetical order
|
||||
bloom_filter_map # failed to find kernel BTF type ID of '__x64_sys_getpgid': -3 (?)
|
||||
bpf_cookie # failed to open_and_load program: -524 (trampoline)
|
||||
bpf_loop # attaches to __x64_sys_nanosleep
|
||||
cgrp_local_storage # prog_attach unexpected error: -524 (trampoline)
|
||||
dynptr/test_dynptr_skb_data
|
||||
dynptr/test_skb_readonly
|
||||
exceptions # JIT does not support calling kfunc bpf_throw (exceptions)
|
||||
fexit_sleep # fexit_skel_load fexit skeleton failed (trampoline)
|
||||
get_stack_raw_tp # user_stack corrupted user stack (no backchain userspace)
|
||||
iters/testmod_seq* # s390x doesn't support kfuncs in modules yet
|
||||
kprobe_multi_bench_attach # bpf_program__attach_kprobe_multi_opts unexpected error: -95
|
||||
kprobe_multi_test # relies on fentry
|
||||
ksyms_btf/weak_ksyms* # test_ksyms_weak__open_and_load unexpected error: -22 (kfunc)
|
||||
ksyms_module # test_ksyms_module__open_and_load unexpected error: -9 (?)
|
||||
ksyms_module_libbpf # JIT does not support calling kernel function (kfunc)
|
||||
ksyms_module_lskel # test_ksyms_module_lskel__open_and_load unexpected error: -9 (?)
|
||||
module_attach # skel_attach skeleton attach failed: -524 (trampoline)
|
||||
ringbuf # skel_load skeleton load failed (?)
|
||||
stacktrace_build_id # compare_map_keys stackid_hmap vs. stackmap err -2 errno 2 (?)
|
||||
test_lsm # attach unexpected error: -524 (trampoline)
|
||||
trace_printk # trace_printk__load unexpected error: -2 (errno 2) (?)
|
||||
trace_vprintk # trace_vprintk__open_and_load unexpected error: -9 (?)
|
||||
unpriv_bpf_disabled # fentry
|
||||
user_ringbuf # failed to find kernel BTF type ID of '__s390x_sys_prctl': -3 (?)
|
||||
verif_stats # trace_vprintk__open_and_load unexpected error: -9 (?)
|
||||
xdp_bonding # failed to auto-attach program 'trace_on_entry': -524 (trampoline)
|
||||
xdp_metadata # JIT does not support calling kernel function (kfunc)
|
||||
test_task_under_cgroup # JIT does not support calling kernel function (kfunc)
|
||||
|
|
|
@ -49,6 +49,10 @@
|
|||
snprintf(buf, sizeof(buf), "%s%s", NETCLS_MOUNT_PATH, \
|
||||
CGROUP_WORK_DIR)
|
||||
|
||||
static __thread bool cgroup_workdir_mounted;
|
||||
|
||||
static void __cleanup_cgroup_environment(void);
|
||||
|
||||
static int __enable_controllers(const char *cgroup_path, const char *controllers)
|
||||
{
|
||||
char path[PATH_MAX + 1];
|
||||
|
@ -209,9 +213,10 @@ int setup_cgroup_environment(void)
|
|||
log_err("mount cgroup2");
|
||||
return 1;
|
||||
}
|
||||
cgroup_workdir_mounted = true;
|
||||
|
||||
/* Cleanup existing failed runs, now that the environment is setup */
|
||||
cleanup_cgroup_environment();
|
||||
__cleanup_cgroup_environment();
|
||||
|
||||
if (mkdir(cgroup_workdir, 0777) && errno != EEXIST) {
|
||||
log_err("mkdir cgroup work dir");
|
||||
|
@ -305,11 +310,26 @@ int join_parent_cgroup(const char *relative_path)
|
|||
return join_cgroup_from_top(cgroup_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* __cleanup_cgroup_environment() - Delete temporary cgroups
|
||||
*
|
||||
* This is a helper for cleanup_cgroup_environment() that is responsible for
|
||||
* deletion of all temporary cgroups that have been created during the test.
|
||||
*/
|
||||
static void __cleanup_cgroup_environment(void)
|
||||
{
|
||||
char cgroup_workdir[PATH_MAX + 1];
|
||||
|
||||
format_cgroup_path(cgroup_workdir, "");
|
||||
join_cgroup_from_top(CGROUP_MOUNT_PATH);
|
||||
nftw(cgroup_workdir, nftwfunc, WALK_FD_LIMIT, FTW_DEPTH | FTW_MOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* cleanup_cgroup_environment() - Cleanup Cgroup Testing Environment
|
||||
*
|
||||
* This is an idempotent function to delete all temporary cgroups that
|
||||
* have been created during the test, including the cgroup testing work
|
||||
* have been created during the test and unmount the cgroup testing work
|
||||
* directory.
|
||||
*
|
||||
* At call time, it moves the calling process to the root cgroup, and then
|
||||
|
@ -320,11 +340,10 @@ int join_parent_cgroup(const char *relative_path)
|
|||
*/
|
||||
void cleanup_cgroup_environment(void)
|
||||
{
|
||||
char cgroup_workdir[PATH_MAX + 1];
|
||||
|
||||
format_cgroup_path(cgroup_workdir, "");
|
||||
join_cgroup_from_top(CGROUP_MOUNT_PATH);
|
||||
nftw(cgroup_workdir, nftwfunc, WALK_FD_LIMIT, FTW_DEPTH | FTW_MOUNT);
|
||||
__cleanup_cgroup_environment();
|
||||
if (cgroup_workdir_mounted && umount(CGROUP_MOUNT_PATH))
|
||||
log_err("umount cgroup2");
|
||||
cgroup_workdir_mounted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && __clang_major__ >= 18
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
|
||||
defined(__TARGET_ARCH_s390)) && __clang_major__ >= 18
|
||||
const volatile int skip = 0;
|
||||
#else
|
||||
const volatile int skip = 1;
|
||||
|
@ -104,7 +105,11 @@ int _tc(volatile struct __sk_buff *skb)
|
|||
"%[tmp_mark] = r1"
|
||||
: [tmp_mark]"=r"(tmp_mark)
|
||||
: [ctx]"r"(skb),
|
||||
[off_mark]"i"(offsetof(struct __sk_buff, mark))
|
||||
[off_mark]"i"(offsetof(struct __sk_buff, mark)
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
+ sizeof(skb->mark) - 1
|
||||
#endif
|
||||
)
|
||||
: "r1");
|
||||
#else
|
||||
tmp_mark = (char)skb->mark;
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include "bpf_misc.h"
|
||||
|
||||
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || defined(__TARGET_ARCH_arm)) && \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
|
||||
defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \
|
||||
__clang_major__ >= 18
|
||||
|
||||
SEC("socket")
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include "bpf_misc.h"
|
||||
|
||||
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || defined(__TARGET_ARCH_arm)) && \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
|
||||
defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \
|
||||
__clang_major__ >= 18
|
||||
|
||||
SEC("socket")
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include "bpf_misc.h"
|
||||
|
||||
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || defined(__TARGET_ARCH_arm)) && \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
|
||||
defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \
|
||||
__clang_major__ >= 18
|
||||
|
||||
SEC("socket")
|
||||
|
@ -13,12 +14,16 @@ __description("LDSX, S8")
|
|||
__success __success_unpriv __retval(-2)
|
||||
__naked void ldsx_s8(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r1 = 0x3fe; \
|
||||
*(u64 *)(r10 - 8) = r1; \
|
||||
r0 = *(s8 *)(r10 - 8); \
|
||||
exit; \
|
||||
" ::: __clobber_all);
|
||||
asm volatile (
|
||||
"r1 = 0x3fe;"
|
||||
"*(u64 *)(r10 - 8) = r1;"
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
"r0 = *(s8 *)(r10 - 8);"
|
||||
#else
|
||||
"r0 = *(s8 *)(r10 - 1);"
|
||||
#endif
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("socket")
|
||||
|
@ -26,12 +31,16 @@ __description("LDSX, S16")
|
|||
__success __success_unpriv __retval(-2)
|
||||
__naked void ldsx_s16(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r1 = 0x3fffe; \
|
||||
*(u64 *)(r10 - 8) = r1; \
|
||||
r0 = *(s16 *)(r10 - 8); \
|
||||
exit; \
|
||||
" ::: __clobber_all);
|
||||
asm volatile (
|
||||
"r1 = 0x3fffe;"
|
||||
"*(u64 *)(r10 - 8) = r1;"
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
"r0 = *(s16 *)(r10 - 8);"
|
||||
#else
|
||||
"r0 = *(s16 *)(r10 - 2);"
|
||||
#endif
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("socket")
|
||||
|
@ -39,13 +48,17 @@ __description("LDSX, S32")
|
|||
__success __success_unpriv __retval(-1)
|
||||
__naked void ldsx_s32(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r1 = 0xfffffffe; \
|
||||
*(u64 *)(r10 - 8) = r1; \
|
||||
r0 = *(s32 *)(r10 - 8); \
|
||||
r0 >>= 1; \
|
||||
exit; \
|
||||
" ::: __clobber_all);
|
||||
asm volatile (
|
||||
"r1 = 0xfffffffe;"
|
||||
"*(u64 *)(r10 - 8) = r1;"
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
"r0 = *(s32 *)(r10 - 8);"
|
||||
#else
|
||||
"r0 = *(s32 *)(r10 - 4);"
|
||||
#endif
|
||||
"r0 >>= 1;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("socket")
|
||||
|
@ -54,20 +67,24 @@ __log_level(2) __success __retval(1)
|
|||
__msg("R1_w=scalar(smin=-128,smax=127)")
|
||||
__naked void ldsx_s8_range_priv(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
*(u64 *)(r10 - 8) = r0; \
|
||||
r1 = *(s8 *)(r10 - 8); \
|
||||
/* r1 with s8 range */ \
|
||||
if r1 s> 0x7f goto l0_%=; \
|
||||
if r1 s< -0x80 goto l0_%=; \
|
||||
r0 = 1; \
|
||||
l1_%=: \
|
||||
exit; \
|
||||
l0_%=: \
|
||||
r0 = 2; \
|
||||
goto l1_%=; \
|
||||
" :
|
||||
asm volatile (
|
||||
"call %[bpf_get_prandom_u32];"
|
||||
"*(u64 *)(r10 - 8) = r0;"
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
"r1 = *(s8 *)(r10 - 8);"
|
||||
#else
|
||||
"r1 = *(s8 *)(r10 - 1);"
|
||||
#endif
|
||||
/* r1 with s8 range */
|
||||
"if r1 s> 0x7f goto l0_%=;"
|
||||
"if r1 s< -0x80 goto l0_%=;"
|
||||
"r0 = 1;"
|
||||
"l1_%=:"
|
||||
"exit;"
|
||||
"l0_%=:"
|
||||
"r0 = 2;"
|
||||
"goto l1_%=;"
|
||||
:
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
@ -77,20 +94,24 @@ __description("LDSX, S16 range checking")
|
|||
__success __success_unpriv __retval(1)
|
||||
__naked void ldsx_s16_range(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
*(u64 *)(r10 - 8) = r0; \
|
||||
r1 = *(s16 *)(r10 - 8); \
|
||||
/* r1 with s16 range */ \
|
||||
if r1 s> 0x7fff goto l0_%=; \
|
||||
if r1 s< -0x8000 goto l0_%=; \
|
||||
r0 = 1; \
|
||||
l1_%=: \
|
||||
exit; \
|
||||
l0_%=: \
|
||||
r0 = 2; \
|
||||
goto l1_%=; \
|
||||
" :
|
||||
asm volatile (
|
||||
"call %[bpf_get_prandom_u32];"
|
||||
"*(u64 *)(r10 - 8) = r0;"
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
"r1 = *(s16 *)(r10 - 8);"
|
||||
#else
|
||||
"r1 = *(s16 *)(r10 - 2);"
|
||||
#endif
|
||||
/* r1 with s16 range */
|
||||
"if r1 s> 0x7fff goto l0_%=;"
|
||||
"if r1 s< -0x8000 goto l0_%=;"
|
||||
"r0 = 1;"
|
||||
"l1_%=:"
|
||||
"exit;"
|
||||
"l0_%=:"
|
||||
"r0 = 2;"
|
||||
"goto l1_%=;"
|
||||
:
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
@ -100,20 +121,24 @@ __description("LDSX, S32 range checking")
|
|||
__success __success_unpriv __retval(1)
|
||||
__naked void ldsx_s32_range(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
*(u64 *)(r10 - 8) = r0; \
|
||||
r1 = *(s32 *)(r10 - 8); \
|
||||
/* r1 with s16 range */ \
|
||||
if r1 s> 0x7fffFFFF goto l0_%=; \
|
||||
if r1 s< -0x80000000 goto l0_%=; \
|
||||
r0 = 1; \
|
||||
l1_%=: \
|
||||
exit; \
|
||||
l0_%=: \
|
||||
r0 = 2; \
|
||||
goto l1_%=; \
|
||||
" :
|
||||
asm volatile (
|
||||
"call %[bpf_get_prandom_u32];"
|
||||
"*(u64 *)(r10 - 8) = r0;"
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
"r1 = *(s32 *)(r10 - 8);"
|
||||
#else
|
||||
"r1 = *(s32 *)(r10 - 4);"
|
||||
#endif
|
||||
/* r1 with s16 range */
|
||||
"if r1 s> 0x7fffFFFF goto l0_%=;"
|
||||
"if r1 s< -0x80000000 goto l0_%=;"
|
||||
"r0 = 1;"
|
||||
"l1_%=:"
|
||||
"exit;"
|
||||
"l0_%=:"
|
||||
"r0 = 2;"
|
||||
"goto l1_%=;"
|
||||
:
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include "bpf_misc.h"
|
||||
|
||||
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || defined(__TARGET_ARCH_arm)) && \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
|
||||
defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \
|
||||
__clang_major__ >= 18
|
||||
|
||||
SEC("socket")
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include "bpf_misc.h"
|
||||
|
||||
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || defined(__TARGET_ARCH_arm)) && \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
|
||||
defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \
|
||||
__clang_major__ >= 18
|
||||
|
||||
SEC("socket")
|
||||
|
|
Loading…
Reference in New Issue