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

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
...@@ -471,6 +471,7 @@ ...@@ -471,6 +471,7 @@
#define PPC_RAW_VCMPEQUB_RC(vrt, vra, vrb) \ #define PPC_RAW_VCMPEQUB_RC(vrt, vra, vrb) \
(0x10000006 | ___PPC_RT(vrt) | ___PPC_RA(vra) | ___PPC_RB(vrb) | __PPC_RC21) (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_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_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_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)) #define PPC_RAW_STD(r, base, i) (0xf8000000 | ___PPC_RS(r) | ___PPC_RA(base) | IMM_DS(i))
......
...@@ -937,13 +937,19 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code ...@@ -937,13 +937,19 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
*/ */
/* dst = *(u8 *)(ul) (src + off) */ /* dst = *(u8 *)(ul) (src + off) */
case BPF_LDX | BPF_MEM | BPF_B: 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_MEM | BPF_B:
case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
/* dst = *(u16 *)(ul) (src + off) */ /* dst = *(u16 *)(ul) (src + off) */
case BPF_LDX | BPF_MEM | BPF_H: 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_MEM | BPF_H:
case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
/* dst = *(u32 *)(ul) (src + off) */ /* dst = *(u32 *)(ul) (src + off) */
case BPF_LDX | BPF_MEM | BPF_W: 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_MEM | BPF_W:
case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
/* dst = *(u64 *)(ul) (src + off) */ /* dst = *(u64 *)(ul) (src + off) */
case BPF_LDX | BPF_MEM | BPF_DW: case BPF_LDX | BPF_MEM | BPF_DW:
case BPF_LDX | BPF_PROBE_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 ...@@ -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 * load only if addr is kernel address (see is_kernel_addr()), otherwise
* set dst_reg=0 and move on. * 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)); EMIT(PPC_RAW_ADDI(tmp1_reg, src_reg, off));
if (IS_ENABLED(CONFIG_PPC_BOOK3E_64)) if (IS_ENABLED(CONFIG_PPC_BOOK3E_64))
PPC_LI64(tmp2_reg, 0x8000000000000000ul); PPC_LI64(tmp2_reg, 0x8000000000000000ul);
...@@ -966,30 +972,47 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code ...@@ -966,30 +972,47 @@ 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 * Check if 'off' is word aligned for BPF_DW, because
* we might generate two instructions. * 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); PPC_JMP((ctx->idx + 3) * 4);
else else
PPC_JMP((ctx->idx + 2) * 4); PPC_JMP((ctx->idx + 2) * 4);
} }
switch (size) { if (BPF_MODE(code) == BPF_MEMSX || BPF_MODE(code) == BPF_PROBE_MEMSX) {
case BPF_B: switch (size) {
EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off)); case BPF_B:
break; EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
case BPF_H: EMIT(PPC_RAW_EXTSB(dst_reg, dst_reg));
EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off)); break;
break; case BPF_H:
case BPF_W: EMIT(PPC_RAW_LHA(dst_reg, src_reg, off));
EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off)); break;
break; case BPF_W:
case BPF_DW: EMIT(PPC_RAW_LWA(dst_reg, src_reg, off));
if (off % 4) { break;
EMIT(PPC_RAW_LI(tmp1_reg, off)); }
EMIT(PPC_RAW_LDX(dst_reg, src_reg, tmp1_reg)); } else {
} else { switch (size) {
EMIT(PPC_RAW_LD(dst_reg, src_reg, off)); case BPF_B:
EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
break;
case BPF_H:
EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
break;
case BPF_W:
EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
break;
case BPF_DW:
if (off % 4) {
EMIT(PPC_RAW_LI(tmp1_reg, off));
EMIT(PPC_RAW_LDX(dst_reg, src_reg, tmp1_reg));
} else {
EMIT(PPC_RAW_LD(dst_reg, src_reg, off));
}
break;
} }
break;
} }
if (size != BPF_DW && insn_is_zext(&insn[i + 1])) if (size != BPF_DW && insn_is_zext(&insn[i + 1]))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment