Hello Lianbo,
On 22/01/24 15:18, Lianbo Jiang wrote:
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.
Sure Lianbo, thanks for the update.
Thanks,
Aditya Gupta
>
> 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
>