-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Qing Zhang
authored and
Huacai Chen
committed
Aug 12, 2022
1 parent
dce6098
commit 4923277
Showing
7 changed files
with
200 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
config UNWINDER_GUESS | ||
bool "Guess unwinder" | ||
help | ||
This option enables the "guess" unwinder for unwinding kernel stack | ||
traces. It scans the stack and reports every kernel text address it | ||
finds. Some of the addresses it reports may be incorrect. | ||
|
||
While this option often produces false positives, it can still be | ||
useful in many cases. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copyright (C) 2022 Loongson Technology Corporation Limited | ||
*/ | ||
#include <linux/kernel.h> | ||
|
||
#include <asm/unwind.h> | ||
|
||
unsigned long unwind_get_return_address(struct unwind_state *state) | ||
{ | ||
if (unwind_done(state)) | ||
return 0; | ||
else if (state->first) | ||
return state->pc; | ||
|
||
return *(unsigned long *)(state->sp); | ||
} | ||
EXPORT_SYMBOL_GPL(unwind_get_return_address); | ||
|
||
void unwind_start(struct unwind_state *state, struct task_struct *task, | ||
struct pt_regs *regs) | ||
{ | ||
memset(state, 0, sizeof(*state)); | ||
|
||
if (regs) { | ||
state->sp = regs->regs[3]; | ||
state->pc = regs->csr_era; | ||
} | ||
|
||
state->task = task; | ||
state->first = true; | ||
|
||
get_stack_info(state->sp, state->task, &state->stack_info); | ||
|
||
if (!unwind_done(state) && !__kernel_text_address(state->pc)) | ||
unwind_next_frame(state); | ||
} | ||
EXPORT_SYMBOL_GPL(unwind_start); | ||
|
||
bool unwind_next_frame(struct unwind_state *state) | ||
{ | ||
struct stack_info *info = &state->stack_info; | ||
unsigned long addr; | ||
|
||
if (unwind_done(state)) | ||
return false; | ||
|
||
if (state->first) | ||
state->first = false; | ||
|
||
do { | ||
for (state->sp += sizeof(unsigned long); | ||
state->sp < info->end; | ||
state->sp += sizeof(unsigned long)) { | ||
addr = *(unsigned long *)(state->sp); | ||
|
||
if (__kernel_text_address(addr)) | ||
return true; | ||
} | ||
|
||
state->sp = info->next_sp; | ||
|
||
} while (!get_stack_info(state->sp, state->task, info)); | ||
|
||
return false; | ||
} | ||
EXPORT_SYMBOL_GPL(unwind_next_frame); |