Hi, Aditya
On 1/22/24 17:24, Aditya Gupta wrote:
Hi Lianbo,
Just a ping for the series. Any pending reviews for upstreaming it ?
Please wait for another ack.
Maybe Kazu is doing some tests for the patch set or reviewing it.
Thanks
Lianbo
Thanks,
Aditya Gupta
On Mon, Jan 08, 2024 at 04:38:20PM +0800, Lianbo Jiang wrote:
> Hi, Aditya
>
> Thank you for the great job.
>
> The v6 patch set looks good to me, and I did not see any new issues in my
> tests.
>
> So for the v6: Ack.
>
>
> Thanks
>
> Lianbo
>
> On 1/5/24 15:31, devel-request(a)lists.crash-utility.osci.io wrote:
>
>> Date: Fri, 5 Jan 2024 13:00:23 +0530
>> From: Aditya Gupta<adityag(a)linux.ibm.com>
>> Subject: [Crash-utility] [PATCH v6 1/5] ppc64: correct gdb
>> passthroughs by implementing machdep->get_cpu_reg
>> To:<devel@lists.crash-utility.osci.io>,<lijiang@redhat.com>,
>> Tao Liu<ltao(a)redhat.com>
>> Cc: Mahesh J Salgaonkar<mahesh(a)linux.ibm.com>, "Naveen N. Rao"
>> <naveen.n.rao(a)linux.vnet.ibm.com>
>> Message-ID:<20240105073027.378928-2-adityag@linux.ibm.com>
>> Content-Type: text/plain; charset=UTF-8
>>
>> Currently, gdb passthroughs of 'bt', 'frame', 'up',
'down', 'info
>> locals' don't work. This is due to gdb not knowing the register values
to
>> unwind the stack frames
>>
>> Every gdb passthrough goes through `gdb_interface`. And then, gdb expects
>> `crash_target::fetch_registers` to give it the register values, which is
>> dependent on `machdep->get_cpu_reg` to read the register values for
>> specific architecture.
>>
>> ┌────────────────────────┐
>> gdb passthrough (eg. "bt") │ │
>> crash ─────────────────────────▶│ │
>> │ gdb_interface │
>> │ │
>> │ │
>> │ ┌────────────────────┐ │
>> fetch_registers │ │ │ │
>> crash_target◀────────────────────────┼─┤ gdb │ │
>> ─────────────────────────┼▶│ │ │
>> Registers (SP,NIP, etc.)│ │ │ │
>> │ │ │ │
>> │ └────────────────────┘ │
>> └────────────────────────┘
>>
>> Implement `machdep->get_cpu_reg` on PPC64, so that crash provides the
>> register values to gdb to unwind stack frames properly
>>
>> With these changes, on powerpc, 'bt' command output in gdb mode, will
look
>> like this:
>>
>> gdb> bt
>> #0 0xc0000000002a53e8 in crash_setup_regs (oldregs=<optimized out>,
newregs=0xc00000000486f8d8) at ./arch/powerpc/include/asm/kexec.h:69
>> #1 __crash_kexec (regs=<optimized out>) at kernel/kexec_core.c:974
>> #2 0xc000000000168918 in panic (fmt=<optimized out>) 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=0xc000000009ed3a80) 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=0xc00000009dda7d00,
buf=buf@entry=0xebcfc7c6040 <error: Cannot access memory at address 0xebcfc7c6040>,
count=count@entry=2, pos=pos@entry=0xc00000000486fda0) at fs/read_write.c:582
>>
>> instead of earlier output without this patch:
>>
>> gdb> bt
>> #0 <unavailable> in ?? ()
>> Backtrace stopped: previous frame identical to this frame (corrupt stack?)
>>
>> Also, 'get_dumpfile_regs' has been introduced to get registers from
>> multiple supported vmcore formats. Correspondingly a flag
'BT_NO_PRINT_REGS'
>> has been introduced to tell helper functions to get registers, to not
>> print registers with every call to backtrace in gdb.
>>
>> Note: This feature to support GDB unwinding doesn't support live
debugging
>>
>> Signed-off-by: Aditya Gupta<adityag(a)linux.ibm.com>
>> ---
>> defs.h | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> kernel.c | 33 +++++++++++++++
>> ppc64.c | 105 +++++++++++++++++++++++++++++++++++++++++++++--
>> 3 files changed, 257 insertions(+), 3 deletions(-)
>>
>> diff --git a/defs.h b/defs.h
>> index 5218a94fe4a4..615f3a37935a 100644
>> --- a/defs.h
>> +++ b/defs.h
>> @@ -6023,6 +6023,7 @@ int load_module_symbols_helper(char *);
>> void unlink_module(struct load_module *);
>> int check_specified_module_tree(char *, char *);
>> int is_system_call(char *, ulong);
>> +void get_dumpfile_regs(struct bt_info*, ulong*, ulong*);
>> void generic_dump_irq(int);
>> void generic_get_irq_affinity(int);
>> void generic_show_interrupts(int, ulong *);
>> @@ -6121,6 +6122,7 @@ ulong cpu_map_addr(const char *type);
>> #define BT_REGS_NOT_FOUND (0x4000000000000ULL)
>> #define BT_OVERFLOW_STACK (0x8000000000000ULL)
>> #define BT_SKIP_IDLE (0x10000000000000ULL)
>> +#define BT_NO_PRINT_REGS (0x20000000000000ULL)
>> #define BT_SYMBOL_OFFSET (BT_SYMBOLIC_ARGS)
>> #define BT_REF_HEXVAL (0x1)
>> @@ -7854,4 +7856,124 @@ enum x86_64_regnum {
>> LAST_REGNUM
>> };
>> +/*
>> + * Register numbers to make crash_target->fetch_registers()
>> + * ---> machdep->get_cpu_reg() work properly.
>> + *
>> + * These register numbers and names are given according to output of
>> + * `rs6000_register_name`, because that is what was being used by
>> + * crash_target::fetch_registers in case of PPC64
>> + */
>> +enum ppc64_regnum {
>> + PPC64_R0_REGNUM = 0,
>> + PPC64_R1_REGNUM,
>> + PPC64_R2_REGNUM,
>> + PPC64_R3_REGNUM,
>> + PPC64_R4_REGNUM,
>> + PPC64_R5_REGNUM,
>> + PPC64_R6_REGNUM,
>> + PPC64_R7_REGNUM,
>> + PPC64_R8_REGNUM,
>> + PPC64_R9_REGNUM,
>> + PPC64_R10_REGNUM,
>> + PPC64_R11_REGNUM,
>> + PPC64_R12_REGNUM,
>> + PPC64_R13_REGNUM,
>> + PPC64_R14_REGNUM,
>> + PPC64_R15_REGNUM,
>> + PPC64_R16_REGNUM,
>> + PPC64_R17_REGNUM,
>> + PPC64_R18_REGNUM,
>> + PPC64_R19_REGNUM,
>> + PPC64_R20_REGNUM,
>> + PPC64_R21_REGNUM,
>> + PPC64_R22_REGNUM,
>> + PPC64_R23_REGNUM,
>> + PPC64_R24_REGNUM,
>> + PPC64_R25_REGNUM,
>> + PPC64_R26_REGNUM,
>> + PPC64_R27_REGNUM,
>> + PPC64_R28_REGNUM,
>> + PPC64_R29_REGNUM,
>> + PPC64_R30_REGNUM,
>> + PPC64_R31_REGNUM,
>> +
>> + PPC64_F0_REGNUM = 32,
>> + PPC64_F1_REGNUM,
>> + PPC64_F2_REGNUM,
>> + PPC64_F3_REGNUM,
>> + PPC64_F4_REGNUM,
>> + PPC64_F5_REGNUM,
>> + PPC64_F6_REGNUM,
>> + PPC64_F7_REGNUM,
>> + PPC64_F8_REGNUM,
>> + PPC64_F9_REGNUM,
>> + PPC64_F10_REGNUM,
>> + PPC64_F11_REGNUM,
>> + PPC64_F12_REGNUM,
>> + PPC64_F13_REGNUM,
>> + PPC64_F14_REGNUM,
>> + PPC64_F15_REGNUM,
>> + PPC64_F16_REGNUM,
>> + PPC64_F17_REGNUM,
>> + PPC64_F18_REGNUM,
>> + PPC64_F19_REGNUM,
>> + PPC64_F20_REGNUM,
>> + PPC64_F21_REGNUM,
>> + PPC64_F22_REGNUM,
>> + PPC64_F23_REGNUM,
>> + PPC64_F24_REGNUM,
>> + PPC64_F25_REGNUM,
>> + PPC64_F26_REGNUM,
>> + PPC64_F27_REGNUM,
>> + PPC64_F28_REGNUM,
>> + PPC64_F29_REGNUM,
>> + PPC64_F30_REGNUM,
>> + PPC64_F31_REGNUM,
>> +
>> + PPC64_PC_REGNUM = 64,
>> + PPC64_MSR_REGNUM = 65,
>> + PPC64_CR_REGNUM = 66,
>> + PPC64_LR_REGNUM = 67,
>> + PPC64_CTR_REGNUM = 68,
>> + PPC64_XER_REGNUM = 69,
>> + PPC64_FPSCR_REGNUM = 70,
>> +
>> + PPC64_VR0_REGNUM = 106,
>> + PPC64_VR1_REGNUM,
>> + PPC64_VR2_REGNUM,
>> + PPC64_VR3_REGNUM,
>> + PPC64_VR4_REGNUM,
>> + PPC64_VR5_REGNUM,
>> + PPC64_VR6_REGNUM,
>> + PPC64_VR7_REGNUM,
>> + PPC64_VR8_REGNUM,
>> + PPC64_VR9_REGNUM,
>> + PPC64_VR10_REGNUM,
>> + PPC64_VR11_REGNUM,
>> + PPC64_VR12_REGNUM,
>> + PPC64_VR13_REGNUM,
>> + PPC64_VR14_REGNUM,
>> + PPC64_VR15_REGNUM,
>> + PPC64_VR16_REGNUM,
>> + PPC64_VR17_REGNUM,
>> + PPC64_VR18_REGNUM,
>> + PPC64_VR19_REGNUM,
>> + PPC64_VR20_REGNUM,
>> + PPC64_VR21_REGNUM,
>> + PPC64_VR22_REGNUM,
>> + PPC64_VR23_REGNUM,
>> + PPC64_VR24_REGNUM,
>> + PPC64_VR25_REGNUM,
>> + PPC64_VR26_REGNUM,
>> + PPC64_VR27_REGNUM,
>> + PPC64_VR28_REGNUM,
>> + PPC64_VR29_REGNUM,
>> + PPC64_VR30_REGNUM,
>> + PPC64_VR31_REGNUM,
>> +
>> + PPC64_VSCR_REGNUM = 138,
>> + PPC64_VRSAVE_REGNU = 139
>> +};
>> +
>> #endif /* !GDB_COMMON */
>> diff --git a/kernel.c b/kernel.c
>> index 6dcf414693e6..52b7ba09f390 100644
>> --- a/kernel.c
>> +++ b/kernel.c
>> @@ -3533,6 +3533,39 @@ get_lkcd_regs(struct bt_info *bt, ulong *eip, ulong *esp)
>> machdep->get_stack_frame(bt, eip, esp);
>> }
>> +void
>> +get_dumpfile_regs(struct bt_info *bt, ulong *eip, ulong *esp)
>> +{
>> + bt->flags |= BT_NO_PRINT_REGS;
>> +
>> + if (NETDUMP_DUMPFILE())
>> + get_netdump_regs(bt, eip, esp);
>> + else if (KDUMP_DUMPFILE())
>> + get_kdump_regs(bt, eip, esp);
>> + else if (DISKDUMP_DUMPFILE())
>> + get_diskdump_regs(bt, eip, esp);
>> + else if (KVMDUMP_DUMPFILE())
>> + get_kvmdump_regs(bt, eip, esp);
>> + else if (LKCD_DUMPFILE())
>> + get_lkcd_regs(bt, eip, esp);
>> + else if (XENDUMP_DUMPFILE())
>> + get_xendump_regs(bt, eip, esp);
>> + else if (SADUMP_DUMPFILE())
>> + get_sadump_regs(bt, eip, esp);
>> + else if (VMSS_DUMPFILE())
>> + get_vmware_vmss_regs(bt, eip, esp);
>> + else if (REMOTE_PAUSED()) {
>> + if (!is_task_active(bt->task) || !get_remote_regs(bt, eip, esp))
>> + machdep->get_stack_frame(bt, eip, esp);
>> + } else
>> + machdep->get_stack_frame(bt, eip, esp);
>> +
>> + bt->flags &= ~BT_NO_PRINT_REGS;
>> +
>> + bt->instptr = *eip;
>> + bt->stkptr = *esp;
>> +}
>> +
>> /*
>> * Store the head of the kernel module list for future use.
>> diff --git a/ppc64.c b/ppc64.c
>> index e8930a139e0d..ea4821d86b9e 100644
>> --- a/ppc64.c
>> +++ b/ppc64.c
>> @@ -55,6 +55,8 @@ static void ppc64_set_bt_emergency_stack(enum
emergency_stack_type type,
>> static char * ppc64_check_eframe(struct ppc64_pt_regs *);
>> static void ppc64_print_eframe(char *, struct ppc64_pt_regs *,
>> struct bt_info *);
>> +static int ppc64_get_cpu_reg(int cpu, int regno, const char *name, int size,
>> + void *value);
>> static void parse_cmdline_args(void);
>> static int ppc64_paca_percpu_offset_init(int);
>> static void ppc64_init_cpu_info(void);
>> @@ -704,6 +706,8 @@ ppc64_init(int when)
>> error(FATAL, "cannot malloc hwirqstack buffer space.");
>> }
>> + machdep->get_cpu_reg = ppc64_get_cpu_reg;
>> +
>> ppc64_init_paca_info();
>> if (!machdep->hz) {
>> @@ -2501,6 +2505,99 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs
*regs,
>> ppc64_print_nip_lr(regs, 1);
>> }
>> +static int
>> +ppc64_get_cpu_reg(int cpu, int regno, const char *name, int size,
>> + void *value)
>> +{
>> + struct bt_info bt_info, bt_setup;
>> + struct task_context *tc;
>> + struct ppc64_pt_regs *pt_regs;
>> + ulong ip, sp;
>> +
>> + if (LIVE()) {
>> + /* doesn't support reading registers in live dump */
>> + return FALSE;
>> + }
>> +
>> + /* Currently only handling registers available in ppc64_pt_regs:
>> + *
>> + * 0-31: r0-r31
>> + * 64: pc/nip
>> + * 65: msr
>> + *
>> + * 67: lr
>> + * 68: ctr
>> + */
>> + switch (regno) {
>> + case PPC64_R0_REGNUM ... PPC64_R31_REGNUM:
>> +
>> + case PPC64_PC_REGNUM:
>> + case PPC64_MSR_REGNUM:
>> + case PPC64_LR_REGNUM:
>> + case PPC64_CTR_REGNUM:
>> + break;
>> +
>> + default:
>> + // return false if we can't get that register
>> + if (CRASHDEBUG(1))
>> + error(WARNING, "unsupported register, regno=%d\n", regno);
>> + return FALSE;
>> + }
>> +
>> + tc = CURRENT_CONTEXT();
>> + BZERO(&bt_setup, sizeof(struct bt_info));
>> + clone_bt_info(&bt_setup, &bt_info, tc);
>> + fill_stackbuf(&bt_info);
>> +
>> + // reusing the get_dumpfile_regs function to get pt regs structure
>> + get_dumpfile_regs(&bt_info, &sp, &ip);
>> + pt_regs = (struct ppc64_pt_regs *)bt_info.machdep;
>> +
>> + if (!pt_regs) {
>> + error(WARNING, "pt_regs not available for cpu %d\n", cpu);
>> + return FALSE;
>> + }
>> +
>> + switch (regno) {
>> + case PPC64_R0_REGNUM ... PPC64_R31_REGNUM:
>> + if (size != sizeof(pt_regs->gpr[regno]))
>> + return FALSE; // size mismatch
>> +
>> + memcpy(value, &pt_regs->gpr[regno], size);
>> + break;
>> +
>> + case PPC64_PC_REGNUM:
>> + if (size != sizeof(pt_regs->nip))
>> + return FALSE; // size mismatch
>> +
>> + memcpy(value, &pt_regs->nip, size);
>> + break;
>> +
>> + case PPC64_MSR_REGNUM:
>> + if (size != sizeof(pt_regs->msr))
>> + return FALSE; // size mismatch
>> +
>> + memcpy(value, &pt_regs->msr, size);
>> + break;
>> +
>> + case PPC64_LR_REGNUM:
>> + if (size != sizeof(pt_regs->link))
>> + return FALSE; // size mismatch
>> +
>> + memcpy(value, &pt_regs->link, size);
>> + break;
>> +
>> + case PPC64_CTR_REGNUM:
>> + if (size != sizeof(pt_regs->ctr))
>> + return FALSE; // size mismatch
>> +
>> + memcpy(value, &pt_regs->ctr, size);
>> + break;
>> + }
>> +
>> + return TRUE;
>> +}
>> +
>> /*
>> * For vmcore typically saved with KDump or FADump, get SP and IP values
>> * from the saved ptregs.
>> @@ -2613,9 +2710,11 @@ ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in,
ulong *nip, ulong *ksp)
>> pt_regs = (struct ppc64_pt_regs *)bt->machdep;
>> ur_nip = pt_regs->nip;
>> ur_ksp = pt_regs->gpr[1];
>> - /* Print the collected regs for panic task. */
>> - ppc64_print_regs(pt_regs);
>> - ppc64_print_nip_lr(pt_regs, 1);
>> + if (!(bt->flags & BT_NO_PRINT_REGS)) {
>> + /* Print the collected regs for panic task. */
>> + ppc64_print_regs(pt_regs);
>> + ppc64_print_nip_lr(pt_regs, 1);
>> + }
>> } else if ((pc->flags & KDUMP) ||
>> ((pc->flags & DISKDUMP) &&
>> (*diskdump_flags & KDUMP_CMPRS_LOCAL))) {
>> -- 2.43.0