summaryrefslogtreecommitdiff
path: root/arch/loongarch/kernel/stacktrace.c
diff options
context:
space:
mode:
authorQing Zhang <zhangqing@loongson.cn>2022-08-06 16:10:04 +0800
committerHuacai Chen <chenhuacai@loongson.cn>2022-08-12 13:10:11 +0800
commit93a4fa622eb061f75f87f0cf9609ab4e69c67d01 (patch)
treed49f5b01e8a2299424b31d9344101dc5b5a561d7 /arch/loongarch/kernel/stacktrace.c
parent49aef111e2dae176a7708b532118f33f24289248 (diff)
downloadlwn-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.c37
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;
+ }
+}