[PATCH] LoongArch: Check unwind_error() in arch_stack_walk()

From: Tiezhu Yang
Date: Tue Mar 21 2023 - 02:29:25 EST


We can see the following messages with CONFIG_PROVE_LOCKING=y on
LoongArch:

BUG: MAX_STACK_TRACE_ENTRIES too low!
turning off the locking correctness validator.

This is because stack_trace_save() returns a big value after call
arch_stack_walk(), here is the call trace:

save_trace()
stack_trace_save()
arch_stack_walk()
stack_trace_consume_entry()

arch_stack_walk() should return immediately if unwind_next_frame()
failed, no need to do the useless loops to increase the value of
c->len in stack_trace_consume_entry(), then we can fix the above
problem.

Reported-by: Guenter Roeck <linux@xxxxxxxxxxxx>
Link: https://lore.kernel.org/all/8a44ad71-68d2-4926-892f-72bfc7a67e2a@xxxxxxxxxxxx/
Signed-off-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>
---
arch/loongarch/kernel/stacktrace.c | 3 ++-
arch/loongarch/kernel/unwind.c | 1 +
arch/loongarch/kernel/unwind_prologue.c | 4 +++-
3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c
index 3a690f9..7c15ba5 100644
--- a/arch/loongarch/kernel/stacktrace.c
+++ b/arch/loongarch/kernel/stacktrace.c
@@ -30,7 +30,8 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,

regs->regs[1] = 0;
for (unwind_start(&state, task, regs);
- !unwind_done(&state); unwind_next_frame(&state)) {
+ !unwind_done(&state) && !unwind_error(&state);
+ unwind_next_frame(&state)) {
addr = unwind_get_return_address(&state);
if (!addr || !consume_entry(cookie, addr))
break;
diff --git a/arch/loongarch/kernel/unwind.c b/arch/loongarch/kernel/unwind.c
index a463d69..ba324ba 100644
--- a/arch/loongarch/kernel/unwind.c
+++ b/arch/loongarch/kernel/unwind.c
@@ -28,5 +28,6 @@ bool default_next_frame(struct unwind_state *state)

} while (!get_stack_info(state->sp, state->task, info));

+ state->error = true;
return false;
}
diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kernel/unwind_prologue.c
index 9095fde..55afc27 100644
--- a/arch/loongarch/kernel/unwind_prologue.c
+++ b/arch/loongarch/kernel/unwind_prologue.c
@@ -211,7 +211,7 @@ static bool next_frame(struct unwind_state *state)
pc = regs->csr_era;

if (user_mode(regs) || !__kernel_text_address(pc))
- return false;
+ goto out;

state->first = true;
state->pc = pc;
@@ -226,6 +226,8 @@ static bool next_frame(struct unwind_state *state)

} while (!get_stack_info(state->sp, state->task, info));

+out:
+ state->error = true;
return false;
}

--
2.1.0