diff options
Diffstat (limited to 'arch/riscv/kernel/stacktrace.c')
| -rw-r--r-- | arch/riscv/kernel/stacktrace.c | 9 | 
1 files changed, 5 insertions, 4 deletions
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index 201ee206fb57..14d2b53ec322 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c @@ -22,15 +22,16 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,  			     bool (*fn)(void *, unsigned long), void *arg)  {  	unsigned long fp, sp, pc; +	int level = 0;  	if (regs) {  		fp = frame_pointer(regs);  		sp = user_stack_pointer(regs);  		pc = instruction_pointer(regs);  	} else if (task == NULL || task == current) { -		fp = (unsigned long)__builtin_frame_address(1); -		sp = (unsigned long)__builtin_frame_address(0); -		pc = (unsigned long)__builtin_return_address(0); +		fp = (unsigned long)__builtin_frame_address(0); +		sp = sp_in_global; +		pc = (unsigned long)walk_stackframe;  	} else {  		/* task blocked in __switch_to */  		fp = task->thread.s[0]; @@ -42,7 +43,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,  		unsigned long low, high;  		struct stackframe *frame; -		if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc))) +		if (unlikely(!__kernel_text_address(pc) || (level++ >= 1 && !fn(arg, pc))))  			break;  		/* Validate frame pointer */  | 
