mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
LoongArch: Get frame info in unwind_start() when regs is not available
At unwind_start(), it is better to get its frame info here rather than get them outside, even we don't have 'regs'. In this way we can simply use unwind_{start, next_frame, done} outside. Signed-off-by: Jinyang He <hejinyang@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
parent
e2f2739227
commit
429a9671f2
@ -191,20 +191,14 @@ out:
|
|||||||
|
|
||||||
unsigned long __get_wchan(struct task_struct *task)
|
unsigned long __get_wchan(struct task_struct *task)
|
||||||
{
|
{
|
||||||
unsigned long pc;
|
unsigned long pc = 0;
|
||||||
struct unwind_state state;
|
struct unwind_state state;
|
||||||
|
|
||||||
if (!try_get_task_stack(task))
|
if (!try_get_task_stack(task))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unwind_start(&state, task, NULL);
|
for (unwind_start(&state, task, NULL);
|
||||||
state.sp = thread_saved_fp(task);
|
!unwind_done(&state); unwind_next_frame(&state)) {
|
||||||
get_stack_info(state.sp, state.task, &state.stack_info);
|
|
||||||
state.pc = thread_saved_ra(task);
|
|
||||||
#ifdef CONFIG_UNWINDER_PROLOGUE
|
|
||||||
state.type = UNWINDER_PROLOGUE;
|
|
||||||
#endif
|
|
||||||
for (; !unwind_done(&state); unwind_next_frame(&state)) {
|
|
||||||
pc = unwind_get_return_address(&state);
|
pc = unwind_get_return_address(&state);
|
||||||
if (!pc)
|
if (!pc)
|
||||||
break;
|
break;
|
||||||
|
@ -26,6 +26,12 @@ void unwind_start(struct unwind_state *state, struct task_struct *task,
|
|||||||
if (regs) {
|
if (regs) {
|
||||||
state->sp = regs->regs[3];
|
state->sp = regs->regs[3];
|
||||||
state->pc = regs->csr_era;
|
state->pc = regs->csr_era;
|
||||||
|
} else if (task && task != current) {
|
||||||
|
state->sp = thread_saved_fp(task);
|
||||||
|
state->pc = thread_saved_ra(task);
|
||||||
|
} else {
|
||||||
|
state->sp = (unsigned long)__builtin_frame_address(0);
|
||||||
|
state->pc = (unsigned long)__builtin_return_address(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->task = task;
|
state->task = task;
|
||||||
|
@ -146,12 +146,22 @@ void unwind_start(struct unwind_state *state, struct task_struct *task,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
memset(state, 0, sizeof(*state));
|
memset(state, 0, sizeof(*state));
|
||||||
|
state->type = UNWINDER_PROLOGUE;
|
||||||
|
|
||||||
if (regs && __kernel_text_address(regs->csr_era)) {
|
if (regs) {
|
||||||
state->pc = regs->csr_era;
|
|
||||||
state->sp = regs->regs[3];
|
state->sp = regs->regs[3];
|
||||||
|
state->pc = regs->csr_era;
|
||||||
state->ra = regs->regs[1];
|
state->ra = regs->regs[1];
|
||||||
state->type = UNWINDER_PROLOGUE;
|
if (!__kernel_text_address(state->pc))
|
||||||
|
state->type = UNWINDER_GUESS;
|
||||||
|
} else if (task && task != current) {
|
||||||
|
state->sp = thread_saved_fp(task);
|
||||||
|
state->pc = thread_saved_ra(task);
|
||||||
|
state->ra = 0;
|
||||||
|
} else {
|
||||||
|
state->sp = (unsigned long)__builtin_frame_address(0);
|
||||||
|
state->pc = (unsigned long)__builtin_return_address(0);
|
||||||
|
state->ra = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->task = task;
|
state->task = task;
|
||||||
|
Loading…
Reference in New Issue
Block a user