Hi Dave, I've reworked patch about ppc "bt" problem discussed in https://www.redhat.com/archives/crash-utility/2012-June/msg00029.html A patch is now getting to work only for ppc targets, and notes are relocatecd in first ppc's "bt", not in initialization-time. And I've tested both "bt" diskdump by makedumpfile and netdump by /proc/vmcore with patched kernel like void crash_save_cpu(struct pt_regs *regs, int cpu) if ((cpu % 2)) return; I was worried about beeing able to catch all of non-contiguous NT_PRSTATUS notes, alternate with invalid odd notes in every process well, so I modified test case this time (that's no problem, everything OK). [After initialization: notes are not relocated yet] crash> help -D | grep notes num_prstatus_notes: 4 notes_buf: 107a3518 notes[0]: 107a3518 notes[1]: 107a3638 notes[2]: 107a3758 notes[3]: 107a3878 [Relocate in first bt(only once) and display correctly] crash> bt PID: 1000 TASK: eb0cf800 CPU: 4 COMMAND: "bash" bt: WARNING: cpu#1: not saved crash_notes bt: WARNING: cpu#3: not saved crash_notes bt: WARNING: cpu#5: not saved crash_notes bt: WARNING: cpu#7: not saved crash_notes R0: 00000001 R1: ea11be60 R2: eb0cf800 R3: 00000063 R4: 00000000 R5: ffffffff R6: c043ba2c R7: 00000000 R8: 00008000 R9: 00000000 R10: 00000000 R11: ea11be70 R12: 28242444 R13: 100b8448 R14: 100b07b8 R15: 100b0894 R16: 00000000 R17: 00000000 R18: 00000000 R19: 1006d270 R20: 00000000 R21: 100f02e0 R22: 00000000 R23: 00000001 R24: c08f1ac8 R25: 00029002 R26: c08f1bac R27: c08d0000 R28: 00000000 R29: c09ada48 R30: 00000063 R31: ea11be60 NIP: c0423378 MSR: 00021002 OR3: c09ada48 CTR: c0423344 LR: c0423d8c XER: 00000000 CCR: 28242444 MQ: 00008000 DAR: 00000000 DSISR: 00800000 Syscall Result: ea11be60 NIP [00000000c0423378] sysrq_handle_crash LR [00000000c0423d8c] __handle_sysrq => PC: c0423378 (sysrq_handle_crash+52) FP: ea11be60 #0 [ea11be60] sysrq_handle_crash at c0423378 #1 [ea11be70] __handle_sysrq at c0423d8c #2 [ea11bea0] write_sysrq_trigger at c0423ed0 #3 [ea11beb0] proc_reg_write at c01a79a4 #4 [ea11bee0] vfs_write at c014ba44 #5 [ea11bf00] sys_write at c014bcd8 #6 [ea11bf40] ret_from_syscall at c0013834 syscall [c00] exception frame: R0: 00000004 R1: bfe54e00 R2: 48027f80 R3: 00000001 R4: 4811d000 R5: 00000002 R6: 00000000 R7: 00000001 R8: 00000000 R9: 00000000 R10: 00000000 R11: 00000200 R12: 28242442 R13: 100b8448 R14: 100b07b8 R15: 100b0894 R16: 00000000 R17: 00000000 R18: 00000000 R19: 1006d270 R20: 00000000 R21: 100f02e0 R22: 1006b4d0 R23: 00000001 R24: 100b0000 R25: 1009b474 R26: bfe54ec8 R27: 00000002 R28: 0fefa400 R29: 4811d000 R30: 0fef9ff4 R31: 00000002 NIP: 0fe61494 MSR: 0002f902 OR3: 00000001 CTR: 0fe06fec LR: 0fe07050 XER: 00000000 CCR: 28242444 MQ: 00000000 DAR: 4811d000 DSISR: 00800000 Syscall Result: 00000000 [notes has been relocated: Counts num_prstatus_notes even if NULL] crash> help -D | grep notes num_prstatus_notes: 8 notes_buf: 107a3518 notes[0]: 107a3518 notes[1]: 0 notes[2]: 107a3638 notes[3]: 0 notes[4]: 107a3758 notes[5]: 0 notes[6]: 107a3878 notes[7]: 0 Thanks, Toshi
Date: Thu, 21 Jun 2012 10:39:45 +0900 Subject: [PATCH] ppc: fix up back trace for panic or active tasks problem When dump file is not contained enough NT_PRSTATUS notes for all online cpus, ppc diskdump and netdump can not do correct "bt". Relocate NT_PRSTATUS instances into corresponding cpu maps. This can do only once when first "bt" command is required. I couldn't found out good entry point for this while initialization time. Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- diskdump.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- netdump.c | 3 ++ ppc.c | 2 + 3 files changed, 85 insertions(+), 1 deletions(-) diff --git a/diskdump.c b/diskdump.c index e3f04e8..4781659 100644 --- a/diskdump.c +++ b/diskdump.c @@ -1012,12 +1012,91 @@ get_diskdump_panic_task(void) extern void get_netdump_regs_x86(struct bt_info *, ulong *, ulong *); extern void get_netdump_regs_x86_64(struct bt_info *, ulong *, ulong *); +/* + * Try to relocate NT_PRSTATUS notes according by in kernel crash_notes. + * Function is only called from ppc's get_regs. + */ + +static int +verify_crash_note_in_kernel_ppc(int cpu) +{ + int ret; + Elf32_Nhdr *note32; + ulong crash_notes_ptr; + char *buf, *name; + + ret = TRUE; + if (!readmem(symbol_value("crash_notes"), KVADDR, &crash_notes_ptr, + sizeof(ulong), "crash_notes", QUIET|RETURN_ON_ERROR) || + !crash_notes_ptr) + goto out; + + buf = GETBUF(SIZE(note_buf)); + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + crash_notes_ptr += kt->__per_cpu_offset[cpu]; + if (!readmem(crash_notes_ptr, KVADDR, buf, SIZE(note_buf), + "cpu crash_notes", QUIET|RETURN_ON_ERROR)) + goto freebuf; + + note32 = (Elf32_Nhdr *)buf; + name = (char *)(note32 + 1); + if (note32->n_type != NT_PRSTATUS || + note32->n_namesz != strlen("CORE") + 1 || + strncmp(name, "CORE", note32->n_namesz) || + note32->n_descsz != SIZE(elf_prstatus)) + ret = FALSE; +freebuf: + FREEBUF(buf); +out: + return ret; +} + +void +relocate_nt_prstatus_percpu_ppc(void **nt_prstatus_percpu, + int *num_prstatus_notes) +{ + static int relocated = FALSE; + void **nt_ptr; + int i, j, nrcpus; + size_t size; + + /* relocation is possible only once */ + if (relocated == TRUE) + return; + relocated = TRUE; + if (!symbol_exists("crash_notes") || + !VALID_STRUCT(note_buf) || !VALID_STRUCT(elf_prstatus)) + return; + + size = NR_CPUS * sizeof(void *); + nt_ptr = (void **)GETBUF(size); + BCOPY(nt_prstatus_percpu, nt_ptr, size); + BZERO(nt_prstatus_percpu, size); + + *num_prstatus_notes = 0; + nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS); + for (i = 0, j = 0; i < nrcpus; i++) { + if (!in_cpu_map(ONLINE, i)) + continue; + if (verify_crash_note_in_kernel_ppc(i)) + nt_prstatus_percpu[i] = nt_ptr[j++]; + else if (CRASHDEBUG(1)) + error(WARNING, "cpu#%d: not saved crash_notes\n", i); + /* num_prstatus_notes is always equal to online cpus in ppc */ + (*num_prstatus_notes)++; + } + FREEBUF(nt_ptr); +} + static void get_diskdump_regs_ppc(struct bt_info *bt, ulong *eip, ulong *esp) { Elf32_Nhdr *note; int len; + if (KDUMP_CMPRS_VALID()) + relocate_nt_prstatus_percpu_ppc(dd->nt_prstatus_percpu, + &dd->num_prstatus_notes); if (KDUMP_CMPRS_VALID() && (bt->task == tt->panic_task || (is_task_active(bt->task) && dd->num_prstatus_notes > 1))) { @@ -1030,7 +1109,7 @@ get_diskdump_regs_ppc(struct bt_info *bt, ulong *eip, ulong *esp) "panic" : "active", bt->task); len = sizeof(Elf32_Nhdr); len = roundup(len + note->n_namesz, 4); - bt->machdep = (void *)((char *)note + len + + bt->machdep = (void *)((char *)note + len + MEMBER_OFFSET("elf_prstatus", "pr_reg")); } diff --git a/netdump.c b/netdump.c index 51bbc35..6cfc1e9 100644 --- a/netdump.c +++ b/netdump.c @@ -2589,12 +2589,15 @@ next_sysrq: machdep->get_stack_frame(bt, eip, esp); } +extern void relocate_nt_prstatus_percpu_ppc(void **, int *); static void get_netdump_regs_ppc(struct bt_info *bt, ulong *eip, ulong *esp) { Elf32_Nhdr *note; size_t len; + relocate_nt_prstatus_percpu_ppc(nd->nt_prstatus_percpu, + &nd->num_prstatus_notes); if ((bt->task == tt->panic_task) || (is_task_active(bt->task) && nd->num_prstatus_notes > 1)) { /* diff --git a/ppc.c b/ppc.c index bc5f201..7c5f3be 100755 --- a/ppc.c +++ b/ppc.c @@ -414,6 +414,8 @@ ppc_init(int when) symbol_exists("hardirq_ctx")) STRUCT_SIZE_INIT(irq_ctx, "hardirq_ctx"); + STRUCT_SIZE_INIT(note_buf, "note_buf_t"); + STRUCT_SIZE_INIT(elf_prstatus, "elf_prstatus"); break; case POST_INIT: -- 1.7.0.4
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility