Commit 738476a0 authored by Ilya Leoshkevich's avatar Ilya Leoshkevich Committed by Alexei Starovoitov
Browse files

s390/bpf: Implement BPF_MEMSX



Implement the cpuv4 load with sign-extension, which is encoded as
BPF_MEMSX (and, for internal uses cases only, BPF_PROBE_MEMSX).

This is the same as BPF_MEM and BPF_PROBE_MEM, but with sign
extension instead of zero extension, and s390x has the necessary
instructions: lgb, lgh and lgf.

Signed-off-by: default avatarIlya Leoshkevich <iii@linux.ibm.com>
Link: https://lore.kernel.org/r/20230919101336.2223655-6-iii@linux.ibm.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 3de55893
Loading
Loading
Loading
Loading
+27 −5
Original line number Diff line number Diff line
@@ -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;
}
@@ -788,7 +791,8 @@ 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) {
@@ -1406,6 +1410,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) */
@@ -1414,6 +1424,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) */
@@ -1422,6 +1438,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) */