Skip to content

Commit

Permalink
LoongArch: Get frame info in unwind_start() when regs is not available
Browse files Browse the repository at this point in the history
[ Upstream commit 429a967 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
MQ-mengqing authored and gregkh committed Feb 6, 2023
1 parent a4a1af9 commit efc1058
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
12 changes: 3 additions & 9 deletions arch/loongarch/kernel/process.c
Expand Up @@ -185,20 +185,14 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)

unsigned long __get_wchan(struct task_struct *task)
{
unsigned long pc;
unsigned long pc = 0;
struct unwind_state state;

if (!try_get_task_stack(task))
return 0;

unwind_start(&state, task, NULL);
state.sp = thread_saved_fp(task);
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)) {
for (unwind_start(&state, task, NULL);
!unwind_done(&state); unwind_next_frame(&state)) {
pc = unwind_get_return_address(&state);
if (!pc)
break;
Expand Down
6 changes: 6 additions & 0 deletions arch/loongarch/kernel/unwind_guess.c
Expand Up @@ -25,6 +25,12 @@ void unwind_start(struct unwind_state *state, struct task_struct *task,
if (regs) {
state->sp = regs->regs[3];
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;
Expand Down
16 changes: 13 additions & 3 deletions arch/loongarch/kernel/unwind_prologue.c
Expand Up @@ -111,12 +111,22 @@ void unwind_start(struct unwind_state *state, struct task_struct *task,
struct pt_regs *regs)
{
memset(state, 0, sizeof(*state));
state->type = UNWINDER_PROLOGUE;

if (regs && __kernel_text_address(regs->csr_era)) {
state->pc = regs->csr_era;
if (regs) {
state->sp = regs->regs[3];
state->pc = regs->csr_era;
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;
Expand Down

0 comments on commit efc1058

Please sign in to comment.