From b4a1ecae94ae803fcd75fb16a7653ff86b64ed8b Mon Sep 17 00:00:00 2001 From: Kumar Kartikeya Dwivedi Date: Wed, 30 Sep 2026 08:35:19 +0000 Subject: [PATCH 1/4] bpf, riscv: Fix stack-passed arguments for indirect trampolines store_args() reads stack-passed arguments relative to FP assuming the trampoline was entered through the fentry call from a traced function. In that path, the trampoline pushes the parent frame before establishing its final FP, so the incoming stack arguments start at FP + 16. An indirect trampoline for a struct_ops callback is called through a function pointer. Its prologue allocates only the trampoline frame and sets FP to the incoming SP. The RISC-V ABI places the first stack argument at that incoming SP, so the arguments start at FP, not FP + 16. Every stack-passed argument of a callback with more than eight argument slots is therefore read two slots late. Pass the prologue-dependent offset to store_args(), using zero for a direct struct_ops trampoline and 16 for the fentry path. Fixes: 6801b0aef79d ("riscv, bpf: Add 12-argument support for RV64 bpf trampoline") Signed-off-by: Kumar Kartikeya Dwivedi Signed-off-by: Pu Lehui Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20260930083522.1914145-2-pulehui@huaweicloud.com --- arch/riscv/net/bpf_jit_comp64.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c index ebd6873b9b3d..016994aef94d 100644 --- a/arch/riscv/net/bpf_jit_comp64.c +++ b/arch/riscv/net/bpf_jit_comp64.c @@ -913,7 +913,8 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t, return ret; } -static void store_args(int nr_arg_slots, int args_off, struct rv_jit_context *ctx) +static void store_args(int nr_arg_slots, int args_off, int stack_args_off, + struct rv_jit_context *ctx) { int i; @@ -921,8 +922,8 @@ static void store_args(int nr_arg_slots, int args_off, struct rv_jit_context *ct if (i < RV_MAX_REG_ARGS) { emit_sd(RV_REG_FP, -args_off, RV_REG_A0 + i, ctx); } else { - /* skip slots for T0 and FP of traced function */ - emit_ld(RV_REG_T1, 16 + (i - RV_MAX_REG_ARGS) * 8, RV_REG_FP, ctx); + emit_ld(RV_REG_T1, stack_args_off + + (i - RV_MAX_REG_ARGS) * 8, RV_REG_FP, ctx); emit_sd(RV_REG_FP, -args_off, RV_REG_T1, ctx); } args_off -= 8; @@ -1217,7 +1218,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, func_meta = nr_arg_slots; emit_store_stack_imm64(RV_REG_T1, -func_meta_off, func_meta, ctx); - store_args(nr_arg_slots, args_off, ctx); + /* + * A direct struct_ops call has its first stack argument at the incoming + * SP, which the trampoline keeps as FP. The fentry path pushes the + * parent frame first, so its incoming stack arguments start at FP + 16. + */ + store_args(nr_arg_slots, args_off, is_struct_ops ? 0 : 16, ctx); if (bpf_fsession_cnt(tnodes)) { /* clear all session cookies' value */ From 153a855d0b3d3b740d7470fc248fe4ebccf06970 Mon Sep 17 00:00:00 2001 From: Pu Lehui Date: Wed, 30 Sep 2026 08:35:20 +0000 Subject: [PATCH 2/4] selftests/bpf: Avoid jiffies quantization error in setget_sockopt The setget_sockopt selftest fails on kernels with HZ=250 (such as the default on riscv64), specifically in the TCP_BPF_DELACK_MAX and TCP_BPF_RTO_MIN sub-tests. The test sets a socket option value in microseconds via bpf_setsockopt() and immediately reads it back via bpf_getsockopt() to verify that it matches. However, the kernel converts the value to jiffies internally for storage and converts it back to microseconds upon retrieval. When HZ=250 (4000 us per jiffy), 30000 us cannot be divided evenly: usecs_to_jiffies(30000) -> 8 jiffies jiffies_to_usecs(8) -> 32000 us (!= 30000 us) This mismatch triggers an assertion failure. Change the test value from 30000 to 40000. 40000 us divides evenly across common kernel timer frequencies (HZ=100, HZ=250, and HZ=1000), avoiding quantization errors and making the test robust across different architectures. Signed-off-by: Pu Lehui Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20260930083522.1914145-3-pulehui@huaweicloud.com --- tools/testing/selftests/bpf/progs/setget_sockopt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/setget_sockopt.c b/tools/testing/selftests/bpf/progs/setget_sockopt.c index d96e99b67aeb..95e6a337ab71 100644 --- a/tools/testing/selftests/bpf/progs/setget_sockopt.c +++ b/tools/testing/selftests/bpf/progs/setget_sockopt.c @@ -61,8 +61,8 @@ static const struct sockopt_test sol_tcp_tests[] = { { .opt = TCP_NOTSENT_LOWAT, .new = 1314, .expected = 1314, }, { .opt = TCP_BPF_SOCK_OPS_CB_FLAGS, .new = BPF_SOCK_OPS_ALL_CB_FLAGS, .expected = BPF_SOCK_OPS_ALL_CB_FLAGS, }, - { .opt = TCP_BPF_DELACK_MAX, .new = 30000, .expected = 30000, }, - { .opt = TCP_BPF_RTO_MIN, .new = 30000, .expected = 30000, }, + { .opt = TCP_BPF_DELACK_MAX, .new = 40000, .expected = 40000, }, + { .opt = TCP_BPF_RTO_MIN, .new = 40000, .expected = 40000, }, { .opt = TCP_RTO_MAX_MS, .new = 2000, .expected = 2000, }, { .opt = 0, }, }; From 78142aa07ef69a314d3da2309c3ed6f024ec915e Mon Sep 17 00:00:00 2001 From: Pu Lehui Date: Wed, 30 Sep 2026 08:35:21 +0000 Subject: [PATCH 3/4] selftests/bpf: Update qemu config for riscv64 in vmtest.sh When running vmtest.sh on riscv64, the kernel panic at boot due to an illegal instruction. This is because '-cpu rv64' only enables a baseline set of riscv extensions, whereas the kernel or toolchain requires newer extensions. Switch to '-cpu max' so qemu enables all supported extensions, and bump the required qemu version accordingly. Additionally, qemu's pmu emulation for riscv64 currently has issues, causing perf_event_open-related tests to fail. Temporarily disable the sscofpmf extension to bypass these failures for now, and will try to investigate and address it later. While at it, update the libbpf/ci branch in INDEX_URL from 'master' to 'main'. Signed-off-by: Pu Lehui Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20260930083522.1914145-4-pulehui@huaweicloud.com --- tools/testing/selftests/bpf/vmtest.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/vmtest.sh b/tools/testing/selftests/bpf/vmtest.sh index e7e0b419a0b8..c4663cad74f5 100755 --- a/tools/testing/selftests/bpf/vmtest.sh +++ b/tools/testing/selftests/bpf/vmtest.sh @@ -35,11 +35,11 @@ aarch64) ARCH="arm64" ;; riscv64) - # required qemu version v7.2.0+ + # required qemu version v8.2.0+ QEMU_BINARY=qemu-system-riscv64 QEMU_CONSOLE="ttyS0,115200" HOST_FLAGS=(-M virt -cpu host -enable-kvm -smp 8) - CROSS_FLAGS=(-M virt -cpu rv64,sscofpmf=true -smp 8) + CROSS_FLAGS=(-M virt -cpu max,sscofpmf=false -smp 8) BZIMAGE="arch/riscv/boot/Image" ARCH="riscv" ;; @@ -65,7 +65,7 @@ OUTPUT_DIR="$HOME/.bpf_selftests" KCONFIG_REL_PATHS=("tools/testing/selftests/bpf/config" "tools/testing/selftests/bpf/config.vm" "tools/testing/selftests/bpf/config.${PLATFORM}") -INDEX_URL="https://raw.githubusercontent.com/libbpf/ci/master/INDEX" +INDEX_URL="https://raw.githubusercontent.com/libbpf/ci/main/INDEX" NUM_COMPILE_JOBS="$(nproc)" LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")" LOG_FILE="${LOG_FILE_BASE}.log" From 52e98bc77f32d6a485781f0d666728bc5785473f Mon Sep 17 00:00:00 2001 From: Pu Lehui Date: Wed, 30 Sep 2026 08:35:22 +0000 Subject: [PATCH 4/4] selftests/bpf: Update DENYLIST.riscv64 Both probe_user and stacktrace_build_id fail on riscv64 due to riscv64's trap-based kprobe handling. For probe_user, kprobes on riscv64 are handled via traps where the entry path invokes irqentry_nmi_enter(). Because bpf_probe_write_user() rejects execution in NMI context, the test fails. Upstream discussions regarding NMI semantics on riscv are ongoing [0] and will be tracked. For stacktrace_build_id, under the kprobe trap context with interrupts disabled, bpf_get_stackid() obtains a valid build_id, but the queued irq_work is deferred. As a result, subsequent bpf_get_stack() fails to acquire mmap_read_trylock() and falls back to BPF_STACK_BUILD_ID_IP, causing an inconsistency between the two results. Since stacktrace_build_id is already included in the generic DENYLIST, only add probe_user to DENYLIST.riscv64. Signed-off-by: Pu Lehui Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/linux-riscv/20230702025708.784106-1-guoren@kernel.org [0] Link: https://patch.msgid.link/20260930083522.1914145-5-pulehui@huaweicloud.com --- tools/testing/selftests/bpf/DENYLIST.riscv64 | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/bpf/DENYLIST.riscv64 b/tools/testing/selftests/bpf/DENYLIST.riscv64 index ca1beae7fe8f..75a9690fb2f2 100644 --- a/tools/testing/selftests/bpf/DENYLIST.riscv64 +++ b/tools/testing/selftests/bpf/DENYLIST.riscv64 @@ -1,2 +1,3 @@ # riscv64 deny list for BPF CI and local vmtest exceptions # JIT does not support exceptions +probe_user # kprobe hit in trap