[PATCH v1] LoongArch: BPF: Implement arch_bpf_stack_walk()

From: Tiezhu Yang

Date: Thu Aug 13 2026 - 00:53:31 EST


From: George Guo <guodongtai@xxxxxxxxxx>

Implement arch_bpf_stack_walk() on top of the ORC unwinder within
the LoongArch BPF JIT backend to provide generic BPF stack walking
capabilities.

This function is required by advanced BPF features, including timed
may_goto timeout tracing and BPF exceptions. It will be invoked in
the BPF core subsystem unwinding paths: bpf_prog_find_from_stack(),
bpf_stream_stage_dump_stack(), and bpf_throw().

Co-developed-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>
Signed-off-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>
Signed-off-by: George Guo <guodongtai@xxxxxxxxxx>
---
This is an independent feature, so split it from
https://lore.kernel.org/loongarch/20260702022322.51033-6-dongtai.guo@xxxxxxxxx/
Based on the latest loongarch-next, tested on Loongson-3A6000.

arch/loongarch/net/bpf_jit.c | 38 ++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)

diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index 7533917c6d47..78c20df2a2f3 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -2402,6 +2402,44 @@ bool bpf_jit_supports_subprog_tailcalls(void)
return true;
}

+#if defined(CONFIG_UNWINDER_ORC)
+#include <asm/unwind.h>
+
+static noinline void walk_bpf_stackframe(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp),
+ void *cookie, unsigned long fp)
+{
+ struct pt_regs dummyregs;
+ struct pt_regs *regs = &dummyregs;
+ struct unwind_state state;
+ unsigned long addr;
+
+ regs->regs[3] = (unsigned long)__builtin_frame_address(0);
+ regs->csr_era = (unsigned long)__builtin_return_address(0);
+ regs->regs[1] = 0;
+ regs->regs[22] = fp;
+
+ for (unwind_start(&state, current, regs);
+ !unwind_done(&state); unwind_next_frame(&state)) {
+ addr = unwind_get_return_address(&state);
+ if (!addr || !consume_fn(cookie, (u64)addr, (u64)state.sp, (u64)state.fp))
+ break;
+ }
+}
+
+void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie)
+{
+ unsigned long fp;
+
+ /*
+ * Capture the live frame pointer ($r22) at the very front-line before
+ * any kernel C code clobbers it. This must be a thin wrapper with no
+ * large stack locals to prevent the compiler from reusing $r22 early.
+ */
+ asm volatile("move %0, $r22" : "=r"(fp));
+ walk_bpf_stackframe(consume_fn, cookie, fp);
+}
+#endif /* CONFIG_UNWINDER_ORC */
+
bool bpf_jit_supports_timed_may_goto(void)
{
return true;
--
2.42.0