Commit 429a9671 authored by Jinyang He's avatar Jinyang He Committed by Huacai Chen

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: default avatarJinyang He <hejinyang@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent e2f27392
...@@ -191,20 +191,14 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) ...@@ -191,20 +191,14 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
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, ...@@ -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, ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment