diff options
author | Qing Zhang <zhangqing@loongson.cn> | 2022-08-06 16:10:04 +0800 |
---|---|---|
committer | Huacai Chen <chenhuacai@loongson.cn> | 2022-08-12 13:10:11 +0800 |
commit | 93a4fa622eb061f75f87f0cf9609ab4e69c67d01 (patch) | |
tree | d49f5b01e8a2299424b31d9344101dc5b5a561d7 /arch/loongarch/kernel/stacktrace.c | |
parent | 49aef111e2dae176a7708b532118f33f24289248 (diff) | |
download | lwn-93a4fa622eb061f75f87f0cf9609ab4e69c67d01.tar.gz lwn-93a4fa622eb061f75f87f0cf9609ab4e69c67d01.zip |
LoongArch: Add STACKTRACE support
1. Use common arch_stack_walk() infrastructure to avoid duplicated code
and avoid taking care of the stack storage and filtering.
2. Add sched_ra (means sched return address) and sched_cfa (means sched
call frame address) to thread_info, and store them in switch_to().
3. Add __get_wchan() implementation.
Now we can print the process stack and wait channel by cat /proc/*/stack
and /proc/*/wchan.
Signed-off-by: Qing Zhang <zhangqing@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch/loongarch/kernel/stacktrace.c')
-rw-r--r-- | arch/loongarch/kernel/stacktrace.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c new file mode 100644 index 000000000000..e690c1c769f2 --- /dev/null +++ b/arch/loongarch/kernel/stacktrace.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Stack trace management functions + * + * Copyright (C) 2022 Loongson Technology Corporation Limited + */ +#include <linux/sched.h> +#include <linux/stacktrace.h> + +#include <asm/stacktrace.h> +#include <asm/unwind.h> + +void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie, + struct task_struct *task, struct pt_regs *regs) +{ + unsigned long addr; + struct pt_regs dummyregs; + struct unwind_state state; + + regs = &dummyregs; + + if (task == current) { + regs->regs[3] = (unsigned long)__builtin_frame_address(0); + regs->csr_era = (unsigned long)__builtin_return_address(0); + } else { + regs->regs[3] = thread_saved_fp(task); + regs->csr_era = thread_saved_ra(task); + } + + regs->regs[1] = 0; + for (unwind_start(&state, task, regs); + !unwind_done(&state); unwind_next_frame(&state)) { + addr = unwind_get_return_address(&state); + if (!addr || !consume_entry(cookie, addr)) + break; + } +} |