LoongArch: Get frame info in unwind_start() when regs is not available
authorJinyang He <hejinyang@loongson.cn>
Tue, 17 Jan 2023 03:42:16 +0000 (11:42 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Tue, 17 Jan 2023 03:42:16 +0000 (11:42 +0800)
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>
arch/loongarch/kernel/process.c
arch/loongarch/kernel/unwind_guess.c
arch/loongarch/kernel/unwind_prologue.c

index c583b1e..edfd220 100644 (file)
@@ -191,20 +191,14 @@ out:
 
 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;
index e2d2e4f..9ef5f2a 100644 (file)
@@ -26,6 +26,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;
index e98b004..613545c 100644 (file)
@@ -146,12 +146,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;