This will be used by bpf_throw() to unwind till the program marked as exception boundary and run the callback with the stack of the main program. This is required for supporting BPF exceptions on RISC-V. This depends on the frame pointer unwinder, so it is only built under CONFIG_FRAME_POINTER, else falls back to the weak no-op. Signed-off-by: Varun R Mallya --- arch/riscv/kernel/stacktrace.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index b41b6255751c..a4c2411f4038 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -102,6 +103,33 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, } } +void notrace arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), + void *cookie) +{ + unsigned long fp, sp, pc; + + fp = (unsigned long)__builtin_frame_address(0); + sp = current_stack_pointer; + pc = (unsigned long)arch_bpf_stack_walk; + + for (;;) { + struct stackframe *frame; + + if (unlikely(!__kernel_text_address(pc))) + break; + /* pc belongs to the function whose frame pointer is fp */ + if (!consume_fn(cookie, pc, sp, fp)) + break; + if (unlikely(!fp_is_valid(fp, sp))) + break; + + frame = (struct stackframe *)fp - 1; + sp = fp; + fp = READ_ONCE_TASK_STACK(current, frame->fp); + pc = READ_ONCE_TASK_STACK(current, frame->ra); + } +} + #else /* !CONFIG_FRAME_POINTER */ void notrace walk_stackframe(struct task_struct *task, -- 2.54.0