* [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions
@ 2025-05-07 3:42 Peilin Ye
2025-05-07 3:42 ` [PATCH bpf-next v2 1/8] bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno() Peilin Ye
` (9 more replies)
0 siblings, 10 replies; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:42 UTC (permalink / raw)
To: bpf
Cc: Peilin Ye, linux-riscv, Andrea Parri, Björn Töpel,
Pu Lehui, Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall
Hi all!
Patchset [1] introduced BPF load-acquire (BPF_LOAD_ACQ) and
store-release (BPF_STORE_REL) instructions, and added x86-64 and arm64
JIT compiler support. As a follow-up, this v2 patchset supports
load-acquire and store-release instructions for the riscv64 JIT
compiler, and introduces some related selftests/ changes.
Specifically:
* PATCH 1 makes insn_def_regno() handle load-acquires properly for
bpf_jit_needs_zext() (true for riscv64) architectures
* PATCH 2, 3 from Andrea Parri add the actual support to the riscv64
JIT compiler
* PATCH 4 optimizes code emission by skipping redundant zext
instructions inserted by the verifier
* PATCH 5, 6 and 7 are minor selftest/ improvements
* PATCH 8 enables (non-arena) load-acquire/store-release selftests for
riscv64
v1: https://lore.kernel.org/bpf/cover.1745970908.git.yepeilin@google.com/
Changes since v1:
* add Acked-by:, Reviewed-by: and Tested-by: tags from Lehui and Björn
* simplify code logic in PATCH 1 (Lehui)
* in PATCH 3, avoid changing 'return 0;' to 'return ret;' at the end of
bpf_jit_emit_insn() (Lehui)
Please refer to individual patches for details. Thanks!
[1] https://lore.kernel.org/all/cover.1741049567.git.yepeilin@google.com/
Andrea Parri (2):
bpf, riscv64: Introduce emit_load_*() and emit_store_*()
bpf, riscv64: Support load-acquire and store-release instructions
Peilin Ye (6):
bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno()
bpf, riscv64: Skip redundant zext instruction after load-acquire
selftests/bpf: Use CAN_USE_LOAD_ACQ_STORE_REL when appropriate
selftests/bpf: Avoid passing out-of-range values to __retval()
selftests/bpf: Verify zero-extension behavior in load-acquire tests
selftests/bpf: Enable non-arena load-acquire/store-release selftests
for riscv64
arch/riscv/net/bpf_jit.h | 15 +
arch/riscv/net/bpf_jit_comp64.c | 332 ++++++++++++------
arch/riscv/net/bpf_jit_core.c | 3 +-
kernel/bpf/verifier.c | 12 +-
tools/testing/selftests/bpf/progs/bpf_misc.h | 5 +-
.../bpf/progs/verifier_load_acquire.c | 48 ++-
.../selftests/bpf/progs/verifier_precision.c | 5 +-
.../bpf/progs/verifier_store_release.c | 39 +-
8 files changed, 313 insertions(+), 146 deletions(-)
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH bpf-next v2 1/8] bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno()
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
@ 2025-05-07 3:42 ` Peilin Ye
2025-05-07 6:42 ` Pu Lehui
2025-05-07 3:42 ` [PATCH bpf-next v2 2/8] bpf, riscv64: Introduce emit_load_*() and emit_store_*() Peilin Ye
` (8 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:42 UTC (permalink / raw)
To: bpf
Cc: Peilin Ye, linux-riscv, Andrea Parri, Björn Töpel,
Pu Lehui, Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall
In preparation for supporting BPF load-acquire and store-release
instructions for architectures where bpf_jit_needs_zext() returns true
(e.g. riscv64), make insn_def_regno() handle load-acquires properly.
Acked-by: Björn Töpel <bjorn@kernel.org>
Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
Signed-off-by: Peilin Ye <yepeilin@google.com>
---
kernel/bpf/verifier.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 99aa2c890e7b..28f5a7899bd6 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3649,16 +3649,16 @@ static int insn_def_regno(const struct bpf_insn *insn)
case BPF_ST:
return -1;
case BPF_STX:
- if ((BPF_MODE(insn->code) == BPF_ATOMIC ||
- BPF_MODE(insn->code) == BPF_PROBE_ATOMIC) &&
- (insn->imm & BPF_FETCH)) {
+ if (BPF_MODE(insn->code) == BPF_ATOMIC ||
+ BPF_MODE(insn->code) == BPF_PROBE_ATOMIC) {
if (insn->imm == BPF_CMPXCHG)
return BPF_REG_0;
- else
+ else if (insn->imm == BPF_LOAD_ACQ)
+ return insn->dst_reg;
+ else if (insn->imm & BPF_FETCH)
return insn->src_reg;
- } else {
- return -1;
}
+ return -1;
default:
return insn->dst_reg;
}
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH bpf-next v2 2/8] bpf, riscv64: Introduce emit_load_*() and emit_store_*()
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
2025-05-07 3:42 ` [PATCH bpf-next v2 1/8] bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno() Peilin Ye
@ 2025-05-07 3:42 ` Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 3/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:42 UTC (permalink / raw)
To: bpf
Cc: Andrea Parri, linux-riscv, Björn Töpel, Pu Lehui,
Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall, Peilin Ye
From: Andrea Parri <parri.andrea@gmail.com>
We're planning to add support for the load-acquire and store-release
BPF instructions. Define emit_load_<size>() and emit_store_<size>()
to enable/facilitate the (re)use of their code.
Acked-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
Tested-by: Peilin Ye <yepeilin@google.com>
Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
[yepeilin@google.com: cosmetic change to commit title]
Signed-off-by: Peilin Ye <yepeilin@google.com>
---
arch/riscv/net/bpf_jit_comp64.c | 242 +++++++++++++++++++-------------
1 file changed, 143 insertions(+), 99 deletions(-)
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index ca60db75199d..953b6a20c69f 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -473,6 +473,140 @@ static inline void emit_kcfi(u32 hash, struct rv_jit_context *ctx)
emit(hash, ctx);
}
+static int emit_load_8(bool sign_ext, u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+{
+ int insns_start;
+
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ if (sign_ext)
+ emit(rv_lb(rd, off, rs), ctx);
+ else
+ emit(rv_lbu(rd, off, rs), ctx);
+ return ctx->ninsns - insns_start;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
+ insns_start = ctx->ninsns;
+ if (sign_ext)
+ emit(rv_lb(rd, 0, RV_REG_T1), ctx);
+ else
+ emit(rv_lbu(rd, 0, RV_REG_T1), ctx);
+ return ctx->ninsns - insns_start;
+}
+
+static int emit_load_16(bool sign_ext, u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+{
+ int insns_start;
+
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ if (sign_ext)
+ emit(rv_lh(rd, off, rs), ctx);
+ else
+ emit(rv_lhu(rd, off, rs), ctx);
+ return ctx->ninsns - insns_start;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
+ insns_start = ctx->ninsns;
+ if (sign_ext)
+ emit(rv_lh(rd, 0, RV_REG_T1), ctx);
+ else
+ emit(rv_lhu(rd, 0, RV_REG_T1), ctx);
+ return ctx->ninsns - insns_start;
+}
+
+static int emit_load_32(bool sign_ext, u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+{
+ int insns_start;
+
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ if (sign_ext)
+ emit(rv_lw(rd, off, rs), ctx);
+ else
+ emit(rv_lwu(rd, off, rs), ctx);
+ return ctx->ninsns - insns_start;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
+ insns_start = ctx->ninsns;
+ if (sign_ext)
+ emit(rv_lw(rd, 0, RV_REG_T1), ctx);
+ else
+ emit(rv_lwu(rd, 0, RV_REG_T1), ctx);
+ return ctx->ninsns - insns_start;
+}
+
+static int emit_load_64(bool sign_ext, u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+{
+ int insns_start;
+
+ if (is_12b_int(off)) {
+ insns_start = ctx->ninsns;
+ emit_ld(rd, off, rs, ctx);
+ return ctx->ninsns - insns_start;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
+ insns_start = ctx->ninsns;
+ emit_ld(rd, 0, RV_REG_T1, ctx);
+ return ctx->ninsns - insns_start;
+}
+
+static void emit_store_8(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+{
+ if (is_12b_int(off)) {
+ emit(rv_sb(rd, off, rs), ctx);
+ return;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ emit(rv_sb(RV_REG_T1, 0, rs), ctx);
+}
+
+static void emit_store_16(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+{
+ if (is_12b_int(off)) {
+ emit(rv_sh(rd, off, rs), ctx);
+ return;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ emit(rv_sh(RV_REG_T1, 0, rs), ctx);
+}
+
+static void emit_store_32(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+{
+ if (is_12b_int(off)) {
+ emit_sw(rd, off, rs, ctx);
+ return;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ emit_sw(RV_REG_T1, 0, rs, ctx);
+}
+
+static void emit_store_64(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+{
+ if (is_12b_int(off)) {
+ emit_sd(rd, off, rs, ctx);
+ return;
+ }
+
+ emit_imm(RV_REG_T1, off, ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ emit_sd(RV_REG_T1, 0, rs, ctx);
+}
+
static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
struct rv_jit_context *ctx)
{
@@ -1650,8 +1784,8 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
case BPF_LDX | BPF_PROBE_MEM32 | BPF_W:
case BPF_LDX | BPF_PROBE_MEM32 | BPF_DW:
{
- int insn_len, insns_start;
bool sign_ext;
+ int insn_len;
sign_ext = BPF_MODE(insn->code) == BPF_MEMSX ||
BPF_MODE(insn->code) == BPF_PROBE_MEMSX;
@@ -1663,78 +1797,16 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
switch (BPF_SIZE(code)) {
case BPF_B:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lb(rd, off, rs), ctx);
- else
- emit(rv_lbu(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, rs, ctx);
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lb(rd, 0, RV_REG_T1), ctx);
- else
- emit(rv_lbu(rd, 0, RV_REG_T1), ctx);
- insn_len = ctx->ninsns - insns_start;
+ insn_len = emit_load_8(sign_ext, rd, off, rs, ctx);
break;
case BPF_H:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lh(rd, off, rs), ctx);
- else
- emit(rv_lhu(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, rs, ctx);
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lh(rd, 0, RV_REG_T1), ctx);
- else
- emit(rv_lhu(rd, 0, RV_REG_T1), ctx);
- insn_len = ctx->ninsns - insns_start;
+ insn_len = emit_load_16(sign_ext, rd, off, rs, ctx);
break;
case BPF_W:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lw(rd, off, rs), ctx);
- else
- emit(rv_lwu(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, rs, ctx);
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lw(rd, 0, RV_REG_T1), ctx);
- else
- emit(rv_lwu(rd, 0, RV_REG_T1), ctx);
- insn_len = ctx->ninsns - insns_start;
+ insn_len = emit_load_32(sign_ext, rd, off, rs, ctx);
break;
case BPF_DW:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit_ld(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, rs, ctx);
- insns_start = ctx->ninsns;
- emit_ld(rd, 0, RV_REG_T1, ctx);
- insn_len = ctx->ninsns - insns_start;
+ insn_len = emit_load_64(sign_ext, rd, off, rs, ctx);
break;
}
@@ -1879,44 +1951,16 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
/* STX: *(size *)(dst + off) = src */
case BPF_STX | BPF_MEM | BPF_B:
- if (is_12b_int(off)) {
- emit(rv_sb(rd, off, rs), ctx);
- break;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- emit(rv_sb(RV_REG_T1, 0, rs), ctx);
+ emit_store_8(rd, off, rs, ctx);
break;
case BPF_STX | BPF_MEM | BPF_H:
- if (is_12b_int(off)) {
- emit(rv_sh(rd, off, rs), ctx);
- break;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- emit(rv_sh(RV_REG_T1, 0, rs), ctx);
+ emit_store_16(rd, off, rs, ctx);
break;
case BPF_STX | BPF_MEM | BPF_W:
- if (is_12b_int(off)) {
- emit_sw(rd, off, rs, ctx);
- break;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- emit_sw(RV_REG_T1, 0, rs, ctx);
+ emit_store_32(rd, off, rs, ctx);
break;
case BPF_STX | BPF_MEM | BPF_DW:
- if (is_12b_int(off)) {
- emit_sd(rd, off, rs, ctx);
- break;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- emit_sd(RV_REG_T1, 0, rs, ctx);
+ emit_store_64(rd, off, rs, ctx);
break;
case BPF_STX | BPF_ATOMIC | BPF_W:
case BPF_STX | BPF_ATOMIC | BPF_DW:
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH bpf-next v2 3/8] bpf, riscv64: Support load-acquire and store-release instructions
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
2025-05-07 3:42 ` [PATCH bpf-next v2 1/8] bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno() Peilin Ye
2025-05-07 3:42 ` [PATCH bpf-next v2 2/8] bpf, riscv64: Introduce emit_load_*() and emit_store_*() Peilin Ye
@ 2025-05-07 3:43 ` Peilin Ye
2025-05-07 6:42 ` Pu Lehui
2025-05-07 3:43 ` [PATCH bpf-next v2 4/8] bpf, riscv64: Skip redundant zext instruction after load-acquire Peilin Ye
` (6 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:43 UTC (permalink / raw)
To: bpf
Cc: Andrea Parri, linux-riscv, Björn Töpel, Pu Lehui,
Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall, Peilin Ye
From: Andrea Parri <parri.andrea@gmail.com>
Support BPF load-acquire (BPF_LOAD_ACQ) and store-release
(BPF_STORE_REL) instructions in the riscv64 JIT compiler. For example,
consider the following 64-bit load-acquire (assuming little-endian):
db 10 00 00 00 01 00 00 r1 = load_acquire((u64 *)(r1 + 0x0))
95 00 00 00 00 00 00 00 exit
opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX
imm (0x00000100): BPF_LOAD_ACQ
The JIT compiler will emit an LD instruction followed by a FENCE R,RW
instruction for the above, e.g.:
ld x7,0(x6)
fence r,rw
Similarly, consider the following 16-bit store-release:
cb 21 00 00 10 01 00 00 store_release((u16 *)(r1 + 0x0), w2)
95 00 00 00 00 00 00 00 exit
opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX
imm (0x00000110): BPF_STORE_REL
A FENCE RW,W instruction followed by an SH instruction will be emitted,
e.g.:
fence rw,w
sh x2,0(x4)
8-bit and 16-bit load-acquires are zero-extending (cf., LBU, LHU). The
verifier always rejects misaligned load-acquires/store-releases (even if
BPF_F_ANY_ALIGNMENT is set), so the emitted load and store instructions
are guaranteed to be single-copy atomic.
Introduce primitives to emit the relevant (and the most common/used in
the kernel) fences, i.e. fences with R -> RW, RW -> W and RW -> RW.
Rename emit_atomic() to emit_atomic_rmw() to make it clear that it only
handles RMW atomics, and replace its is64 parameter to allow to perform
the required checks on the opsize (BPF_SIZE(code)).
Acked-by: Björn Töpel <bjorn@kernel.org>
Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
Co-developed-by: Peilin Ye <yepeilin@google.com>
Signed-off-by: Peilin Ye <yepeilin@google.com>
---
arch/riscv/net/bpf_jit.h | 15 +++++++
arch/riscv/net/bpf_jit_comp64.c | 75 ++++++++++++++++++++++++++++++---
2 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
index 1d1c78d4cff1..e7b032dfd17f 100644
--- a/arch/riscv/net/bpf_jit.h
+++ b/arch/riscv/net/bpf_jit.h
@@ -608,6 +608,21 @@ static inline u32 rv_fence(u8 pred, u8 succ)
return rv_i_insn(imm11_0, 0, 0, 0, 0xf);
}
+static inline void emit_fence_r_rw(struct rv_jit_context *ctx)
+{
+ emit(rv_fence(0x2, 0x3), ctx);
+}
+
+static inline void emit_fence_rw_w(struct rv_jit_context *ctx)
+{
+ emit(rv_fence(0x3, 0x1), ctx);
+}
+
+static inline void emit_fence_rw_rw(struct rv_jit_context *ctx)
+{
+ emit(rv_fence(0x3, 0x3), ctx);
+}
+
static inline u32 rv_nop(void)
{
return rv_i_insn(0, 0, 0, 0, 0x13);
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 953b6a20c69f..8767f032f2de 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -607,11 +607,65 @@ static void emit_store_64(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
emit_sd(RV_REG_T1, 0, rs, ctx);
}
-static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
- struct rv_jit_context *ctx)
+static int emit_atomic_ld_st(u8 rd, u8 rs, s16 off, s32 imm, u8 code, struct rv_jit_context *ctx)
+{
+ switch (imm) {
+ /* dst_reg = load_acquire(src_reg + off16) */
+ case BPF_LOAD_ACQ:
+ switch (BPF_SIZE(code)) {
+ case BPF_B:
+ emit_load_8(false, rd, off, rs, ctx);
+ break;
+ case BPF_H:
+ emit_load_16(false, rd, off, rs, ctx);
+ break;
+ case BPF_W:
+ emit_load_32(false, rd, off, rs, ctx);
+ break;
+ case BPF_DW:
+ emit_load_64(false, rd, off, rs, ctx);
+ break;
+ }
+ emit_fence_r_rw(ctx);
+ break;
+ /* store_release(dst_reg + off16, src_reg) */
+ case BPF_STORE_REL:
+ emit_fence_rw_w(ctx);
+ switch (BPF_SIZE(code)) {
+ case BPF_B:
+ emit_store_8(rd, off, rs, ctx);
+ break;
+ case BPF_H:
+ emit_store_16(rd, off, rs, ctx);
+ break;
+ case BPF_W:
+ emit_store_32(rd, off, rs, ctx);
+ break;
+ case BPF_DW:
+ emit_store_64(rd, off, rs, ctx);
+ break;
+ }
+ break;
+ default:
+ pr_err_once("bpf-jit: invalid atomic load/store opcode %02x\n", imm);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int emit_atomic_rmw(u8 rd, u8 rs, s16 off, s32 imm, u8 code,
+ struct rv_jit_context *ctx)
{
u8 r0;
int jmp_offset;
+ bool is64;
+
+ if (BPF_SIZE(code) != BPF_W && BPF_SIZE(code) != BPF_DW) {
+ pr_err_once("bpf-jit: 1- and 2-byte RMW atomics are not supported\n");
+ return -EINVAL;
+ }
+ is64 = BPF_SIZE(code) == BPF_DW;
if (off) {
if (is_12b_int(off)) {
@@ -688,9 +742,14 @@ static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
rv_sc_w(RV_REG_T3, rs, rd, 0, 1), ctx);
jmp_offset = ninsns_rvoff(-6);
emit(rv_bne(RV_REG_T3, 0, jmp_offset >> 1), ctx);
- emit(rv_fence(0x3, 0x3), ctx);
+ emit_fence_rw_rw(ctx);
break;
+ default:
+ pr_err_once("bpf-jit: invalid atomic RMW opcode %02x\n", imm);
+ return -EINVAL;
}
+
+ return 0;
}
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
@@ -1962,10 +2021,16 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
case BPF_STX | BPF_MEM | BPF_DW:
emit_store_64(rd, off, rs, ctx);
break;
+ case BPF_STX | BPF_ATOMIC | BPF_B:
+ case BPF_STX | BPF_ATOMIC | BPF_H:
case BPF_STX | BPF_ATOMIC | BPF_W:
case BPF_STX | BPF_ATOMIC | BPF_DW:
- emit_atomic(rd, rs, off, imm,
- BPF_SIZE(code) == BPF_DW, ctx);
+ if (bpf_atomic_is_load_store(insn))
+ ret = emit_atomic_ld_st(rd, rs, off, imm, code, ctx);
+ else
+ ret = emit_atomic_rmw(rd, rs, off, imm, code, ctx);
+ if (ret)
+ return ret;
break;
case BPF_STX | BPF_PROBE_MEM32 | BPF_B:
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH bpf-next v2 4/8] bpf, riscv64: Skip redundant zext instruction after load-acquire
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
` (2 preceding siblings ...)
2025-05-07 3:43 ` [PATCH bpf-next v2 3/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
@ 2025-05-07 3:43 ` Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 5/8] selftests/bpf: Use CAN_USE_LOAD_ACQ_STORE_REL when appropriate Peilin Ye
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:43 UTC (permalink / raw)
To: bpf
Cc: Peilin Ye, linux-riscv, Andrea Parri, Björn Töpel,
Pu Lehui, Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall
Currently, the verifier inserts a zext instruction right after every 8-,
16- or 32-bit load-acquire, which is already zero-extending. Skip such
redundant zext instructions.
While we are here, update that already-obsolete comment about "skip the
next instruction" in build_body(). Also change emit_atomic_rmw()'s
parameters to keep it consistent with emit_atomic_ld_st().
Note that checking 'insn[1]' relies on 'insn' not being the last
instruction, which should have been guaranteed by the verifier; we
already use 'insn[1]' elsewhere in the file for similar purposes.
Additionally, we don't check if 'insn[1]' is actually a zext for our
load-acquire's dst_reg, or some other registers - in other words, here
we are relying on the verifier to always insert a redundant zext right
after a 8/16/32-bit load-acquire, for its dst_reg.
Acked-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
Signed-off-by: Peilin Ye <yepeilin@google.com>
---
arch/riscv/net/bpf_jit_comp64.c | 23 ++++++++++++++++++-----
arch/riscv/net/bpf_jit_core.c | 3 +--
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 8767f032f2de..10e01ff06312 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -607,8 +607,13 @@ static void emit_store_64(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
emit_sd(RV_REG_T1, 0, rs, ctx);
}
-static int emit_atomic_ld_st(u8 rd, u8 rs, s16 off, s32 imm, u8 code, struct rv_jit_context *ctx)
+static int emit_atomic_ld_st(u8 rd, u8 rs, const struct bpf_insn *insn,
+ struct rv_jit_context *ctx)
{
+ u8 code = insn->code;
+ s32 imm = insn->imm;
+ s16 off = insn->off;
+
switch (imm) {
/* dst_reg = load_acquire(src_reg + off16) */
case BPF_LOAD_ACQ:
@@ -627,6 +632,12 @@ static int emit_atomic_ld_st(u8 rd, u8 rs, s16 off, s32 imm, u8 code, struct rv_
break;
}
emit_fence_r_rw(ctx);
+
+ /* If our next insn is a redundant zext, return 1 to tell
+ * build_body() to skip it.
+ */
+ if (BPF_SIZE(code) != BPF_DW && insn_is_zext(&insn[1]))
+ return 1;
break;
/* store_release(dst_reg + off16, src_reg) */
case BPF_STORE_REL:
@@ -654,10 +665,12 @@ static int emit_atomic_ld_st(u8 rd, u8 rs, s16 off, s32 imm, u8 code, struct rv_
return 0;
}
-static int emit_atomic_rmw(u8 rd, u8 rs, s16 off, s32 imm, u8 code,
+static int emit_atomic_rmw(u8 rd, u8 rs, const struct bpf_insn *insn,
struct rv_jit_context *ctx)
{
- u8 r0;
+ u8 r0, code = insn->code;
+ s16 off = insn->off;
+ s32 imm = insn->imm;
int jmp_offset;
bool is64;
@@ -2026,9 +2039,9 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
case BPF_STX | BPF_ATOMIC | BPF_W:
case BPF_STX | BPF_ATOMIC | BPF_DW:
if (bpf_atomic_is_load_store(insn))
- ret = emit_atomic_ld_st(rd, rs, off, imm, code, ctx);
+ ret = emit_atomic_ld_st(rd, rs, insn, ctx);
else
- ret = emit_atomic_rmw(rd, rs, off, imm, code, ctx);
+ ret = emit_atomic_rmw(rd, rs, insn, ctx);
if (ret)
return ret;
break;
diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
index f8cd2f70a7fb..f6ca5cfa6b2f 100644
--- a/arch/riscv/net/bpf_jit_core.c
+++ b/arch/riscv/net/bpf_jit_core.c
@@ -26,9 +26,8 @@ static int build_body(struct rv_jit_context *ctx, bool extra_pass, int *offset)
int ret;
ret = bpf_jit_emit_insn(insn, ctx, extra_pass);
- /* BPF_LD | BPF_IMM | BPF_DW: skip the next instruction. */
if (ret > 0)
- i++;
+ i++; /* skip the next instruction */
if (offset)
offset[i] = ctx->ninsns;
if (ret < 0)
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH bpf-next v2 5/8] selftests/bpf: Use CAN_USE_LOAD_ACQ_STORE_REL when appropriate
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
` (3 preceding siblings ...)
2025-05-07 3:43 ` [PATCH bpf-next v2 4/8] bpf, riscv64: Skip redundant zext instruction after load-acquire Peilin Ye
@ 2025-05-07 3:43 ` Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 6/8] selftests/bpf: Avoid passing out-of-range values to __retval() Peilin Ye
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:43 UTC (permalink / raw)
To: bpf
Cc: Peilin Ye, linux-riscv, Andrea Parri, Björn Töpel,
Pu Lehui, Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall
Instead of open-coding the conditions, use
'#ifdef CAN_USE_LOAD_ACQ_STORE_REL' to guard the following tests:
verifier_precision/bpf_load_acquire
verifier_precision/bpf_store_release
verifier_store_release/*
Note that, for the first two tests in verifier_precision.c, switching to
'#ifdef CAN_USE_LOAD_ACQ_STORE_REL' means also checking if
'__clang_major__ >= 18', which has already been guaranteed by the outer
'#if' check.
Acked-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
Signed-off-by: Peilin Ye <yepeilin@google.com>
---
tools/testing/selftests/bpf/progs/verifier_precision.c | 5 ++---
tools/testing/selftests/bpf/progs/verifier_store_release.c | 7 +++----
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
index 6662d4b39969..2dd0d15c2678 100644
--- a/tools/testing/selftests/bpf/progs/verifier_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
@@ -91,8 +91,7 @@ __naked int bpf_end_bswap(void)
::: __clobber_all);
}
-#if defined(ENABLE_ATOMICS_TESTS) && \
- (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+#ifdef CAN_USE_LOAD_ACQ_STORE_REL
SEC("?raw_tp")
__success __log_level(2)
@@ -138,7 +137,7 @@ __naked int bpf_store_release(void)
: __clobber_all);
}
-#endif /* load-acquire, store-release */
+#endif /* CAN_USE_LOAD_ACQ_STORE_REL */
#endif /* v4 instruction */
SEC("?raw_tp")
diff --git a/tools/testing/selftests/bpf/progs/verifier_store_release.c b/tools/testing/selftests/bpf/progs/verifier_store_release.c
index c0442d5bb049..7e456e2861b4 100644
--- a/tools/testing/selftests/bpf/progs/verifier_store_release.c
+++ b/tools/testing/selftests/bpf/progs/verifier_store_release.c
@@ -6,8 +6,7 @@
#include "../../../include/linux/filter.h"
#include "bpf_misc.h"
-#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
- (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+#ifdef CAN_USE_LOAD_ACQ_STORE_REL
SEC("socket")
__description("store-release, 8-bit")
@@ -271,7 +270,7 @@ __naked void store_release_with_invalid_reg(void)
: __clobber_all);
}
-#else
+#else /* CAN_USE_LOAD_ACQ_STORE_REL */
SEC("socket")
__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/or JIT doesn't support store-release, use a dummy test")
@@ -281,6 +280,6 @@ int dummy_test(void)
return 0;
}
-#endif
+#endif /* CAN_USE_LOAD_ACQ_STORE_REL */
char _license[] SEC("license") = "GPL";
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH bpf-next v2 6/8] selftests/bpf: Avoid passing out-of-range values to __retval()
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
` (4 preceding siblings ...)
2025-05-07 3:43 ` [PATCH bpf-next v2 5/8] selftests/bpf: Use CAN_USE_LOAD_ACQ_STORE_REL when appropriate Peilin Ye
@ 2025-05-07 3:43 ` Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 7/8] selftests/bpf: Verify zero-extension behavior in load-acquire tests Peilin Ye
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:43 UTC (permalink / raw)
To: bpf
Cc: Peilin Ye, linux-riscv, Andrea Parri, Björn Töpel,
Pu Lehui, Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall
Currently, we pass 0x1234567890abcdef to __retval() for the following
two tests:
verifier_load_acquire/load_acquire_64
verifier_store_release/store_release_64
However, the upper 32 bits of that value are being ignored, since
__retval() expects an int. Actually, the tests would still pass even if
I change '__retval(0x1234567890abcdef)' to e.g. '__retval(0x90abcdef)'.
Restructure the tests a bit to test the entire 64-bit values properly.
Do the same to their 8-, 16- and 32-bit variants as well to keep the
style consistent.
Fixes: ff3afe5da998 ("selftests/bpf: Add selftests for load-acquire and store-release instructions")
Acked-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
Signed-off-by: Peilin Ye <yepeilin@google.com>
---
.../bpf/progs/verifier_load_acquire.c | 40 +++++++++++++------
.../bpf/progs/verifier_store_release.c | 32 +++++++++++----
2 files changed, 52 insertions(+), 20 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/verifier_load_acquire.c b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
index 77698d5a19e4..a696ab84bfd6 100644
--- a/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
+++ b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
@@ -10,65 +10,81 @@
SEC("socket")
__description("load-acquire, 8-bit")
-__success __success_unpriv __retval(0x12)
+__success __success_unpriv __retval(0)
__naked void load_acquire_8(void)
{
asm volatile (
+ "r0 = 0;"
"w1 = 0x12;"
"*(u8 *)(r10 - 1) = w1;"
- ".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r10 - 1));
+ ".8byte %[load_acquire_insn];" // w2 = load_acquire((u8 *)(r10 - 1));
+ "if r2 == r1 goto 1f;"
+ "r0 = 1;"
+"1:"
"exit;"
:
: __imm_insn(load_acquire_insn,
- BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -1))
+ BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_2, BPF_REG_10, -1))
: __clobber_all);
}
SEC("socket")
__description("load-acquire, 16-bit")
-__success __success_unpriv __retval(0x1234)
+__success __success_unpriv __retval(0)
__naked void load_acquire_16(void)
{
asm volatile (
+ "r0 = 0;"
"w1 = 0x1234;"
"*(u16 *)(r10 - 2) = w1;"
- ".8byte %[load_acquire_insn];" // w0 = load_acquire((u16 *)(r10 - 2));
+ ".8byte %[load_acquire_insn];" // w2 = load_acquire((u16 *)(r10 - 2));
+ "if r2 == r1 goto 1f;"
+ "r0 = 1;"
+"1:"
"exit;"
:
: __imm_insn(load_acquire_insn,
- BPF_ATOMIC_OP(BPF_H, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -2))
+ BPF_ATOMIC_OP(BPF_H, BPF_LOAD_ACQ, BPF_REG_2, BPF_REG_10, -2))
: __clobber_all);
}
SEC("socket")
__description("load-acquire, 32-bit")
-__success __success_unpriv __retval(0x12345678)
+__success __success_unpriv __retval(0)
__naked void load_acquire_32(void)
{
asm volatile (
+ "r0 = 0;"
"w1 = 0x12345678;"
"*(u32 *)(r10 - 4) = w1;"
- ".8byte %[load_acquire_insn];" // w0 = load_acquire((u32 *)(r10 - 4));
+ ".8byte %[load_acquire_insn];" // w2 = load_acquire((u32 *)(r10 - 4));
+ "if r2 == r1 goto 1f;"
+ "r0 = 1;"
+"1:"
"exit;"
:
: __imm_insn(load_acquire_insn,
- BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -4))
+ BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_2, BPF_REG_10, -4))
: __clobber_all);
}
SEC("socket")
__description("load-acquire, 64-bit")
-__success __success_unpriv __retval(0x1234567890abcdef)
+__success __success_unpriv __retval(0)
__naked void load_acquire_64(void)
{
asm volatile (
+ "r0 = 0;"
"r1 = 0x1234567890abcdef ll;"
"*(u64 *)(r10 - 8) = r1;"
- ".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r10 - 8));
+ ".8byte %[load_acquire_insn];" // r2 = load_acquire((u64 *)(r10 - 8));
+ "if r2 == r1 goto 1f;"
+ "r0 = 1;"
+"1:"
"exit;"
:
: __imm_insn(load_acquire_insn,
- BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -8))
+ BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_2, BPF_REG_10, -8))
: __clobber_all);
}
diff --git a/tools/testing/selftests/bpf/progs/verifier_store_release.c b/tools/testing/selftests/bpf/progs/verifier_store_release.c
index 7e456e2861b4..72f1eb006074 100644
--- a/tools/testing/selftests/bpf/progs/verifier_store_release.c
+++ b/tools/testing/selftests/bpf/progs/verifier_store_release.c
@@ -10,13 +10,17 @@
SEC("socket")
__description("store-release, 8-bit")
-__success __success_unpriv __retval(0x12)
+__success __success_unpriv __retval(0)
__naked void store_release_8(void)
{
asm volatile (
+ "r0 = 0;"
"w1 = 0x12;"
".8byte %[store_release_insn];" // store_release((u8 *)(r10 - 1), w1);
- "w0 = *(u8 *)(r10 - 1);"
+ "w2 = *(u8 *)(r10 - 1);"
+ "if r2 == r1 goto 1f;"
+ "r0 = 1;"
+"1:"
"exit;"
:
: __imm_insn(store_release_insn,
@@ -26,13 +30,17 @@ __naked void store_release_8(void)
SEC("socket")
__description("store-release, 16-bit")
-__success __success_unpriv __retval(0x1234)
+__success __success_unpriv __retval(0)
__naked void store_release_16(void)
{
asm volatile (
+ "r0 = 0;"
"w1 = 0x1234;"
".8byte %[store_release_insn];" // store_release((u16 *)(r10 - 2), w1);
- "w0 = *(u16 *)(r10 - 2);"
+ "w2 = *(u16 *)(r10 - 2);"
+ "if r2 == r1 goto 1f;"
+ "r0 = 1;"
+"1:"
"exit;"
:
: __imm_insn(store_release_insn,
@@ -42,13 +50,17 @@ __naked void store_release_16(void)
SEC("socket")
__description("store-release, 32-bit")
-__success __success_unpriv __retval(0x12345678)
+__success __success_unpriv __retval(0)
__naked void store_release_32(void)
{
asm volatile (
+ "r0 = 0;"
"w1 = 0x12345678;"
".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 4), w1);
- "w0 = *(u32 *)(r10 - 4);"
+ "w2 = *(u32 *)(r10 - 4);"
+ "if r2 == r1 goto 1f;"
+ "r0 = 1;"
+"1:"
"exit;"
:
: __imm_insn(store_release_insn,
@@ -58,13 +70,17 @@ __naked void store_release_32(void)
SEC("socket")
__description("store-release, 64-bit")
-__success __success_unpriv __retval(0x1234567890abcdef)
+__success __success_unpriv __retval(0)
__naked void store_release_64(void)
{
asm volatile (
+ "r0 = 0;"
"r1 = 0x1234567890abcdef ll;"
".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1);
- "r0 = *(u64 *)(r10 - 8);"
+ "r2 = *(u64 *)(r10 - 8);"
+ "if r2 == r1 goto 1f;"
+ "r0 = 1;"
+"1:"
"exit;"
:
: __imm_insn(store_release_insn,
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH bpf-next v2 7/8] selftests/bpf: Verify zero-extension behavior in load-acquire tests
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
` (5 preceding siblings ...)
2025-05-07 3:43 ` [PATCH bpf-next v2 6/8] selftests/bpf: Avoid passing out-of-range values to __retval() Peilin Ye
@ 2025-05-07 3:43 ` Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 8/8] selftests/bpf: Enable non-arena load-acquire/store-release selftests for riscv64 Peilin Ye
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:43 UTC (permalink / raw)
To: bpf
Cc: Peilin Ye, linux-riscv, Andrea Parri, Björn Töpel,
Pu Lehui, Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall
Verify that 8-, 16- and 32-bit load-acquires are zero-extending by using
immediate values with their highest bit set. Do the same for the 64-bit
variant to keep the style consistent.
Acked-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
Signed-off-by: Peilin Ye <yepeilin@google.com>
---
tools/testing/selftests/bpf/progs/verifier_load_acquire.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/verifier_load_acquire.c b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
index a696ab84bfd6..74f4f19c10b8 100644
--- a/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
+++ b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
@@ -15,7 +15,7 @@ __naked void load_acquire_8(void)
{
asm volatile (
"r0 = 0;"
- "w1 = 0x12;"
+ "w1 = 0xfe;"
"*(u8 *)(r10 - 1) = w1;"
".8byte %[load_acquire_insn];" // w2 = load_acquire((u8 *)(r10 - 1));
"if r2 == r1 goto 1f;"
@@ -35,7 +35,7 @@ __naked void load_acquire_16(void)
{
asm volatile (
"r0 = 0;"
- "w1 = 0x1234;"
+ "w1 = 0xfedc;"
"*(u16 *)(r10 - 2) = w1;"
".8byte %[load_acquire_insn];" // w2 = load_acquire((u16 *)(r10 - 2));
"if r2 == r1 goto 1f;"
@@ -55,7 +55,7 @@ __naked void load_acquire_32(void)
{
asm volatile (
"r0 = 0;"
- "w1 = 0x12345678;"
+ "w1 = 0xfedcba09;"
"*(u32 *)(r10 - 4) = w1;"
".8byte %[load_acquire_insn];" // w2 = load_acquire((u32 *)(r10 - 4));
"if r2 == r1 goto 1f;"
@@ -75,7 +75,7 @@ __naked void load_acquire_64(void)
{
asm volatile (
"r0 = 0;"
- "r1 = 0x1234567890abcdef ll;"
+ "r1 = 0xfedcba0987654321 ll;"
"*(u64 *)(r10 - 8) = r1;"
".8byte %[load_acquire_insn];" // r2 = load_acquire((u64 *)(r10 - 8));
"if r2 == r1 goto 1f;"
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH bpf-next v2 8/8] selftests/bpf: Enable non-arena load-acquire/store-release selftests for riscv64
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
` (6 preceding siblings ...)
2025-05-07 3:43 ` [PATCH bpf-next v2 7/8] selftests/bpf: Verify zero-extension behavior in load-acquire tests Peilin Ye
@ 2025-05-07 3:43 ` Peilin Ye
2025-05-07 3:46 ` [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
2025-05-09 17:20 ` patchwork-bot+netdevbpf
9 siblings, 0 replies; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:43 UTC (permalink / raw)
To: bpf
Cc: Peilin Ye, linux-riscv, Andrea Parri, Björn Töpel,
Pu Lehui, Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall
For riscv64, enable all BPF_{LOAD_ACQ,STORE_REL} selftests except the
arena_atomics/* ones (not guarded behind CAN_USE_LOAD_ACQ_STORE_REL),
since arena access is not yet supported.
Acked-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
Signed-off-by: Peilin Ye <yepeilin@google.com>
---
tools/testing/selftests/bpf/progs/bpf_misc.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index 863df7c0fdd0..6e208e24ba3b 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -225,8 +225,9 @@
#define CAN_USE_BPF_ST
#endif
-#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
- (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
+ (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
+ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64))
#define CAN_USE_LOAD_ACQ_STORE_REL
#endif
--
2.49.0.967.g6a0df3ecc3-goog
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
` (7 preceding siblings ...)
2025-05-07 3:43 ` [PATCH bpf-next v2 8/8] selftests/bpf: Enable non-arena load-acquire/store-release selftests for riscv64 Peilin Ye
@ 2025-05-07 3:46 ` Peilin Ye
2025-05-09 17:20 ` patchwork-bot+netdevbpf
9 siblings, 0 replies; 13+ messages in thread
From: Peilin Ye @ 2025-05-07 3:46 UTC (permalink / raw)
To: bpf
Cc: linux-riscv, Andrea Parri, Björn Töpel, Pu Lehui,
Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Paul E. McKenney, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Luke Nelson,
Xi Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Mykola Lysenko, Shuah Khan, Josh Don,
Barret Rhoden, Neel Natu, Benjamin Segall
Hi Lehui,
On Wed, May 07, 2025 at 03:42:29AM +0000, Peilin Ye wrote:
> v1: https://lore.kernel.org/bpf/cover.1745970908.git.yepeilin@google.com/
> Changes since v1:
>
> * add Acked-by:, Reviewed-by: and Tested-by: tags from Lehui and Björn
> * simplify code logic in PATCH 1 (Lehui)
> * in PATCH 3, avoid changing 'return 0;' to 'return ret;' at the end of
> bpf_jit_emit_insn() (Lehui)
>
> Please refer to individual patches for details. Thanks!
>
> [1] https://lore.kernel.org/all/cover.1741049567.git.yepeilin@google.com/
>
> Andrea Parri (2):
> bpf, riscv64: Introduce emit_load_*() and emit_store_*()
> bpf, riscv64: Support load-acquire and store-release instructions
>
> Peilin Ye (6):
> bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno()
> bpf, riscv64: Skip redundant zext instruction after load-acquire
> selftests/bpf: Use CAN_USE_LOAD_ACQ_STORE_REL when appropriate
> selftests/bpf: Avoid passing out-of-range values to __retval()
> selftests/bpf: Verify zero-extension behavior in load-acquire tests
> selftests/bpf: Enable non-arena load-acquire/store-release selftests
> for riscv64
>
> arch/riscv/net/bpf_jit.h | 15 +
> arch/riscv/net/bpf_jit_comp64.c | 332 ++++++++++++------
> arch/riscv/net/bpf_jit_core.c | 3 +-
> kernel/bpf/verifier.c | 12 +-
> tools/testing/selftests/bpf/progs/bpf_misc.h | 5 +-
> .../bpf/progs/verifier_load_acquire.c | 48 ++-
> .../selftests/bpf/progs/verifier_precision.c | 5 +-
> .../bpf/progs/verifier_store_release.c | 39 +-
> 8 files changed, 313 insertions(+), 146 deletions(-)
Please take another look at v2 PATCH 1/8 and 3/8, thanks!
Peilin Ye
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v2 1/8] bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno()
2025-05-07 3:42 ` [PATCH bpf-next v2 1/8] bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno() Peilin Ye
@ 2025-05-07 6:42 ` Pu Lehui
0 siblings, 0 replies; 13+ messages in thread
From: Pu Lehui @ 2025-05-07 6:42 UTC (permalink / raw)
To: Peilin Ye, bpf
Cc: linux-riscv, Andrea Parri, Björn Töpel, Puranjay Mohan,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Paul E. McKenney, Song Liu,
Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
Hao Luo, Jiri Olsa, Luke Nelson, Xi Wang, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Mykola Lysenko,
Shuah Khan, Josh Don, Barret Rhoden, Neel Natu, Benjamin Segall
On 2025/5/7 11:42, Peilin Ye wrote:
> In preparation for supporting BPF load-acquire and store-release
> instructions for architectures where bpf_jit_needs_zext() returns true
> (e.g. riscv64), make insn_def_regno() handle load-acquires properly.
>
> Acked-by: Björn Töpel <bjorn@kernel.org>
> Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
> Signed-off-by: Peilin Ye <yepeilin@google.com>
> ---
> kernel/bpf/verifier.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 99aa2c890e7b..28f5a7899bd6 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -3649,16 +3649,16 @@ static int insn_def_regno(const struct bpf_insn *insn)
> case BPF_ST:
> return -1;
> case BPF_STX:
> - if ((BPF_MODE(insn->code) == BPF_ATOMIC ||
> - BPF_MODE(insn->code) == BPF_PROBE_ATOMIC) &&
> - (insn->imm & BPF_FETCH)) {
> + if (BPF_MODE(insn->code) == BPF_ATOMIC ||
> + BPF_MODE(insn->code) == BPF_PROBE_ATOMIC) {
> if (insn->imm == BPF_CMPXCHG)
> return BPF_REG_0;
> - else
> + else if (insn->imm == BPF_LOAD_ACQ)
> + return insn->dst_reg;
> + else if (insn->imm & BPF_FETCH)
> return insn->src_reg;
> - } else {
> - return -1;
> }
> + return -1;
> default:
> return insn->dst_reg;
> }
lgtm, thanks
Reviewed-by: Pu Lehui <pulehui@huawei.com>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v2 3/8] bpf, riscv64: Support load-acquire and store-release instructions
2025-05-07 3:43 ` [PATCH bpf-next v2 3/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
@ 2025-05-07 6:42 ` Pu Lehui
0 siblings, 0 replies; 13+ messages in thread
From: Pu Lehui @ 2025-05-07 6:42 UTC (permalink / raw)
To: Peilin Ye, bpf
Cc: Andrea Parri, linux-riscv, Björn Töpel, Puranjay Mohan,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Paul E. McKenney, Song Liu,
Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
Hao Luo, Jiri Olsa, Luke Nelson, Xi Wang, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Mykola Lysenko,
Shuah Khan, Josh Don, Barret Rhoden, Neel Natu, Benjamin Segall
On 2025/5/7 11:43, Peilin Ye wrote:
> From: Andrea Parri <parri.andrea@gmail.com>
>
> Support BPF load-acquire (BPF_LOAD_ACQ) and store-release
> (BPF_STORE_REL) instructions in the riscv64 JIT compiler. For example,
> consider the following 64-bit load-acquire (assuming little-endian):
>
> db 10 00 00 00 01 00 00 r1 = load_acquire((u64 *)(r1 + 0x0))
> 95 00 00 00 00 00 00 00 exit
>
> opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX
> imm (0x00000100): BPF_LOAD_ACQ
>
> The JIT compiler will emit an LD instruction followed by a FENCE R,RW
> instruction for the above, e.g.:
>
> ld x7,0(x6)
> fence r,rw
>
> Similarly, consider the following 16-bit store-release:
>
> cb 21 00 00 10 01 00 00 store_release((u16 *)(r1 + 0x0), w2)
> 95 00 00 00 00 00 00 00 exit
>
> opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX
> imm (0x00000110): BPF_STORE_REL
>
> A FENCE RW,W instruction followed by an SH instruction will be emitted,
> e.g.:
>
> fence rw,w
> sh x2,0(x4)
>
> 8-bit and 16-bit load-acquires are zero-extending (cf., LBU, LHU). The
> verifier always rejects misaligned load-acquires/store-releases (even if
> BPF_F_ANY_ALIGNMENT is set), so the emitted load and store instructions
> are guaranteed to be single-copy atomic.
>
> Introduce primitives to emit the relevant (and the most common/used in
> the kernel) fences, i.e. fences with R -> RW, RW -> W and RW -> RW.
>
> Rename emit_atomic() to emit_atomic_rmw() to make it clear that it only
> handles RMW atomics, and replace its is64 parameter to allow to perform
> the required checks on the opsize (BPF_SIZE(code)).
>
> Acked-by: Björn Töpel <bjorn@kernel.org>
> Tested-by: Björn Töpel <bjorn@rivosinc.com> # QEMU/RVA23
> Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
> Co-developed-by: Peilin Ye <yepeilin@google.com>
> Signed-off-by: Peilin Ye <yepeilin@google.com>
> ---
> arch/riscv/net/bpf_jit.h | 15 +++++++
> arch/riscv/net/bpf_jit_comp64.c | 75 ++++++++++++++++++++++++++++++---
> 2 files changed, 85 insertions(+), 5 deletions(-)
>
> diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
> index 1d1c78d4cff1..e7b032dfd17f 100644
> --- a/arch/riscv/net/bpf_jit.h
> +++ b/arch/riscv/net/bpf_jit.h
> @@ -608,6 +608,21 @@ static inline u32 rv_fence(u8 pred, u8 succ)
> return rv_i_insn(imm11_0, 0, 0, 0, 0xf);
> }
>
> +static inline void emit_fence_r_rw(struct rv_jit_context *ctx)
> +{
> + emit(rv_fence(0x2, 0x3), ctx);
> +}
> +
> +static inline void emit_fence_rw_w(struct rv_jit_context *ctx)
> +{
> + emit(rv_fence(0x3, 0x1), ctx);
> +}
> +
> +static inline void emit_fence_rw_rw(struct rv_jit_context *ctx)
> +{
> + emit(rv_fence(0x3, 0x3), ctx);
> +}
> +
> static inline u32 rv_nop(void)
> {
> return rv_i_insn(0, 0, 0, 0, 0x13);
> diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
> index 953b6a20c69f..8767f032f2de 100644
> --- a/arch/riscv/net/bpf_jit_comp64.c
> +++ b/arch/riscv/net/bpf_jit_comp64.c
> @@ -607,11 +607,65 @@ static void emit_store_64(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
> emit_sd(RV_REG_T1, 0, rs, ctx);
> }
>
> -static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
> - struct rv_jit_context *ctx)
> +static int emit_atomic_ld_st(u8 rd, u8 rs, s16 off, s32 imm, u8 code, struct rv_jit_context *ctx)
> +{
> + switch (imm) {
> + /* dst_reg = load_acquire(src_reg + off16) */
> + case BPF_LOAD_ACQ:
> + switch (BPF_SIZE(code)) {
> + case BPF_B:
> + emit_load_8(false, rd, off, rs, ctx);
> + break;
> + case BPF_H:
> + emit_load_16(false, rd, off, rs, ctx);
> + break;
> + case BPF_W:
> + emit_load_32(false, rd, off, rs, ctx);
> + break;
> + case BPF_DW:
> + emit_load_64(false, rd, off, rs, ctx);
> + break;
> + }
> + emit_fence_r_rw(ctx);
> + break;
> + /* store_release(dst_reg + off16, src_reg) */
> + case BPF_STORE_REL:
> + emit_fence_rw_w(ctx);
> + switch (BPF_SIZE(code)) {
> + case BPF_B:
> + emit_store_8(rd, off, rs, ctx);
> + break;
> + case BPF_H:
> + emit_store_16(rd, off, rs, ctx);
> + break;
> + case BPF_W:
> + emit_store_32(rd, off, rs, ctx);
> + break;
> + case BPF_DW:
> + emit_store_64(rd, off, rs, ctx);
> + break;
> + }
> + break;
> + default:
> + pr_err_once("bpf-jit: invalid atomic load/store opcode %02x\n", imm);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int emit_atomic_rmw(u8 rd, u8 rs, s16 off, s32 imm, u8 code,
> + struct rv_jit_context *ctx)
> {
> u8 r0;
> int jmp_offset;
> + bool is64;
> +
> + if (BPF_SIZE(code) != BPF_W && BPF_SIZE(code) != BPF_DW) {
> + pr_err_once("bpf-jit: 1- and 2-byte RMW atomics are not supported\n");
> + return -EINVAL;
> + }
> + is64 = BPF_SIZE(code) == BPF_DW;
>
> if (off) {
> if (is_12b_int(off)) {
> @@ -688,9 +742,14 @@ static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
> rv_sc_w(RV_REG_T3, rs, rd, 0, 1), ctx);
> jmp_offset = ninsns_rvoff(-6);
> emit(rv_bne(RV_REG_T3, 0, jmp_offset >> 1), ctx);
> - emit(rv_fence(0x3, 0x3), ctx);
> + emit_fence_rw_rw(ctx);
> break;
> + default:
> + pr_err_once("bpf-jit: invalid atomic RMW opcode %02x\n", imm);
> + return -EINVAL;
> }
> +
> + return 0;
> }
>
> #define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
> @@ -1962,10 +2021,16 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> case BPF_STX | BPF_MEM | BPF_DW:
> emit_store_64(rd, off, rs, ctx);
> break;
> + case BPF_STX | BPF_ATOMIC | BPF_B:
> + case BPF_STX | BPF_ATOMIC | BPF_H:
> case BPF_STX | BPF_ATOMIC | BPF_W:
> case BPF_STX | BPF_ATOMIC | BPF_DW:
> - emit_atomic(rd, rs, off, imm,
> - BPF_SIZE(code) == BPF_DW, ctx);
> + if (bpf_atomic_is_load_store(insn))
> + ret = emit_atomic_ld_st(rd, rs, off, imm, code, ctx);
> + else
> + ret = emit_atomic_rmw(rd, rs, off, imm, code, ctx);
> + if (ret)
> + return ret;
> break;
>
> case BPF_STX | BPF_PROBE_MEM32 | BPF_B:
Reviewed-by: Pu Lehui <pulehui@huawei.com>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
` (8 preceding siblings ...)
2025-05-07 3:46 ` [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
@ 2025-05-09 17:20 ` patchwork-bot+netdevbpf
9 siblings, 0 replies; 13+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-05-09 17:20 UTC (permalink / raw)
To: Peilin Ye
Cc: bpf, linux-riscv, parri.andrea, bjorn, pulehui, puranjay, ast,
daniel, andrii, martin.lau, eddyz87, paulmck, song, yonghong.song,
john.fastabend, kpsingh, sdf, haoluo, jolsa, luke.r.nels, xi.wang,
paul.walmsley, palmer, aou, alex, mykolal, shuah, joshdon, brho,
neelnatu, bsegall
Hello:
This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Wed, 7 May 2025 03:42:29 +0000 you wrote:
> Hi all!
>
> Patchset [1] introduced BPF load-acquire (BPF_LOAD_ACQ) and
> store-release (BPF_STORE_REL) instructions, and added x86-64 and arm64
> JIT compiler support. As a follow-up, this v2 patchset supports
> load-acquire and store-release instructions for the riscv64 JIT
> compiler, and introduces some related selftests/ changes.
>
> [...]
Here is the summary with links:
- [bpf-next,v2,1/8] bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno()
https://git.kernel.org/bpf/bpf-next/c/fce7bd8e385a
- [bpf-next,v2,2/8] bpf, riscv64: Introduce emit_load_*() and emit_store_*()
https://git.kernel.org/bpf/bpf-next/c/118ae46b7942
- [bpf-next,v2,3/8] bpf, riscv64: Support load-acquire and store-release instructions
https://git.kernel.org/bpf/bpf-next/c/8afd3170d511
- [bpf-next,v2,4/8] bpf, riscv64: Skip redundant zext instruction after load-acquire
https://git.kernel.org/bpf/bpf-next/c/db7a3822b5f4
- [bpf-next,v2,5/8] selftests/bpf: Use CAN_USE_LOAD_ACQ_STORE_REL when appropriate
https://git.kernel.org/bpf/bpf-next/c/13fdecf3456e
- [bpf-next,v2,6/8] selftests/bpf: Avoid passing out-of-range values to __retval()
https://git.kernel.org/bpf/bpf-next/c/6e492ffcab60
- [bpf-next,v2,7/8] selftests/bpf: Verify zero-extension behavior in load-acquire tests
https://git.kernel.org/bpf/bpf-next/c/0357f29de809
- [bpf-next,v2,8/8] selftests/bpf: Enable non-arena load-acquire/store-release selftests for riscv64
https://git.kernel.org/bpf/bpf-next/c/d3131466b4f8
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-05-09 20:26 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-07 3:42 [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
2025-05-07 3:42 ` [PATCH bpf-next v2 1/8] bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno() Peilin Ye
2025-05-07 6:42 ` Pu Lehui
2025-05-07 3:42 ` [PATCH bpf-next v2 2/8] bpf, riscv64: Introduce emit_load_*() and emit_store_*() Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 3/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
2025-05-07 6:42 ` Pu Lehui
2025-05-07 3:43 ` [PATCH bpf-next v2 4/8] bpf, riscv64: Skip redundant zext instruction after load-acquire Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 5/8] selftests/bpf: Use CAN_USE_LOAD_ACQ_STORE_REL when appropriate Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 6/8] selftests/bpf: Avoid passing out-of-range values to __retval() Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 7/8] selftests/bpf: Verify zero-extension behavior in load-acquire tests Peilin Ye
2025-05-07 3:43 ` [PATCH bpf-next v2 8/8] selftests/bpf: Enable non-arena load-acquire/store-release selftests for riscv64 Peilin Ye
2025-05-07 3:46 ` [PATCH bpf-next v2 0/8] bpf, riscv64: Support load-acquire and store-release instructions Peilin Ye
2025-05-09 17:20 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox