diff options
author | Qing Zhang <zhangqing@loongson.cn> | 2022-08-06 16:10:02 +0800 |
---|---|---|
committer | Huacai Chen <chenhuacai@loongson.cn> | 2022-08-12 13:10:11 +0800 |
commit | 49232773d8233ed70c4998851bc84e465fc1c788 (patch) | |
tree | eb361dbb849c68b079022e025e755cdb17a1f10c /arch/loongarch/include | |
parent | dce6098b22d58e5b646b1c67174c53f5a6a05605 (diff) | |
download | linux-49232773d8233ed70c4998851bc84e465fc1c788.tar.bz2 |
LoongArch: Add guess unwinder support
Name "guess unwinder" comes from x86, it scans the stack and reports
every kernel text address it finds.
Unwinders can be used by dump_stack() and other stacktrace functions.
Three stages when we do unwind,
1) unwind_start(), the prapare of unwinding, fill unwind_state.
2) unwind_done(), judge whether the unwind process is finished or not.
3) unwind_next_frame(), unwind the next frame.
Add get_stack_info() to get stack info. At present we have irq stack and
task stack. The next_sp is the key info between two types of stacks.
Dividing unwinder helps to add new unwinders in the future.
Signed-off-by: Qing Zhang <zhangqing@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch/loongarch/include')
-rw-r--r-- | arch/loongarch/include/asm/stacktrace.h | 15 | ||||
-rw-r--r-- | arch/loongarch/include/asm/unwind.h | 36 |
2 files changed, 51 insertions, 0 deletions
diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h index 6b5c2a7aa706..5820a0cabe3a 100644 --- a/arch/loongarch/include/asm/stacktrace.h +++ b/arch/loongarch/include/asm/stacktrace.h @@ -10,6 +10,21 @@ #include <asm/loongarch.h> #include <linux/stringify.h> +enum stack_type { + STACK_TYPE_UNKNOWN, + STACK_TYPE_IRQ, + STACK_TYPE_TASK, +}; + +struct stack_info { + enum stack_type type; + unsigned long begin, end, next_sp; +}; + +bool in_irq_stack(unsigned long stack, struct stack_info *info); +bool in_task_stack(unsigned long stack, struct task_struct *task, struct stack_info *info); +int get_stack_info(unsigned long stack, struct task_struct *task, struct stack_info *info); + #define STR_LONG_L __stringify(LONG_L) #define STR_LONG_S __stringify(LONG_S) #define STR_LONGSIZE __stringify(LONGSIZE) diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/asm/unwind.h new file mode 100644 index 000000000000..206fcbe24c0a --- /dev/null +++ b/arch/loongarch/include/asm/unwind.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Most of this ideas comes from x86. + * + * Copyright (C) 2022 Loongson Technology Corporation Limited + */ +#ifndef _ASM_UNWIND_H +#define _ASM_UNWIND_H + +#include <linux/sched.h> + +#include <asm/stacktrace.h> + +struct unwind_state { + struct stack_info stack_info; + struct task_struct *task; + bool first, error; + unsigned long sp, pc; +}; + +void unwind_start(struct unwind_state *state, + struct task_struct *task, struct pt_regs *regs); +bool unwind_next_frame(struct unwind_state *state); +unsigned long unwind_get_return_address(struct unwind_state *state); + +static inline bool unwind_done(struct unwind_state *state) +{ + return state->stack_info.type == STACK_TYPE_UNKNOWN; +} + +static inline bool unwind_error(struct unwind_state *state) +{ + return state->error; +} + +#endif /* _ASM_UNWIND_H */ |