Commit 717756c9 authored by Artem Savkov's avatar Artem Savkov Committed by Michael Ellerman
Browse files

powerpc64/bpf: jit support for sign extended load



Add jit support for sign extended load. Tested using test_bpf module.

Signed-off-by: default avatarArtem Savkov <asavkov@redhat.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20240517075650.248801-4-asavkov@redhat.com
parent a71c0b09
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -471,6 +471,7 @@
#define PPC_RAW_VCMPEQUB_RC(vrt, vra, vrb) \
	(0x10000006 | ___PPC_RT(vrt) | ___PPC_RA(vra) | ___PPC_RB(vrb) | __PPC_RC21)
#define PPC_RAW_LD(r, base, i)		(0xe8000000 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_DS(i))
#define PPC_RAW_LWA(r, base, i)		(0xe8000002 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_DS(i))
#define PPC_RAW_LWZ(r, base, i)		(0x80000000 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
#define PPC_RAW_LWZX(t, a, b)		(0x7c00002e | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b))
#define PPC_RAW_STD(r, base, i)		(0xf8000000 | ___PPC_RS(r) | ___PPC_RA(base) | IMM_DS(i))
+42 −19
Original line number Diff line number Diff line
@@ -937,13 +937,19 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
		 */
		/* dst = *(u8 *)(ul) (src + off) */
		case BPF_LDX | BPF_MEM | BPF_B:
		case BPF_LDX | BPF_MEMSX | BPF_B:
		case BPF_LDX | BPF_PROBE_MEM | BPF_B:
		case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
		/* dst = *(u16 *)(ul) (src + off) */
		case BPF_LDX | BPF_MEM | BPF_H:
		case BPF_LDX | BPF_MEMSX | BPF_H:
		case BPF_LDX | BPF_PROBE_MEM | BPF_H:
		case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
		/* dst = *(u32 *)(ul) (src + off) */
		case BPF_LDX | BPF_MEM | BPF_W:
		case BPF_LDX | BPF_MEMSX | BPF_W:
		case BPF_LDX | BPF_PROBE_MEM | BPF_W:
		case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
		/* dst = *(u64 *)(ul) (src + off) */
		case BPF_LDX | BPF_MEM | BPF_DW:
		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
@@ -953,7 +959,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
			 * load only if addr is kernel address (see is_kernel_addr()), otherwise
			 * set dst_reg=0 and move on.
			 */
			if (BPF_MODE(code) == BPF_PROBE_MEM) {
			if (BPF_MODE(code) == BPF_PROBE_MEM || BPF_MODE(code) == BPF_PROBE_MEMSX) {
				EMIT(PPC_RAW_ADDI(tmp1_reg, src_reg, off));
				if (IS_ENABLED(CONFIG_PPC_BOOK3E_64))
					PPC_LI64(tmp2_reg, 0x8000000000000000ul);
@@ -966,12 +972,28 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
				 * Check if 'off' is word aligned for BPF_DW, because
				 * we might generate two instructions.
				 */
				if (BPF_SIZE(code) == BPF_DW && (off & 3))
				if ((BPF_SIZE(code) == BPF_DW ||
				    (BPF_SIZE(code) == BPF_B && BPF_MODE(code) == BPF_PROBE_MEMSX)) &&
						(off & 3))
					PPC_JMP((ctx->idx + 3) * 4);
				else
					PPC_JMP((ctx->idx + 2) * 4);
			}

			if (BPF_MODE(code) == BPF_MEMSX || BPF_MODE(code) == BPF_PROBE_MEMSX) {
				switch (size) {
				case BPF_B:
					EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
					EMIT(PPC_RAW_EXTSB(dst_reg, dst_reg));
					break;
				case BPF_H:
					EMIT(PPC_RAW_LHA(dst_reg, src_reg, off));
					break;
				case BPF_W:
					EMIT(PPC_RAW_LWA(dst_reg, src_reg, off));
					break;
				}
			} else {
				switch (size) {
				case BPF_B:
					EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
@@ -991,6 +1013,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
					}
					break;
				}
			}

			if (size != BPF_DW && insn_is_zext(&insn[i + 1]))
				addrs[++i] = ctx->idx * 4;