Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/stacktrace: Fix arch_stack_walk_reliable()

The changes to copy_thread() made in commit eed7c420aac7 ("powerpc:
copy_thread differentiate kthreads and user mode threads") inadvertently
broke arch_stack_walk_reliable() because it has knowledge of the stack
layout.

Fix it by changing the condition to match the new logic in
copy_thread(). The changes make the comments about the stack layout
incorrect, rather than rephrasing them just refer the reader to
copy_thread().

Also the comment about the stack backchain is no longer true, since
commit edbd0387f324 ("powerpc: copy_thread add a back chain to the
switch stack frame"), so remove that as well.

Fixes: eed7c420aac7 ("powerpc: copy_thread differentiate kthreads and user mode threads")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230921232441.1181843-1-mpe@ellerman.id.au

+5 -22
+5 -22
arch/powerpc/kernel/stacktrace.c
··· 73 73 bool firstframe; 74 74 75 75 stack_end = stack_page + THREAD_SIZE; 76 - if (!is_idle_task(task)) { 77 - /* 78 - * For user tasks, this is the SP value loaded on 79 - * kernel entry, see "PACAKSAVE(r13)" in _switch() and 80 - * system_call_common(). 81 - * 82 - * Likewise for non-swapper kernel threads, 83 - * this also happens to be the top of the stack 84 - * as setup by copy_thread(). 85 - * 86 - * Note that stack backlinks are not properly setup by 87 - * copy_thread() and thus, a forked task() will have 88 - * an unreliable stack trace until it's been 89 - * _switch()'ed to for the first time. 90 - */ 91 - stack_end -= STACK_USER_INT_FRAME_SIZE; 92 - } else { 93 - /* 94 - * idle tasks have a custom stack layout, 95 - * c.f. cpu_idle_thread_init(). 96 - */ 76 + 77 + // See copy_thread() for details. 78 + if (task->flags & PF_KTHREAD) 97 79 stack_end -= STACK_FRAME_MIN_SIZE; 98 - } 80 + else 81 + stack_end -= STACK_USER_INT_FRAME_SIZE; 99 82 100 83 if (task == current) 101 84 sp = current_stack_frame();