* [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena
@ 2024-03-26 22:49 Puranjay Mohan
2024-03-26 22:49 ` [PATCH bpf-next v3 1/2] bpf,riscv: Implement PROBE_MEM32 pseudo instructions Puranjay Mohan
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Puranjay Mohan @ 2024-03-26 22:49 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
Björn Töpel, Luke Nelson, Xi Wang, Paul Walmsley,
Palmer Dabbelt, Albert Ou, bpf, linux-riscv, linux-kernel,
Pu Lehui
Cc: puranjay12
Changes in V3
V2: https://lore.kernel.org/bpf/20240325155434.65589-1-puranjay12@gmail.com/
- Use REG_DONT_CLEAR_MARKER in place of DONT_CLEAR as the name.
- Use RV_REG_ZERO for the above as it is guaranteed to be never used in as
dst/src register in BPF LDX/STX/ST instructions.
- Use #define RV_REG_ARENA for RV_REG_S7
Changes in V2
V1: https://lore.kernel.org/bpf/20240323154652.54572-1-puranjay12@gmail.com/
- Used S7 in place of S11 for storing the kernel_vm_start
- Used 17 in place of 16 for DONT_CLEAR marker
- Remove an unused variable
- Removed some misleading information from the commit message.
This series adds the support for PROBE_MEM32 and bpf_addr_space_cast
instructions to the RISCV BPF JIT. These two instructions allow the
enablement of BPF Arena.
All arena related selftests are passing:
root@rv-tester:~/bpf# uname -p
riscv64
root@rv-tester:~/bpf# ./test_progs -a "*arena*"
#3/1 arena_htab/arena_htab_llvm:OK
#3/2 arena_htab/arena_htab_asm:OK
#3 arena_htab:OK
#4/1 arena_list/arena_list_1:OK
#4/2 arena_list/arena_list_1000:OK
#4 arena_list:OK
#434/1 verifier_arena/basic_alloc1:OK
#434/2 verifier_arena/basic_alloc2:OK
#434/3 verifier_arena/basic_alloc3:OK
#434/4 verifier_arena/iter_maps1:OK
#434/5 verifier_arena/iter_maps2:OK
#434/6 verifier_arena/iter_maps3:OK
#434 verifier_arena:OK
Summary: 3/10 PASSED, 0 SKIPPED, 0 FAILED
This feature needs the following two fixes in the bpf/bpf.git to work
properly:
f7f5d1808b1b6 ("bpf: verifier: fix addr_space_cast from as(1) to as(0)")
443574b033876 ("riscv, bpf: Fix kfunc parameters incompatibility between bpf and riscv abi")
There is a lot of code repetition for LDX, STX, and ST. I will be sending a
follow-up patch to refactor these.
Puranjay Mohan (2):
bpf,riscv: Implement PROBE_MEM32 pseudo instructions
bpf,riscv: Implement bpf_addr_space_cast instruction
arch/riscv/net/bpf_jit.h | 2 +
arch/riscv/net/bpf_jit_comp64.c | 205 +++++++++++++++++++++++++++++++-
arch/riscv/net/bpf_jit_core.c | 2 +
3 files changed, 207 insertions(+), 2 deletions(-)
--
2.40.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH bpf-next v3 1/2] bpf,riscv: Implement PROBE_MEM32 pseudo instructions
2024-03-26 22:49 [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena Puranjay Mohan
@ 2024-03-26 22:49 ` Puranjay Mohan
2024-03-27 7:27 ` Pu Lehui
2024-03-26 22:49 ` [PATCH bpf-next v3 2/2] bpf,riscv: Implement bpf_addr_space_cast instruction Puranjay Mohan
2024-03-27 12:23 ` [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena Björn Töpel
2 siblings, 1 reply; 6+ messages in thread
From: Puranjay Mohan @ 2024-03-26 22:49 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
Björn Töpel, Luke Nelson, Xi Wang, Paul Walmsley,
Palmer Dabbelt, Albert Ou, bpf, linux-riscv, linux-kernel,
Pu Lehui
Cc: puranjay12
Add support for [LDX | STX | ST], PROBE_MEM32, [B | H | W | DW]
instructions. They are similar to PROBE_MEM instructions with the
following differences:
- PROBE_MEM32 supports store.
- PROBE_MEM32 relies on the verifier to clear upper 32-bit of the
src/dst register
- PROBE_MEM32 adds 64-bit kern_vm_start address (which is stored in S7
in the prologue). Due to bpf_arena constructions such S7 + reg +
off16 access is guaranteed to be within arena virtual range, so no
address check at run-time.
- S11 is a free callee-saved register, so it is used to store kern_vm_start
- PROBE_MEM32 allows STX and ST. If they fault the store is a nop. When
LDX faults the destination register is zeroed.
To support these on riscv, we do tmp = S7 + src/dst reg and then use
tmp2 as the new src/dst register. This allows us to reuse most of the
code for normal [LDX | STX | ST].
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
---
arch/riscv/net/bpf_jit.h | 1 +
arch/riscv/net/bpf_jit_comp64.c | 191 +++++++++++++++++++++++++++++++-
arch/riscv/net/bpf_jit_core.c | 1 +
3 files changed, 191 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
index f4b6b3b9edda..8a47da08dd9c 100644
--- a/arch/riscv/net/bpf_jit.h
+++ b/arch/riscv/net/bpf_jit.h
@@ -81,6 +81,7 @@ struct rv_jit_context {
int nexentries;
unsigned long flags;
int stack_size;
+ u64 arena_vm_start;
};
/* Convert from ninsns to bytes. */
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 1adf2f39ce59..73726f455f6b 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -18,6 +18,7 @@
#define RV_REG_TCC RV_REG_A6
#define RV_REG_TCC_SAVED RV_REG_S6 /* Store A6 in S6 if program do calls */
+#define RV_REG_ARENA RV_REG_S7 /* For storing arena_vm_start */
static const int regmap[] = {
[BPF_REG_0] = RV_REG_A5,
@@ -255,6 +256,10 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
emit_ld(RV_REG_S6, store_offset, RV_REG_SP, ctx);
store_offset -= 8;
}
+ if (ctx->arena_vm_start) {
+ emit_ld(RV_REG_ARENA, store_offset, RV_REG_SP, ctx);
+ store_offset -= 8;
+ }
emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx);
/* Set return value. */
@@ -548,6 +553,7 @@ static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
#define BPF_FIXUP_REG_MASK GENMASK(31, 27)
+#define REG_DONT_CLEAR_MARKER 0 /* RV_REG_ZERO unused in pt_regmap */
bool ex_handler_bpf(const struct exception_table_entry *ex,
struct pt_regs *regs)
@@ -555,7 +561,8 @@ bool ex_handler_bpf(const struct exception_table_entry *ex,
off_t offset = FIELD_GET(BPF_FIXUP_OFFSET_MASK, ex->fixup);
int regs_offset = FIELD_GET(BPF_FIXUP_REG_MASK, ex->fixup);
- *(unsigned long *)((void *)regs + pt_regmap[regs_offset]) = 0;
+ if (regs_offset != REG_DONT_CLEAR_MARKER)
+ *(unsigned long *)((void *)regs + pt_regmap[regs_offset]) = 0;
regs->epc = (unsigned long)&ex->fixup - offset;
return true;
@@ -572,7 +579,8 @@ static int add_exception_handler(const struct bpf_insn *insn,
off_t fixup_offset;
if (!ctx->insns || !ctx->ro_insns || !ctx->prog->aux->extable ||
- (BPF_MODE(insn->code) != BPF_PROBE_MEM && BPF_MODE(insn->code) != BPF_PROBE_MEMSX))
+ (BPF_MODE(insn->code) != BPF_PROBE_MEM && BPF_MODE(insn->code) != BPF_PROBE_MEMSX &&
+ BPF_MODE(insn->code) != BPF_PROBE_MEM32))
return 0;
if (WARN_ON_ONCE(ctx->nexentries >= ctx->prog->aux->num_exentries))
@@ -1539,6 +1547,11 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
+ /* LDX | PROBE_MEM32: dst = *(unsigned size *)(src + S7 + off)*/
+ case BPF_LDX | BPF_PROBE_MEM32 | BPF_B:
+ case BPF_LDX | BPF_PROBE_MEM32 | BPF_H:
+ case BPF_LDX | BPF_PROBE_MEM32 | BPF_W:
+ case BPF_LDX | BPF_PROBE_MEM32 | BPF_DW:
{
int insn_len, insns_start;
bool sign_ext;
@@ -1546,6 +1559,11 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
sign_ext = BPF_MODE(insn->code) == BPF_MEMSX ||
BPF_MODE(insn->code) == BPF_PROBE_MEMSX;
+ if (BPF_MODE(insn->code) == BPF_PROBE_MEM32) {
+ emit_add(RV_REG_T2, rs, RV_REG_ARENA, ctx);
+ rs = RV_REG_T2;
+ }
+
switch (BPF_SIZE(code)) {
case BPF_B:
if (is_12b_int(off)) {
@@ -1682,6 +1700,88 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
break;
+ case BPF_ST | BPF_PROBE_MEM32 | BPF_B:
+ case BPF_ST | BPF_PROBE_MEM32 | BPF_H:
+ case BPF_ST | BPF_PROBE_MEM32 | BPF_W:
+ case BPF_ST | BPF_PROBE_MEM32 | BPF_DW:
+ {
+ int insn_len, insns_start;
+
+ emit_add(RV_REG_T3, rd, RV_REG_ARENA, ctx);
+ rd = RV_REG_T3;
+
+ /* Load imm to a register then store it */
+ emit_imm(RV_REG_T1, imm, ctx);
+
+ switch (BPF_SIZE(code)) {
+ case BPF_B:
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit(rv_sb(rd, off, RV_REG_T1), ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ emit_imm(RV_REG_T2, off, ctx);
+ emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+ insns_start = ctx->ninsns;
+ emit(rv_sb(RV_REG_T2, 0, RV_REG_T1), ctx);
+ insn_len = ctx->ninsns - insns_start;
+
+ break;
+
+ case BPF_H:
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit(rv_sh(rd, off, RV_REG_T1), ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ emit_imm(RV_REG_T2, off, ctx);
+ emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+ insns_start = ctx->ninsns;
+ emit(rv_sh(RV_REG_T2, 0, RV_REG_T1), ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ case BPF_W:
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit_sw(rd, off, RV_REG_T1, ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ emit_imm(RV_REG_T2, off, ctx);
+ emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+ insns_start = ctx->ninsns;
+ emit_sw(RV_REG_T2, 0, RV_REG_T1, ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ case BPF_DW:
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit_sd(rd, off, RV_REG_T1, ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ emit_imm(RV_REG_T2, off, ctx);
+ emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+ insns_start = ctx->ninsns;
+ emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ ret = add_exception_handler(insn, ctx, REG_DONT_CLEAR_MARKER,
+ insn_len);
+ if (ret)
+ return ret;
+
+ break;
+ }
+
/* STX: *(size *)(dst + off) = src */
case BPF_STX | BPF_MEM | BPF_B:
if (is_12b_int(off)) {
@@ -1728,6 +1828,84 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
emit_atomic(rd, rs, off, imm,
BPF_SIZE(code) == BPF_DW, ctx);
break;
+
+ case BPF_STX | BPF_PROBE_MEM32 | BPF_B:
+ case BPF_STX | BPF_PROBE_MEM32 | BPF_H:
+ case BPF_STX | BPF_PROBE_MEM32 | BPF_W:
+ case BPF_STX | BPF_PROBE_MEM32 | BPF_DW:
+ {
+ int insn_len, insns_start;
+
+ emit_add(RV_REG_T2, rd, RV_REG_ARENA, ctx);
+ rd = RV_REG_T2;
+
+ switch (BPF_SIZE(code)) {
+ case BPF_B:
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit(rv_sb(rd, off, rs), ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ insns_start = ctx->ninsns;
+ emit(rv_sb(RV_REG_T1, 0, rs), ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ case BPF_H:
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit(rv_sh(rd, off, rs), ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ insns_start = ctx->ninsns;
+ emit(rv_sh(RV_REG_T1, 0, rs), ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ case BPF_W:
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit_sw(rd, off, rs, ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ insns_start = ctx->ninsns;
+ emit_sw(RV_REG_T1, 0, rs, ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ case BPF_DW:
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit_sd(rd, off, rs, ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ insns_start = ctx->ninsns;
+ emit_sd(RV_REG_T1, 0, rs, ctx);
+ insn_len = ctx->ninsns - insns_start;
+ break;
+ }
+
+ ret = add_exception_handler(insn, ctx, REG_DONT_CLEAR_MARKER,
+ insn_len);
+ if (ret)
+ return ret;
+
+ break;
+ }
+
default:
pr_err("bpf-jit: unknown opcode %02x\n", code);
return -EINVAL;
@@ -1759,6 +1937,8 @@ void bpf_jit_build_prologue(struct rv_jit_context *ctx, bool is_subprog)
stack_adjust += 8;
if (seen_reg(RV_REG_S6, ctx))
stack_adjust += 8;
+ if (ctx->arena_vm_start)
+ stack_adjust += 8;
stack_adjust = round_up(stack_adjust, 16);
stack_adjust += bpf_stack_adjust;
@@ -1810,6 +1990,10 @@ void bpf_jit_build_prologue(struct rv_jit_context *ctx, bool is_subprog)
emit_sd(RV_REG_SP, store_offset, RV_REG_S6, ctx);
store_offset -= 8;
}
+ if (ctx->arena_vm_start) {
+ emit_sd(RV_REG_SP, store_offset, RV_REG_ARENA, ctx);
+ store_offset -= 8;
+ }
emit_addi(RV_REG_FP, RV_REG_SP, stack_adjust, ctx);
@@ -1823,6 +2007,9 @@ void bpf_jit_build_prologue(struct rv_jit_context *ctx, bool is_subprog)
emit_mv(RV_REG_TCC_SAVED, RV_REG_TCC, ctx);
ctx->stack_size = stack_adjust;
+
+ if (ctx->arena_vm_start)
+ emit_imm(RV_REG_ARENA, ctx->arena_vm_start, ctx);
}
void bpf_jit_build_epilogue(struct rv_jit_context *ctx)
diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
index 6b3acac30c06..9ab739b9f9a2 100644
--- a/arch/riscv/net/bpf_jit_core.c
+++ b/arch/riscv/net/bpf_jit_core.c
@@ -80,6 +80,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
goto skip_init_ctx;
}
+ ctx->arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena);
ctx->prog = prog;
ctx->offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
if (!ctx->offset) {
--
2.40.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH bpf-next v3 2/2] bpf,riscv: Implement bpf_addr_space_cast instruction
2024-03-26 22:49 [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena Puranjay Mohan
2024-03-26 22:49 ` [PATCH bpf-next v3 1/2] bpf,riscv: Implement PROBE_MEM32 pseudo instructions Puranjay Mohan
@ 2024-03-26 22:49 ` Puranjay Mohan
2024-03-27 7:28 ` Pu Lehui
2024-03-27 12:23 ` [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena Björn Töpel
2 siblings, 1 reply; 6+ messages in thread
From: Puranjay Mohan @ 2024-03-26 22:49 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
Björn Töpel, Luke Nelson, Xi Wang, Paul Walmsley,
Palmer Dabbelt, Albert Ou, bpf, linux-riscv, linux-kernel,
Pu Lehui
Cc: puranjay12
LLVM generates bpf_addr_space_cast instruction while translating
pointers between native (zero) address space and
__attribute__((address_space(N))). The addr_space=0 is reserved as
bpf_arena address space.
rY = addr_space_cast(rX, 0, 1) is processed by the verifier and
converted to normal 32-bit move: wX = wY
rY = addr_space_cast(rX, 1, 0) has to be converted by JIT.
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
---
arch/riscv/net/bpf_jit.h | 1 +
arch/riscv/net/bpf_jit_comp64.c | 14 ++++++++++++++
arch/riscv/net/bpf_jit_core.c | 1 +
3 files changed, 16 insertions(+)
diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
index 8a47da08dd9c..5fc374ed98ea 100644
--- a/arch/riscv/net/bpf_jit.h
+++ b/arch/riscv/net/bpf_jit.h
@@ -82,6 +82,7 @@ struct rv_jit_context {
unsigned long flags;
int stack_size;
u64 arena_vm_start;
+ u64 user_vm_start;
};
/* Convert from ninsns to bytes. */
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 73726f455f6b..77ea306452d4 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -1081,6 +1081,15 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
/* dst = src */
case BPF_ALU | BPF_MOV | BPF_X:
case BPF_ALU64 | BPF_MOV | BPF_X:
+ if (insn_is_cast_user(insn)) {
+ emit_mv(RV_REG_T1, rs, ctx);
+ emit_zextw(RV_REG_T1, RV_REG_T1, ctx);
+ emit_imm(rd, (ctx->user_vm_start >> 32) << 32, ctx);
+ emit(rv_beq(RV_REG_T1, RV_REG_ZERO, 4), ctx);
+ emit_or(RV_REG_T1, rd, RV_REG_T1, ctx);
+ emit_mv(rd, RV_REG_T1, ctx);
+ break;
+ }
if (imm == 1) {
/* Special mov32 for zext */
emit_zextw(rd, rd, ctx);
@@ -2026,3 +2035,8 @@ bool bpf_jit_supports_ptr_xchg(void)
{
return true;
}
+
+bool bpf_jit_supports_arena(void)
+{
+ return true;
+}
diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
index 9ab739b9f9a2..8a69d6d81e32 100644
--- a/arch/riscv/net/bpf_jit_core.c
+++ b/arch/riscv/net/bpf_jit_core.c
@@ -81,6 +81,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
}
ctx->arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena);
+ ctx->user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
ctx->prog = prog;
ctx->offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
if (!ctx->offset) {
--
2.40.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v3 1/2] bpf,riscv: Implement PROBE_MEM32 pseudo instructions
2024-03-26 22:49 ` [PATCH bpf-next v3 1/2] bpf,riscv: Implement PROBE_MEM32 pseudo instructions Puranjay Mohan
@ 2024-03-27 7:27 ` Pu Lehui
0 siblings, 0 replies; 6+ messages in thread
From: Pu Lehui @ 2024-03-27 7:27 UTC (permalink / raw)
To: Puranjay Mohan
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
Björn Töpel, Luke Nelson, Xi Wang, Paul Walmsley,
Palmer Dabbelt, Albert Ou, bpf, linux-riscv, linux-kernel
On 2024/3/27 6:49, Puranjay Mohan wrote:
> Add support for [LDX | STX | ST], PROBE_MEM32, [B | H | W | DW]
[SNIP]
> if (WARN_ON_ONCE(ctx->nexentries >= ctx->prog->aux->num_exentries))
> @@ -1539,6 +1547,11 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
> case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
> case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
> + /* LDX | PROBE_MEM32: dst = *(unsigned size *)(src + S7 + off)*/
still some nits. please align, change S7 here to reg_arena.
> + case BPF_LDX | BPF_PROBE_MEM32 | BPF_B:
> + case BPF_LDX | BPF_PROBE_MEM32 | BPF_H:
> + case BPF_LDX | BPF_PROBE_MEM32 | BPF_W:
> + case BPF_LDX | BPF_PROBE_MEM32 | BPF_DW:
[SNIP]
> +
> + switch (BPF_SIZE(code)) {
> + case BPF_B:
> + if (is_12b_int(off)) {
> + insns_start = ctx->ninsns;
> + emit(rv_sb(rd, off, RV_REG_T1), ctx);
> + insn_len = ctx->ninsns - insns_start;
> + break;
> + }
> +
> + emit_imm(RV_REG_T2, off, ctx);
> + emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
> + insns_start = ctx->ninsns;
> + emit(rv_sb(RV_REG_T2, 0, RV_REG_T1), ctx);
> + insn_len = ctx->ninsns - insns_start;
> +
redundant blank.
> + break;
> +
ditto.
Others, looks good to me.
Reviewed-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Pu Lehui <pulehui@huawei.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v3 2/2] bpf,riscv: Implement bpf_addr_space_cast instruction
2024-03-26 22:49 ` [PATCH bpf-next v3 2/2] bpf,riscv: Implement bpf_addr_space_cast instruction Puranjay Mohan
@ 2024-03-27 7:28 ` Pu Lehui
0 siblings, 0 replies; 6+ messages in thread
From: Pu Lehui @ 2024-03-27 7:28 UTC (permalink / raw)
To: Puranjay Mohan
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
Björn Töpel, Luke Nelson, Xi Wang, Paul Walmsley,
Palmer Dabbelt, Albert Ou, bpf, linux-riscv, linux-kernel
On 2024/3/27 6:49, Puranjay Mohan wrote:
> LLVM generates bpf_addr_space_cast instruction while translating
> pointers between native (zero) address space and
> __attribute__((address_space(N))). The addr_space=0 is reserved as
> bpf_arena address space.
>
> rY = addr_space_cast(rX, 0, 1) is processed by the verifier and
> converted to normal 32-bit move: wX = wY
>
> rY = addr_space_cast(rX, 1, 0) has to be converted by JIT.
>
> Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
> ---
> arch/riscv/net/bpf_jit.h | 1 +
> arch/riscv/net/bpf_jit_comp64.c | 14 ++++++++++++++
> arch/riscv/net/bpf_jit_core.c | 1 +
> 3 files changed, 16 insertions(+)
>
> diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
> index 8a47da08dd9c..5fc374ed98ea 100644
> --- a/arch/riscv/net/bpf_jit.h
> +++ b/arch/riscv/net/bpf_jit.h
> @@ -82,6 +82,7 @@ struct rv_jit_context {
> unsigned long flags;
> int stack_size;
> u64 arena_vm_start;
> + u64 user_vm_start;
> };
>
> /* Convert from ninsns to bytes. */
> diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
> index 73726f455f6b..77ea306452d4 100644
> --- a/arch/riscv/net/bpf_jit_comp64.c
> +++ b/arch/riscv/net/bpf_jit_comp64.c
> @@ -1081,6 +1081,15 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> /* dst = src */
> case BPF_ALU | BPF_MOV | BPF_X:
> case BPF_ALU64 | BPF_MOV | BPF_X:
> + if (insn_is_cast_user(insn)) {
> + emit_mv(RV_REG_T1, rs, ctx);
> + emit_zextw(RV_REG_T1, RV_REG_T1, ctx);
> + emit_imm(rd, (ctx->user_vm_start >> 32) << 32, ctx);
> + emit(rv_beq(RV_REG_T1, RV_REG_ZERO, 4), ctx);
> + emit_or(RV_REG_T1, rd, RV_REG_T1, ctx);
> + emit_mv(rd, RV_REG_T1, ctx);
> + break;
> + }
> if (imm == 1) {
> /* Special mov32 for zext */
> emit_zextw(rd, rd, ctx);
> @@ -2026,3 +2035,8 @@ bool bpf_jit_supports_ptr_xchg(void)
> {
> return true;
> }
> +
> +bool bpf_jit_supports_arena(void)
> +{
> + return true;
> +}
> diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
> index 9ab739b9f9a2..8a69d6d81e32 100644
> --- a/arch/riscv/net/bpf_jit_core.c
> +++ b/arch/riscv/net/bpf_jit_core.c
> @@ -81,6 +81,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> }
>
> ctx->arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena);
> + ctx->user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
> ctx->prog = prog;
> ctx->offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
> if (!ctx->offset) {
Reviewed-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Pu Lehui <pulehui@huawei.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena
2024-03-26 22:49 [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena Puranjay Mohan
2024-03-26 22:49 ` [PATCH bpf-next v3 1/2] bpf,riscv: Implement PROBE_MEM32 pseudo instructions Puranjay Mohan
2024-03-26 22:49 ` [PATCH bpf-next v3 2/2] bpf,riscv: Implement bpf_addr_space_cast instruction Puranjay Mohan
@ 2024-03-27 12:23 ` Björn Töpel
2 siblings, 0 replies; 6+ messages in thread
From: Björn Töpel @ 2024-03-27 12:23 UTC (permalink / raw)
To: Puranjay Mohan
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
Luke Nelson, Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
bpf, linux-riscv, linux-kernel, Pu Lehui
On Tue, 26 Mar 2024 at 23:49, Puranjay Mohan <puranjay12@gmail.com> wrote:
>
> Changes in V3
> V2: https://lore.kernel.org/bpf/20240325155434.65589-1-puranjay12@gmail.com/
> - Use REG_DONT_CLEAR_MARKER in place of DONT_CLEAR as the name.
> - Use RV_REG_ZERO for the above as it is guaranteed to be never used in as
> dst/src register in BPF LDX/STX/ST instructions.
> - Use #define RV_REG_ARENA for RV_REG_S7
>
> Changes in V2
> V1: https://lore.kernel.org/bpf/20240323154652.54572-1-puranjay12@gmail.com/
> - Used S7 in place of S11 for storing the kernel_vm_start
> - Used 17 in place of 16 for DONT_CLEAR marker
> - Remove an unused variable
> - Removed some misleading information from the commit message.
>
> This series adds the support for PROBE_MEM32 and bpf_addr_space_cast
> instructions to the RISCV BPF JIT. These two instructions allow the
> enablement of BPF Arena.
>
> All arena related selftests are passing:
>
> root@rv-tester:~/bpf# uname -p
> riscv64
> root@rv-tester:~/bpf# ./test_progs -a "*arena*"
> #3/1 arena_htab/arena_htab_llvm:OK
> #3/2 arena_htab/arena_htab_asm:OK
> #3 arena_htab:OK
> #4/1 arena_list/arena_list_1:OK
> #4/2 arena_list/arena_list_1000:OK
> #4 arena_list:OK
> #434/1 verifier_arena/basic_alloc1:OK
> #434/2 verifier_arena/basic_alloc2:OK
> #434/3 verifier_arena/basic_alloc3:OK
> #434/4 verifier_arena/iter_maps1:OK
> #434/5 verifier_arena/iter_maps2:OK
> #434/6 verifier_arena/iter_maps3:OK
> #434 verifier_arena:OK
> Summary: 3/10 PASSED, 0 SKIPPED, 0 FAILED
>
> This feature needs the following two fixes in the bpf/bpf.git to work
> properly:
>
> f7f5d1808b1b6 ("bpf: verifier: fix addr_space_cast from as(1) to as(0)")
> 443574b033876 ("riscv, bpf: Fix kfunc parameters incompatibility between bpf and riscv abi")
>
> There is a lot of code repetition for LDX, STX, and ST. I will be sending a
> follow-up patch to refactor these.
Thank you, and please address Lehui's remarks as well.
For the series:
Tested-by: Björn Töpel <bjorn@rivosinc.com>
Acked-by: Björn Töpel <bjorn@kernel.org>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-03-27 12:24 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-26 22:49 [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena Puranjay Mohan
2024-03-26 22:49 ` [PATCH bpf-next v3 1/2] bpf,riscv: Implement PROBE_MEM32 pseudo instructions Puranjay Mohan
2024-03-27 7:27 ` Pu Lehui
2024-03-26 22:49 ` [PATCH bpf-next v3 2/2] bpf,riscv: Implement bpf_addr_space_cast instruction Puranjay Mohan
2024-03-27 7:28 ` Pu Lehui
2024-03-27 12:23 ` [PATCH bpf-next v3 0/2] bpf,riscv: Add support for BPF Arena Björn Töpel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox