bpf, arm64: Support sign-extension load instructions
Add JIT support for sign-extension load instructions. Signed-off-by: Xu Kuohai <xukuohai@huawei.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Tested-by: Florent Revest <revest@chromium.org> Acked-by: Florent Revest <revest@chromium.org> Link: https://lore.kernel.org/bpf/20230815154158.717901-3-xukuohai@huaweicloud.com
This commit is contained in:
parent
6c9f86d363
commit
cc88f540da
@ -59,10 +59,13 @@
|
|||||||
AARCH64_INSN_LDST_##type##_REG_OFFSET)
|
AARCH64_INSN_LDST_##type##_REG_OFFSET)
|
||||||
#define A64_STRB(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 8, STORE)
|
#define A64_STRB(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 8, STORE)
|
||||||
#define A64_LDRB(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 8, LOAD)
|
#define A64_LDRB(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 8, LOAD)
|
||||||
|
#define A64_LDRSB(Xt, Xn, Xm) A64_LS_REG(Xt, Xn, Xm, 8, SIGNED_LOAD)
|
||||||
#define A64_STRH(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 16, STORE)
|
#define A64_STRH(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 16, STORE)
|
||||||
#define A64_LDRH(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 16, LOAD)
|
#define A64_LDRH(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 16, LOAD)
|
||||||
|
#define A64_LDRSH(Xt, Xn, Xm) A64_LS_REG(Xt, Xn, Xm, 16, SIGNED_LOAD)
|
||||||
#define A64_STR32(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 32, STORE)
|
#define A64_STR32(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 32, STORE)
|
||||||
#define A64_LDR32(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 32, LOAD)
|
#define A64_LDR32(Wt, Xn, Xm) A64_LS_REG(Wt, Xn, Xm, 32, LOAD)
|
||||||
|
#define A64_LDRSW(Xt, Xn, Xm) A64_LS_REG(Xt, Xn, Xm, 32, SIGNED_LOAD)
|
||||||
#define A64_STR64(Xt, Xn, Xm) A64_LS_REG(Xt, Xn, Xm, 64, STORE)
|
#define A64_STR64(Xt, Xn, Xm) A64_LS_REG(Xt, Xn, Xm, 64, STORE)
|
||||||
#define A64_LDR64(Xt, Xn, Xm) A64_LS_REG(Xt, Xn, Xm, 64, LOAD)
|
#define A64_LDR64(Xt, Xn, Xm) A64_LS_REG(Xt, Xn, Xm, 64, LOAD)
|
||||||
|
|
||||||
@ -73,10 +76,13 @@
|
|||||||
AARCH64_INSN_LDST_##type##_IMM_OFFSET)
|
AARCH64_INSN_LDST_##type##_IMM_OFFSET)
|
||||||
#define A64_STRBI(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 8, STORE)
|
#define A64_STRBI(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 8, STORE)
|
||||||
#define A64_LDRBI(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 8, LOAD)
|
#define A64_LDRBI(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 8, LOAD)
|
||||||
|
#define A64_LDRSBI(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 8, SIGNED_LOAD)
|
||||||
#define A64_STRHI(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 16, STORE)
|
#define A64_STRHI(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 16, STORE)
|
||||||
#define A64_LDRHI(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 16, LOAD)
|
#define A64_LDRHI(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 16, LOAD)
|
||||||
|
#define A64_LDRSHI(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 16, SIGNED_LOAD)
|
||||||
#define A64_STR32I(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 32, STORE)
|
#define A64_STR32I(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 32, STORE)
|
||||||
#define A64_LDR32I(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 32, LOAD)
|
#define A64_LDR32I(Wt, Xn, imm) A64_LS_IMM(Wt, Xn, imm, 32, LOAD)
|
||||||
|
#define A64_LDRSWI(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 32, SIGNED_LOAD)
|
||||||
#define A64_STR64I(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 64, STORE)
|
#define A64_STR64I(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 64, STORE)
|
||||||
#define A64_LDR64I(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 64, LOAD)
|
#define A64_LDR64I(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 64, LOAD)
|
||||||
|
|
||||||
|
@ -715,7 +715,8 @@ static int add_exception_handler(const struct bpf_insn *insn,
|
|||||||
/* First pass */
|
/* First pass */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (BPF_MODE(insn->code) != BPF_PROBE_MEM)
|
if (BPF_MODE(insn->code) != BPF_PROBE_MEM &&
|
||||||
|
BPF_MODE(insn->code) != BPF_PROBE_MEMSX)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!ctx->prog->aux->extable ||
|
if (!ctx->prog->aux->extable ||
|
||||||
@ -779,6 +780,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
|||||||
u8 dst_adj;
|
u8 dst_adj;
|
||||||
int off_adj;
|
int off_adj;
|
||||||
int ret;
|
int ret;
|
||||||
|
bool sign_extend;
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
/* dst = src */
|
/* dst = src */
|
||||||
@ -1122,7 +1124,7 @@ emit_cond_jmp:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LDX: dst = *(size *)(src + off) */
|
/* LDX: dst = (u64)*(unsigned size *)(src + off) */
|
||||||
case BPF_LDX | BPF_MEM | BPF_W:
|
case BPF_LDX | BPF_MEM | BPF_W:
|
||||||
case BPF_LDX | BPF_MEM | BPF_H:
|
case BPF_LDX | BPF_MEM | BPF_H:
|
||||||
case BPF_LDX | BPF_MEM | BPF_B:
|
case BPF_LDX | BPF_MEM | BPF_B:
|
||||||
@ -1131,6 +1133,13 @@ emit_cond_jmp:
|
|||||||
case BPF_LDX | BPF_PROBE_MEM | BPF_W:
|
case BPF_LDX | BPF_PROBE_MEM | BPF_W:
|
||||||
case BPF_LDX | BPF_PROBE_MEM | BPF_H:
|
case BPF_LDX | BPF_PROBE_MEM | BPF_H:
|
||||||
case BPF_LDX | BPF_PROBE_MEM | BPF_B:
|
case BPF_LDX | BPF_PROBE_MEM | BPF_B:
|
||||||
|
/* LDXS: dst_reg = (s64)*(signed size *)(src_reg + off) */
|
||||||
|
case BPF_LDX | BPF_MEMSX | BPF_B:
|
||||||
|
case BPF_LDX | BPF_MEMSX | BPF_H:
|
||||||
|
case BPF_LDX | BPF_MEMSX | BPF_W:
|
||||||
|
case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
|
||||||
|
case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
|
||||||
|
case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
|
||||||
if (ctx->fpb_offset > 0 && src == fp) {
|
if (ctx->fpb_offset > 0 && src == fp) {
|
||||||
src_adj = fpb;
|
src_adj = fpb;
|
||||||
off_adj = off + ctx->fpb_offset;
|
off_adj = off + ctx->fpb_offset;
|
||||||
@ -1138,29 +1147,49 @@ emit_cond_jmp:
|
|||||||
src_adj = src;
|
src_adj = src;
|
||||||
off_adj = off;
|
off_adj = off;
|
||||||
}
|
}
|
||||||
|
sign_extend = (BPF_MODE(insn->code) == BPF_MEMSX ||
|
||||||
|
BPF_MODE(insn->code) == BPF_PROBE_MEMSX);
|
||||||
switch (BPF_SIZE(code)) {
|
switch (BPF_SIZE(code)) {
|
||||||
case BPF_W:
|
case BPF_W:
|
||||||
if (is_lsi_offset(off_adj, 2)) {
|
if (is_lsi_offset(off_adj, 2)) {
|
||||||
emit(A64_LDR32I(dst, src_adj, off_adj), ctx);
|
if (sign_extend)
|
||||||
|
emit(A64_LDRSWI(dst, src_adj, off_adj), ctx);
|
||||||
|
else
|
||||||
|
emit(A64_LDR32I(dst, src_adj, off_adj), ctx);
|
||||||
} else {
|
} else {
|
||||||
emit_a64_mov_i(1, tmp, off, ctx);
|
emit_a64_mov_i(1, tmp, off, ctx);
|
||||||
emit(A64_LDR32(dst, src, tmp), ctx);
|
if (sign_extend)
|
||||||
|
emit(A64_LDRSW(dst, src_adj, off_adj), ctx);
|
||||||
|
else
|
||||||
|
emit(A64_LDR32(dst, src, tmp), ctx);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BPF_H:
|
case BPF_H:
|
||||||
if (is_lsi_offset(off_adj, 1)) {
|
if (is_lsi_offset(off_adj, 1)) {
|
||||||
emit(A64_LDRHI(dst, src_adj, off_adj), ctx);
|
if (sign_extend)
|
||||||
|
emit(A64_LDRSHI(dst, src_adj, off_adj), ctx);
|
||||||
|
else
|
||||||
|
emit(A64_LDRHI(dst, src_adj, off_adj), ctx);
|
||||||
} else {
|
} else {
|
||||||
emit_a64_mov_i(1, tmp, off, ctx);
|
emit_a64_mov_i(1, tmp, off, ctx);
|
||||||
emit(A64_LDRH(dst, src, tmp), ctx);
|
if (sign_extend)
|
||||||
|
emit(A64_LDRSH(dst, src, tmp), ctx);
|
||||||
|
else
|
||||||
|
emit(A64_LDRH(dst, src, tmp), ctx);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BPF_B:
|
case BPF_B:
|
||||||
if (is_lsi_offset(off_adj, 0)) {
|
if (is_lsi_offset(off_adj, 0)) {
|
||||||
emit(A64_LDRBI(dst, src_adj, off_adj), ctx);
|
if (sign_extend)
|
||||||
|
emit(A64_LDRSBI(dst, src_adj, off_adj), ctx);
|
||||||
|
else
|
||||||
|
emit(A64_LDRBI(dst, src_adj, off_adj), ctx);
|
||||||
} else {
|
} else {
|
||||||
emit_a64_mov_i(1, tmp, off, ctx);
|
emit_a64_mov_i(1, tmp, off, ctx);
|
||||||
emit(A64_LDRB(dst, src, tmp), ctx);
|
if (sign_extend)
|
||||||
|
emit(A64_LDRSB(dst, src, tmp), ctx);
|
||||||
|
else
|
||||||
|
emit(A64_LDRB(dst, src, tmp), ctx);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BPF_DW:
|
case BPF_DW:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user