--- crash-4.0-2.21/ppc64.c.orig 2006-03-12 23:51:31.000000000 -0800 +++ crash-4.0-2.21/ppc64.c 2006-03-13 00:24:25.000000000 -0800 @@ -1184,8 +1184,12 @@ ppc64_back_trace(struct gnu_request *req ms->hwstacksize + STACK_FRAME_OVERHEAD; bt->stackbuf = ms->hwstackbuf; alter_stackbuf(bt); - } else - error(FATAL, "cannot find the stack info"); + } else { + if (CRASHDEBUG(1)) { + fprintf(fp, "cannot find the stack info.\n"); + } + return; + } } @@ -1493,9 +1497,19 @@ ppc64_kdump_stack_frame(struct bt_info * return FALSE; } *ksp = pt_regs->gpr[1]; - readmem(*ksp+16, KVADDR, &unip, sizeof(ulong), "Regs NIP value", - FAULT_ON_ERROR); - *nip = unip; + if (IS_KVADDR(*ksp)) { + readmem(*ksp+16, KVADDR, &unip, sizeof(ulong), "Regs NIP value", + FAULT_ON_ERROR); + *nip = unip; + } else { + if (IN_TASK_VMA(bt_in->task, *ksp)) + fprintf(fp, "%0lx: Task is running in user space\n", + bt_in->task); + else + fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n", + bt_in->task, *ksp); + *nip = pt_regs->nip; + } if (bt_in->flags && ((BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_PRINT|BT_TEXT_SYMBOLS_NOPRINT))) @@ -1505,7 +1519,9 @@ ppc64_kdump_stack_frame(struct bt_info * * Print the collected regs for the active task */ ppc64_print_regs(pt_regs); - + if (!IS_KVADDR(*ksp)) + return FALSE; + fprintf(fp, " NIP [%016lx] %s\n", pt_regs->nip, closest_symbol(pt_regs->nip)); if (unip != pt_regs->link) @@ -1538,7 +1554,7 @@ ppc64_get_dumpfile_stack_frame(struct bt /* * For the kdump vmcore, Use SP and IP values that are saved in ptregs. */ - if (pc->flags && KDUMP) + if (pc->flags & KDUMP) return ppc64_kdump_stack_frame(bt_in, nip, ksp); bt = &bt_local; @@ -2279,42 +2295,59 @@ parse_cmdline_arg(void) fprintf(fp, "\n"); } +/* + * Updating any smp-related items that were possibly bypassed + * or improperly initialized in kernel_init(). + */ static void ppc64_paca_init(void) { +#define BITS_FOR_LONG sizeof(ulong)*8 int i, cpus, nr_paca; char *cpu_paca_buf; ulong data_offset; - ulong per_cpu_offset; - ulong cpuid_offset; - signed short cpuid; + ulong cpu_online_map[NR_CPUS/BITS_FOR_LONG]; if (!symbol_exists("paca")) - return; + error(FATAL, "PPC64: Could not find 'paca' symbol\n"); + + if (!symbol_exists("cpu_online_map")) + error(FATAL, "PPC64: Could not find 'cpu_online_map' symbol\n"); if (!MEMBER_EXISTS("paca_struct", "data_offset")) return; STRUCT_SIZE_INIT(ppc64_paca, "paca_struct"); - cpuid_offset = MEMBER_OFFSET("paca_struct", "hw_cpu_id"); data_offset = MEMBER_OFFSET("paca_struct", "data_offset"); cpu_paca_buf = GETBUF(SIZE(ppc64_paca)); - if (!(nr_paca = get_array_length("paca", NULL, 0))) + if (!(nr_paca = get_array_length("paca", NULL, 0))) nr_paca = NR_CPUS; + if (nr_paca > NR_CPUS) { + error(WARNING, + "PPC64: Number of paca entries (%d) greater than NR_CPUS (%d)\n", + nr_paca, NR_CPUS); + error(FATAL, "Recompile crash with larger NR_CPUS\n"); + } + + readmem(symbol_value("cpu_online_map"), KVADDR, &cpu_online_map[0], + nr_paca/8, "cpu_online_map", FAULT_ON_ERROR); + for (i = cpus = 0; i < nr_paca; i++) { + div_t val = div(i, BITS_FOR_LONG); + /* + * CPU online? + */ + if (!(cpu_online_map[val.quot] & (0x1UL << val.rem))) + continue; + readmem(symbol_value("paca") + (i * SIZE(ppc64_paca)), KVADDR, cpu_paca_buf, SIZE(ppc64_paca), "paca entry", FAULT_ON_ERROR); - cpuid = SHORT(cpu_paca_buf + cpuid_offset); - if (cpuid == -1) - continue; - - per_cpu_offset = ULONG(cpu_paca_buf + data_offset); - kt->__per_cpu_offset[i] = per_cpu_offset; + kt->__per_cpu_offset[i] = ULONG(cpu_paca_buf + data_offset); kt->flags |= PER_CPU_OFF; cpus++; }