linux/arch/powerpc
Aditya Gupta 3786416e1f powerpc: update ppc_save_regs to save current r1 in pt_regs
[ Upstream commit b684c09f09 ]

ppc_save_regs() skips one stack frame while saving the CPU register states.
Instead of saving current R1, it pulls the previous stack frame pointer.

When vmcores caused by direct panic call (such as `echo c >
/proc/sysrq-trigger`), are debugged with gdb, gdb fails to show the
backtrace correctly. On further analysis, it was found that it was because
of mismatch between r1 and NIP.

GDB uses NIP to get current function symbol and uses corresponding debug
info of that function to unwind previous frames, but due to the
mismatching r1 and NIP, the unwinding does not work, and it fails to
unwind to the 2nd frame and hence does not show the backtrace.

GDB backtrace with vmcore of kernel without this patch:

---------
(gdb) bt
 #0  0xc0000000002a53e8 in crash_setup_regs (oldregs=<optimized out>,
    newregs=0xc000000004f8f8d8) at ./arch/powerpc/include/asm/kexec.h:69
 #1  __crash_kexec (regs=<optimized out>) at kernel/kexec_core.c:974
 #2  0x0000000000000063 in ?? ()
 #3  0xc000000003579320 in ?? ()
---------

Further analysis revealed that the mismatch occurred because
"ppc_save_regs" was saving the previous stack's SP instead of the current
r1. This patch fixes this by storing current r1 in the saved pt_regs.

GDB backtrace with vmcore of patched kernel:

--------
(gdb) bt
 #0  0xc0000000002a53e8 in crash_setup_regs (oldregs=0x0, newregs=0xc00000000670b8d8)
    at ./arch/powerpc/include/asm/kexec.h:69
 #1  __crash_kexec (regs=regs@entry=0x0) at kernel/kexec_core.c:974
 #2  0xc000000000168918 in panic (fmt=fmt@entry=0xc000000001654a60 "sysrq triggered crash\n")
    at kernel/panic.c:358
 #3  0xc000000000b735f8 in sysrq_handle_crash (key=<optimized out>) at drivers/tty/sysrq.c:155
 #4  0xc000000000b742cc in __handle_sysrq (key=key@entry=99, check_mask=check_mask@entry=false)
    at drivers/tty/sysrq.c:602
 #5  0xc000000000b7506c in write_sysrq_trigger (file=<optimized out>, buf=<optimized out>,
    count=2, ppos=<optimized out>) at drivers/tty/sysrq.c:1163
 #6  0xc00000000069a7bc in pde_write (ppos=<optimized out>, count=<optimized out>,
    buf=<optimized out>, file=<optimized out>, pde=0xc00000000362cb40) at fs/proc/inode.c:340
 #7  proc_reg_write (file=<optimized out>, buf=<optimized out>, count=<optimized out>,
    ppos=<optimized out>) at fs/proc/inode.c:352
 #8  0xc0000000005b3bbc in vfs_write (file=file@entry=0xc000000006aa6b00,
    buf=buf@entry=0x61f498b4f60 <error: Cannot access memory at address 0x61f498b4f60>,
    count=count@entry=2, pos=pos@entry=0xc00000000670bda0) at fs/read_write.c:582
 #9  0xc0000000005b4264 in ksys_write (fd=<optimized out>,
    buf=0x61f498b4f60 <error: Cannot access memory at address 0x61f498b4f60>, count=2)
    at fs/read_write.c:637
 #10 0xc00000000002ea2c in system_call_exception (regs=0xc00000000670be80, r0=<optimized out>)
    at arch/powerpc/kernel/syscall.c:171
 #11 0xc00000000000c270 in system_call_vectored_common ()
    at arch/powerpc/kernel/interrupt_64.S:192
--------

Nick adds:
  So this now saves regs as though it was an interrupt taken in the
  caller, at the instruction after the call to ppc_save_regs, whereas
  previously the NIP was there, but R1 came from the caller's caller and
  that mismatch is what causes gdb's dwarf unwinder to go haywire.

Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Fixes: d16a58f885 ("powerpc: Improve ppc_save_regs()")
Reivewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230615091047.90433-1-adityag@linux.ibm.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
2023-07-23 13:47:13 +02:00
..
boot powerpc: dts: t1040rdb: fix compatible string for Rev A boards 2023-03-17 08:48:54 +01:00
configs Remove DECnet support from kernel 2023-06-21 15:59:15 +02:00
crypto powerpc: flexible GPR range save/restore macros 2022-07-12 16:35:02 +02:00
include powerpc/vmlinux.lds: Add an explicit symbol for the SRWX boundary 2023-02-25 12:06:44 +01:00
kernel powerpc: update ppc_save_regs to save current r1 in pt_regs 2023-07-23 13:47:13 +02:00
kexec powerpc: Set crashkernel offset to mid of RMA region 2022-04-13 20:59:03 +02:00
kvm KVM: PPC: Book3S HV: Fix "rm_exit" entry in debugfs timings 2022-08-25 11:40:40 +02:00
lib powerpc: flexible GPR range save/restore macros 2022-07-12 16:35:02 +02:00
math-emu powerpc/math_emu/efp: Include module.h 2022-10-26 12:35:21 +02:00
mm powerpc/64s/radix: Fix soft dirty tracking 2023-05-24 17:36:55 +01:00
net powerpc64/bpf: Limit 'ldbrx' to processors compliant with ISA v2.06 2022-02-01 17:27:09 +01:00
perf powerpc/imc-pmu: Revert nest_init_lock to being a mutex 2023-02-09 11:26:47 +01:00
platforms powerpc/powernv/sriov: perform null check on iov before dereferencing iov 2023-07-23 13:47:13 +02:00
purgatory powerpc/purgatory: remove PGO flags 2023-06-21 15:59:14 +02:00
sysdev powerpc/sysdev/tsi108: fix resource printk format warnings 2023-05-11 23:00:34 +09:00
tools powerpc/64: Add UADDR64 relocation support 2022-05-09 09:14:44 +02:00
xmon powerpc/xmon: Fix -Wswitch-unreachable warning in bpt_cmds 2022-12-31 13:14:35 +01:00
Kbuild
Kconfig powerpc/memhotplug: Add add_pages override for PPC 2022-07-07 17:53:28 +02:00
Kconfig.debug powerpc/ptdump: Convert powerpc to GENERIC_PTDUMP 2021-08-25 13:35:48 +10:00
Makefile powerpc: Remove linker flag from KBUILD_AFLAGS 2023-03-10 09:39:44 +01:00
Makefile.postlink