Hello Dave, I attach patches which are updating powerpc based on linux-2.6.27. Please review them. Following updates have been done but some of them could not test yet because of constraints in environment. (Non-SMP powerpc virtual machine of qemu can only use) - Get rid of __func__. symbols (patch 0001) This patch can delete such symbols from command output like crash> sym -l | grep __func__ -m 3 c03604ac (r) __func__.21434 c0360500 (r) __func__.21333 c0360508 (r) __func__.21309 - Minor updates (patch 0002/0003/0004) ppc_processor_speed() support "ibm,extended-clock-frequency" [Not tested] ppc_get_smp_cpus() can return correct cpu numbers on SMP [Not tested] "bt", "mach" can handle (tt->flags & IRQSTACKS) [Not tested] - Enhancement of "bt" (patch 0005/0006/0007/0008) Detect exeption frame of linux-2.6 style ("bt" can dispaly '+' parts of below) Some functions are cleanuped with ppc64's. * Link Register of nested exception frame could not be tested. This may require the exception in kernel mode like oops but can not try kernel dump for a while... crash> bt 1 PID: 1 TASK: c8818000 CPU: 0 COMMAND: "init" #0 [c881da10] schedule at c0356ac4 #1 [c881da70] schedule_timeout at c0357468 #2 [c881dab0] do_select at c00c4758 #3 [c881dd90] core_sys_select at c00c4bd0 #4 [c881dee0] sys_select at c00c52b0 #5 [c881df30] ppc_select at c00053c0 #6 [c881df40] ret_from_syscall at c0011f64 + syscall [c01] exception frame: +R0: 0000008e R1: b8c11a60 R2: 48008660 R3: 0000000b +R4: b8c11cac R5: 00000000 R6: 00000000 R7: b8c11b24 +R8: 00000000 R9: 00000400 R10: 00000000 R11: 0ff24b2c +R12: 0ff1b8ec R13: 100207f0 +NIP: 0ff24b40 MSR: 0000d032 OR3: 0000000b CTR: 0ff24b2c +LR: 10005314 XER: 00000000 CCR: 24002462 MQ: 00000000 +DAR: 0ffb4cd0 DSISR: 0a000000 Syscall Result: 00000000 Still remaining the parts of PPC update and I have to setup more useful environment for the tests as soon as possible. Thanks, Toshi.
>From 89d6a242ed95f9a50f99bf75aa08a71556a336ce Mon Sep 17 00:00:00 2001 From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> Date: Thu, 27 Oct 2011 11:19:20 +0900 Subject: [PATCH 8/8] ppc: handle link register Porting from ppc64. Add link register of exception frame handling and newpc is also cleanuped with new LR macro. Ported BT_FULL parts from ppc64. Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- defs.h | 1 + ppc.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 11 deletions(-) diff --git a/defs.h b/defs.h index 022af0d..212c561 100755 --- a/defs.h +++ b/defs.h @@ -2616,6 +2616,7 @@ struct load_module { #define _MAX_PHYSMEM_BITS 44 #define STACK_FRAME_OVERHEAD 16 +#define STACK_FRAME_LR_SAVE (sizeof(ulong)) #define STACK_FRAME_MARKER (2 * sizeof(ulong)) #define STACK_FRAME_REGS_MARKER 0x72656773 #define PPC_STACK_SIZE 8192 diff --git a/ppc.c b/ppc.c index f2adff0..a6e67fd 100755 --- a/ppc.c +++ b/ppc.c @@ -53,10 +53,11 @@ static void ppc_back_trace_cmd(struct bt_info *); static void ppc_back_trace(struct gnu_request *, struct bt_info *); static void get_ppc_frame(struct bt_info *, ulong *, ulong *); static void ppc_print_stack_entry(int,struct gnu_request *, - ulong, char *, struct bt_info *); + ulong, ulong, struct bt_info *); static char *ppc_check_eframe(struct ppc_pt_regs *); static void ppc_print_eframe(char *, struct ppc_pt_regs *, struct bt_info *); static void ppc_print_regs(struct ppc_pt_regs *); +static void ppc_display_full_frame(struct bt_info *, ulong, FILE *); static void ppc_dump_irq(int); static ulong ppc_get_pc(struct bt_info *); static ulong ppc_get_sp(struct bt_info *); @@ -839,6 +840,7 @@ static void ppc_back_trace(struct gnu_request *req, struct bt_info *bt) { int frame = 0; + ulong lr = 0; ulong newpc = 0, newsp, marker; int eframe_found; @@ -859,7 +861,8 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt) while (INSTACK(req->sp, bt)) { newsp = *(ulong *)&bt->stackbuf[req->sp - bt->stackbase]; if (IS_KVADDR(newsp) && INSTACK(newsp, bt)) - newpc = *(ulong *)&bt->stackbuf[newsp + 4 - + newpc = *(ulong *)&bt->stackbuf[newsp + + STACK_FRAME_LR_SAVE - bt->stackbase]; if ((req->name = closest_symbol(req->pc)) == NULL) { error(FATAL, @@ -869,8 +872,9 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt) } bt->flags |= BT_SAVE_LASTSP; - ppc_print_stack_entry(frame, req, req->pc, req->name, bt); + ppc_print_stack_entry(frame, req, newsp, lr, bt); bt->flags &= ~(ulonglong)BT_SAVE_LASTSP; + lr = 0; if (BT_REFERENCE_FOUND(bt)) return; @@ -908,6 +912,7 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt) efrm_str = ppc_check_eframe(®s); if (efrm_str) { ppc_print_eframe(efrm_str, ®s, bt); + lr = regs.link; newpc = regs.nip; newsp = regs.gpr[1]; } @@ -924,45 +929,112 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt) return; } +static void +ppc_display_full_frame(struct bt_info *bt, ulong nextsp, FILE *ofp) +{ + int i, u_idx; + ulong *nip; + ulong words, addr; + char buf[BUFSIZE]; + + if (!INSTACK(nextsp, bt)) + nextsp = bt->stacktop; + + words = (nextsp - bt->frameptr) / sizeof(ulong); + addr = bt->frameptr; + u_idx = (bt->frameptr - bt->stackbase)/sizeof(ulong); + for (i = 0; i < words; i++, u_idx++) { + if (!(i & 1)) + fprintf(ofp, "%s %lx: ", i ? "\n" : "", addr); + + nip = (ulong *)(&bt->stackbuf[u_idx*sizeof(ulong)]); + fprintf(ofp, "%s ", format_stack_entry(bt, buf, *nip, 0)); + addr += sizeof(ulong); + } + fprintf(ofp, "\n"); +} + /* * print one entry of a stack trace */ static void ppc_print_stack_entry(int frame, struct gnu_request *req, - ulong callpc, - char *name, + ulong newsp, + ulong lr, struct bt_info *bt) { struct load_module *lm; + char *lrname = NULL; if (BT_REFERENCE_CHECK(bt)) { switch (bt->ref->cmdflags & (BT_REF_SYMBOL|BT_REF_HEXVAL)) { case BT_REF_SYMBOL: - if (STREQ(name, bt->ref->str)) + if (STREQ(req->name, bt->ref->str)) bt->ref->cmdflags |= BT_REF_FOUND; break; case BT_REF_HEXVAL: - if (bt->ref->hexval == callpc) + if (bt->ref->hexval == req->pc) bt->ref->cmdflags |= BT_REF_FOUND; break; } } else { fprintf(fp, "%s#%d [%lx] %s at %lx", frame < 10 ? " " : "", frame, - req->sp, name, callpc); - if (module_symbol(callpc, NULL, &lm, NULL, 0)) + req->sp, req->name, req->pc); + if (module_symbol(req->pc, NULL, &lm, NULL, 0)) fprintf(fp, " [%s]", lm->mod_name); - fprintf(fp, "\n"); + + if (req->ra) { + /* + * Previous frame is an exception one. If the func + * symbol for the current frame is same as with + * the previous frame's LR value, print "(unreliable)". + */ + lrname = closest_symbol(req->ra); + req->ra = 0; + if (!lrname) { + if (CRASHDEBUG(1)) + error(FATAL, + "ppc_back_trace hit unknown symbol (%lx).\n", + req->ra); + return; + } + } + if (lr) { + /* + * Link register value for an expection frame. + */ + if ((lrname = closest_symbol(lr)) == NULL) { + if (CRASHDEBUG(1)) + error(FATAL, + "ppc_back_trace hit unknown symbol (%lx).\n", + lr); + return; + } + if (req->pc != lr) { + fprintf(fp, "\n [Link Register ] "); + fprintf(fp, " [%lx] %s at %lx", + req->sp, lrname, lr); + } + req->ra = lr; + } + if (!req->name || STREQ(req->name,lrname)) + fprintf(fp, " (unreliable)"); + fprintf(fp, "\n"); } if (bt->flags & BT_SAVE_LASTSP) req->lastsp = req->sp; + bt->frameptr = req->sp; + if (bt->flags & BT_FULL) + if (IS_KVADDR(newsp)) + ppc_display_full_frame(bt, newsp, fp); if (bt->flags & BT_LINE_NUMBERS) - ppc_dump_line_number(callpc); + ppc_dump_line_number(req->pc); } /* -- 1.7.6.rc2.11.g13b7
>From 1916480dfe14989dbd9346ddbc1ec5efbd28a8ce Mon Sep 17 00:00:00 2001 From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> Date: Tue, 25 Oct 2011 11:19:03 +0900 Subject: [PATCH 1/8] ppc: update symbol table Porting from ppc64. Get rid of __func__. symbols from symbol table at ppc_verify_symbol(). This update gives effect for some command results, example: [Before] crash> sym -l | grep __func__ -m 3 c03604ac (r) __func__.21434 c0360500 (r) __func__.21333 c0360508 (r) __func__.21309 [After] => disappeared Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/ppc.c b/ppc.c index 1ec8e70..b17143b 100755 --- a/ppc.c +++ b/ppc.c @@ -599,7 +599,7 @@ ppc_verify_symbol(const char *name, ulong value, char type) machdep->flags |= KSYMS_START; return (name && strlen(name) && (machdep->flags & KSYMS_START) && - !STREQ(name, "Letext")); + !STREQ(name, "Letext") && !STRNEQ(name, "__func__.")); } -- 1.7.6.rc2.11.g13b7
>From f769af54e9f80a98a54404545adf6893953f8959 Mon Sep 17 00:00:00 2001 From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> Date: Tue, 25 Oct 2011 11:35:30 +0900 Subject: [PATCH 2/8] ppc: update processor frequency Porting from ppc64. Add "ibm,extended-clock-frequency" device property which is appeared in the ppc common code arch/powerpc/kernel/time.c. Fix indent nearby readmem(). Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 43 ++++++++++++++++++++++++++++--------------- 1 files changed, 28 insertions(+), 15 deletions(-) diff --git a/ppc.c b/ppc.c index b17143b..60d4028 100755 --- a/ppc.c +++ b/ppc.c @@ -523,15 +523,28 @@ ppc_processor_speed(void) "clock frequency value", FAULT_ON_ERROR); mhz /= 1000000; - + break; + } else if(len && (strcasecmp(str_buf, + "ibm,extended-clock-frequency") == 0)){ + /* found the right cpu property */ + + readmem(properties+ + OFFSET(property_value), + KVADDR, &value, sizeof(ulong), + "clock freqency pointer", + FAULT_ON_ERROR); + readmem(value, KVADDR, &mhz, + sizeof(ulong), + "clock frequency value", + FAULT_ON_ERROR); + mhz /= 1000000; break; } /* keep looking */ - readmem(properties+ - OFFSET(property_next), - KVADDR, &properties, sizeof(ulong), - "property next", FAULT_ON_ERROR); + OFFSET(property_next), + KVADDR, &properties, sizeof(ulong), + "property next", FAULT_ON_ERROR); } if(!properties) { /* didn't find the cpu speed for some reason */ @@ -551,19 +564,19 @@ ppc_processor_speed(void) get_symbol_data("ppc_md", sizeof(void *), &ppc_md); readmem(ppc_md + - OFFSET(machdep_calls_setup_residual), - KVADDR, &md_setup_res, - sizeof(ulong), "ppc_md setup_residual", - FAULT_ON_ERROR); + OFFSET(machdep_calls_setup_residual), + KVADDR, &md_setup_res, + sizeof(ulong), "ppc_md setup_residual", + FAULT_ON_ERROR); if(prep_setup_res == md_setup_res) { - /* PREP machine */ + /* PREP machine */ readmem(res+ - OFFSET(RESIDUAL_VitalProductData)+ - OFFSET(VPD_ProcessorHz), - KVADDR, &mhz, sizeof(ulong), - "res VitalProductData", - FAULT_ON_ERROR); + OFFSET(RESIDUAL_VitalProductData)+ + OFFSET(VPD_ProcessorHz), + KVADDR, &mhz, sizeof(ulong), + "res VitalProductData", + FAULT_ON_ERROR); mhz = (mhz > 1024) ? mhz >> 20 : mhz; } -- 1.7.6.rc2.11.g13b7
>From c826e4f244fb5a369ccf44d566c9d84308fd5747 Mon Sep 17 00:00:00 2001 From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> Date: Tue, 25 Oct 2011 14:21:05 +0900 Subject: [PATCH 3/8] ppc: update get_smp_cpus Porting from ppc64. ppc_get_smp_cpus() returned kt->cpus for kt->cpus setting, won't overwrite cpus. Return get_cpus_online() which cpu_online_map is common symbol in powerpc kernel. [Before] maybe everytime print "1" even if SMP machine. crash> mach | grep CPUS CPUS: 1 crash> help -k | grep "cpus:" cpus: 1 [After] Could print correctable cpus (not tested yet) Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/ppc.c b/ppc.c index 60d4028..adcf239 100755 --- a/ppc.c +++ b/ppc.c @@ -1328,7 +1328,7 @@ ppc_dis_filter(ulong vaddr, char *inbuf, unsigned int output_radix) int ppc_get_smp_cpus(void) { - return kt->cpus; + return (get_cpus_online() > 0) ? get_cpus_online() : kt->cpus; } /* -- 1.7.6.rc2.11.g13b7
>From 83199eb1aced18b509c798bb9db9a90df8173c8e Mon Sep 17 00:00:00 2001 From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> Date: Fri, 28 Oct 2011 13:07:27 +0900 Subject: [PATCH 4/8] ppc: mach and bt can handle irq stack Porting from ppc64. When CONFIG_IRQSTACK is y (tt->flags & IRQSTACKS), mach command can show IRQ stacks and bt command can display backtrace in IRQ stacks. IRQ stack -> current task's stack switch can not support yet. Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 68 insertions(+), 1 deletions(-) diff --git a/ppc.c b/ppc.c index adcf239..ed21236 100755 --- a/ppc.c +++ b/ppc.c @@ -27,6 +27,7 @@ static int ppc_translate_pte(ulong, void *, ulonglong); static ulong ppc_processor_speed(void); static int ppc_eframe_search(struct bt_info *); +static ulong ppc_in_irqstack(ulong); static void ppc_back_trace_cmd(struct bt_info *); static void ppc_back_trace(struct gnu_request *, struct bt_info *); static void get_ppc_frame(struct bt_info *, ulong *, ulong *); @@ -155,6 +156,12 @@ ppc_init(int when) machdep->flags |= CPU_BOOKE; machdep->section_size_bits = _SECTION_SIZE_BITS; machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; + /* + * IRQ stacks are introduced in 2.6 and also configurable. + */ + if ((THIS_KERNEL_VERSION >= LINUX(2,6,0)) && + symbol_exists("hardirq_ctx")) + STRUCT_SIZE_INIT(irq_ctx, "hardirq_ctx"); break; case POST_INIT: @@ -762,6 +769,30 @@ ppc_eframe_search(struct bt_info *bt) return (error(FATAL, "ppc_eframe_search: function not written yet!\n")); } +static ulong +ppc_in_irqstack(ulong addr) +{ + int c; + + if (!(tt->flags & IRQSTACKS)) + return 0; + + for (c = 0; c < kt->cpus; c++) { + if (tt->hardirq_ctx[c]) { + if ((addr >= tt->hardirq_ctx[c]) && + (addr < (tt->hardirq_ctx[c] + SIZE(irq_ctx)))) + return tt->hardirq_ctx[c]; + } + if (tt->softirq_ctx[c]) { + if ((addr >= tt->softirq_ctx[c]) && + (addr < (tt->softirq_ctx[c] + SIZE(irq_ctx)))) + return tt->softirq_ctx[c]; + } + } + + return 0; +} + /* * Unroll a kernel stack. */ @@ -808,6 +839,20 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt) int frame; int done; + if (!INSTACK(req->sp, bt)) { + ulong irqstack; + + if ((irqstack = ppc_in_irqstack(req->sp))) { + bt->stackbase = irqstack; + bt->stacktop = bt->stackbase + SIZE(irq_ctx); + alter_stackbuf(bt); + } else { + if (CRASHDEBUG(1)) + fprintf(fp, "cannot find the stack info.\n"); + return; + } + } + for (frame = 0, done = FALSE; !done && (frame < 100); frame++) { if ((req->name = closest_symbol(req->pc)) == NULL) { error(FATAL, @@ -1360,6 +1405,7 @@ ppc_cmd_mach(void) static void ppc_display_machine_stats(void) { + int c; struct new_utsname *uts; char buf[BUFSIZE]; ulong mhz; @@ -1376,10 +1422,31 @@ ppc_display_machine_stats(void) fprintf(fp, "(unknown)\n"); fprintf(fp, " HZ: %d\n", machdep->hz); fprintf(fp, " PAGE SIZE: %d\n", PAGESIZE()); - fprintf(fp, " L1 CACHE SIZE: %d\n", l1_cache_size()); +// fprintf(fp, " L1 CACHE SIZE: %d\n", l1_cache_size()); fprintf(fp, "KERNEL VIRTUAL BASE: %lx\n", machdep->kvbase); fprintf(fp, "KERNEL VMALLOC BASE: %lx\n", vt->vmalloc_start); fprintf(fp, " KERNEL STACK SIZE: %ld\n", STACKSIZE()); + + if (tt->flags & IRQSTACKS) { + fprintf(fp, "HARD IRQ STACK SIZE: %ld\n", SIZE(irq_ctx)); + fprintf(fp, " HARD IRQ STACKS:\n"); + + for (c = 0; c < kt->cpus; c++) { + if (!tt->hardirq_ctx[c]) + break; + sprintf(buf, "CPU %d", c); + fprintf(fp, "%19s: %lx\n", buf, tt->hardirq_ctx[c]); + } + + fprintf(fp, "SOFT IRQ STACK SIZE: %ld\n", SIZE(irq_ctx)); + fprintf(fp, " SOFT IRQ STACKS:\n"); + for (c = 0; c < kt->cpus; c++) { + if (!tt->softirq_ctx[c]) + break; + sprintf(buf, "CPU %d", c); + fprintf(fp, "%19s: %lx\n", buf, tt->softirq_ctx[c]); + } + } } -- 1.7.6.rc2.11.g13b7
>From 1599ec683994f7b4b71a87680613e6a414efdf55 Mon Sep 17 00:00:00 2001 From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> Date: Wed, 26 Oct 2011 14:47:32 +0900 Subject: [PATCH 5/8] ppc: cleanup backtrace loop Porting from ppc64. Apply using newsp, newpc into stack frame loop. This can also avoid unnecessary readmem(). Drop loop limitation 100, use INSTACK(). Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 41 ++++++++++++++++++----------------------- 1 files changed, 18 insertions(+), 23 deletions(-) diff --git a/ppc.c b/ppc.c index ed21236..ff14827 100755 --- a/ppc.c +++ b/ppc.c @@ -836,8 +836,8 @@ ppc_back_trace_cmd(struct bt_info *bt) static void ppc_back_trace(struct gnu_request *req, struct bt_info *bt) { - int frame; - int done; + int frame = 0; + ulong newpc = 0, newsp; if (!INSTACK(req->sp, bt)) { ulong irqstack; @@ -853,44 +853,39 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt) } } - for (frame = 0, done = FALSE; !done && (frame < 100); frame++) { + while (INSTACK(req->sp, bt)) { + newsp = *(ulong *)&bt->stackbuf[req->sp - bt->stackbase]; + if (IS_KVADDR(newsp) && INSTACK(newsp, bt)) + newpc = *(ulong *)&bt->stackbuf[newsp + 4 - + bt->stackbase]; if ((req->name = closest_symbol(req->pc)) == NULL) { error(FATAL, - "ppc_back_trace hit unknown symbol (%lx).\n", + "ppc_back_trace hit unknown symbol (%lx).\n", req->pc); - req->ra = req->pc = 0; break; } bt->flags |= BT_SAVE_LASTSP; ppc_print_stack_entry(frame, req, req->pc, req->name, bt); bt->flags &= ~(ulonglong)BT_SAVE_LASTSP; - + if (BT_REFERENCE_FOUND(bt)) return; - /* get the next sp and ip values */ - readmem(req->sp, KVADDR, &req->sp, sizeof(ulong), - "stack frame", FAULT_ON_ERROR); - - /* an actual valid end of the back-chain! */ - if(req->sp == 0) - break; - - if((req->sp - req->lastsp) >= sizeof(struct ppc_pt_regs)) { + if((newsp - req->sp) >= sizeof(struct ppc_pt_regs)) { /* there might be an exception frame here... */ - ppc_exception_frame(req->lastsp, bt, req); - } else if(!IS_KVADDR(req->sp) || (req->sp < req->lastsp)) { + ppc_exception_frame(req->sp, bt, req); + } else if(!IS_KVADDR(newsp) || (newsp < req->sp)) { /* also possible one here... */ - ppc_exception_frame(req->lastsp, bt, req); + ppc_exception_frame(req->sp, bt, req); } - - if (!INSTACK(req->sp, bt) || - STREQ(req->name, "start_kernel")) + + if (STREQ(req->name, "start_kernel")) break; - readmem(req->sp+sizeof(long), KVADDR, &req->pc, sizeof(ulong), - "instruction pointer", FAULT_ON_ERROR); + req->pc = newpc; + req->sp = newsp; + frame++; } return; -- 1.7.6.rc2.11.g13b7
>From c65bd42bae131a6d225510f7e23848a6c2577898 Mon Sep 17 00:00:00 2001 From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> Date: Fri, 28 Oct 2011 13:45:31 +0900 Subject: [PATCH 6/8] ppc: update exception frame search Porting from ppc64. The backtrace of ppc can handle exception frame and print frame information for linux-2.6 style by checking exception frame marker. Clear LS-4bits of trap register when refer exception number for linux-2.6. Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- defs.h | 2 ++ ppc.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/defs.h b/defs.h index 970b78e..022af0d 100755 --- a/defs.h +++ b/defs.h @@ -2616,6 +2616,8 @@ struct load_module { #define _MAX_PHYSMEM_BITS 44 #define STACK_FRAME_OVERHEAD 16 +#define STACK_FRAME_MARKER (2 * sizeof(ulong)) +#define STACK_FRAME_REGS_MARKER 0x72656773 #define PPC_STACK_SIZE 8192 #endif /* PPC */ diff --git a/ppc.c b/ppc.c index ff14827..1bbde2c 100755 --- a/ppc.c +++ b/ppc.c @@ -837,7 +837,8 @@ static void ppc_back_trace(struct gnu_request *req, struct bt_info *bt) { int frame = 0; - ulong newpc = 0, newsp; + ulong newpc = 0, newsp, marker; + int eframe_found; if (!INSTACK(req->sp, bt)) { ulong irqstack; @@ -872,13 +873,31 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt) if (BT_REFERENCE_FOUND(bt)) return; - if((newsp - req->sp) >= sizeof(struct ppc_pt_regs)) { - /* there might be an exception frame here... */ - ppc_exception_frame(req->sp, bt, req); - } else if(!IS_KVADDR(newsp) || (newsp < req->sp)) { - /* also possible one here... */ - ppc_exception_frame(req->sp, bt, req); + eframe_found = FALSE; + /* + * Is this frame an execption one? + * In 2.6, 0x72656773 is saved and used + * to determine the execption frame. + */ + if (THIS_KERNEL_VERSION < LINUX(2,6,0)) { + if (frame && (newsp - req->sp - STACK_FRAME_OVERHEAD >= + sizeof(struct ppc_pt_regs))) + /* there might be an exception frame here... */ + eframe_found = TRUE; + /* also possible ones here... */ + else if(!IS_KVADDR(newsp) || (newsp < req->sp)) + eframe_found = TRUE; + else if (STREQ(req->name, ".ret_from_except")) + eframe_found = TRUE; + } else if ((newsp - req->sp - STACK_FRAME_OVERHEAD) >= + sizeof(struct ppc_pt_regs)){ + readmem(req->sp + STACK_FRAME_MARKER, KVADDR, &marker, + sizeof(ulong), "frame marker", FAULT_ON_ERROR); + if (marker == STACK_FRAME_REGS_MARKER) + eframe_found = TRUE; } + if (eframe_found) + ppc_exception_frame(req->sp, bt, req); if (STREQ(req->name, "start_kernel")) break; @@ -944,10 +963,10 @@ ppc_exception_frame(ulong addr, struct bt_info *bt, struct gnu_request *req) if (BT_REFERENCE_CHECK(bt)) return; - readmem(addr+16, KVADDR, ®s, sizeof(regs), + readmem(addr + STACK_FRAME_OVERHEAD, KVADDR, ®s, sizeof(regs), "exception frame", FAULT_ON_ERROR); - switch(regs.trap) { + switch(regs.trap & ~0xF) { case 0x200: fprintf(fp, "machine check"); break; -- 1.7.6.rc2.11.g13b7
>From 365a7175685413fa58d8773c992ea1b04013a27b Mon Sep 17 00:00:00 2001 From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> Date: Fri, 28 Oct 2011 13:59:29 +0900 Subject: [PATCH 7/8] ppc: devided exception frame printer function Porting from ppc64. This update can also get rid of unused GIP[14-31] field for linux-2.6. Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 175 +++++++++++++++++++++++++++++++++++----------------------------- 1 files changed, 96 insertions(+), 79 deletions(-) diff --git a/ppc.c b/ppc.c index 1bbde2c..f2adff0 100755 --- a/ppc.c +++ b/ppc.c @@ -17,6 +17,27 @@ #ifdef PPC #include "defs.h" +/* + * This structure was copied from kernel source + * in include/asm-ppc/ptrace.h + */ +struct ppc_pt_regs { + long gpr[32]; + long nip; + long msr; + long orig_gpr3; /* Used for restarting system calls */ + long ctr; + long link; + long xer; + long ccr; + long mq; /* 601 only (not used at present) */ + /* Used on APUS to hold IPL value. */ + long trap; /* Reason for being here */ + long dar; /* Fault registers */ + long dsisr; + long result; /* Result of a system call */ +}; + static int ppc_kvtop(struct task_context *, ulong, physaddr_t *, int); static int ppc_uvtop(struct task_context *, ulong, physaddr_t *, int); static ulong ppc_vmalloc_start(void); @@ -33,7 +54,9 @@ static void ppc_back_trace(struct gnu_request *, struct bt_info *); static void get_ppc_frame(struct bt_info *, ulong *, ulong *); static void ppc_print_stack_entry(int,struct gnu_request *, ulong, char *, struct bt_info *); -static void ppc_exception_frame(ulong, struct bt_info *, struct gnu_request *); +static char *ppc_check_eframe(struct ppc_pt_regs *); +static void ppc_print_eframe(char *, struct ppc_pt_regs *, struct bt_info *); +static void ppc_print_regs(struct ppc_pt_regs *); static void ppc_dump_irq(int); static ulong ppc_get_pc(struct bt_info *); static ulong ppc_get_sp(struct bt_info *); @@ -742,27 +765,6 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused) * Look for likely exception frames in a stack. */ -/* - * This structure was copied from kernel source - * in include/asm-ppc/ptrace.h - */ -struct ppc_pt_regs { - long gpr[32]; - long nip; - long msr; - long orig_gpr3; /* Used for restarting system calls */ - long ctr; - long link; - long xer; - long ccr; - long mq; /* 601 only (not used at present) */ - /* Used on APUS to hold IPL value. */ - long trap; /* Reason for being here */ - long dar; /* Fault registers */ - long dsisr; - long result; /* Result of a system call */ -}; - static int ppc_eframe_search(struct bt_info *bt) { @@ -896,8 +898,20 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt) if (marker == STACK_FRAME_REGS_MARKER) eframe_found = TRUE; } - if (eframe_found) - ppc_exception_frame(req->sp, bt, req); + if (eframe_found) { + char *efrm_str; + struct ppc_pt_regs regs; + + readmem(req->sp + STACK_FRAME_OVERHEAD, KVADDR, ®s, + sizeof(struct ppc_pt_regs), + "exception frame", FAULT_ON_ERROR); + efrm_str = ppc_check_eframe(®s); + if (efrm_str) { + ppc_print_eframe(efrm_str, ®s, bt); + newpc = regs.nip; + newsp = regs.gpr[1]; + } + } if (STREQ(req->name, "start_kernel")) break; @@ -952,65 +966,47 @@ ppc_print_stack_entry(int frame, } /* - * Print exception frame information for PowerPC + * Check whether the frame is exception one! */ -static void -ppc_exception_frame(ulong addr, struct bt_info *bt, struct gnu_request *req) +static char * +ppc_check_eframe(struct ppc_pt_regs *regs) { - int i; - struct ppc_pt_regs regs; - - if (BT_REFERENCE_CHECK(bt)) - return; - - readmem(addr + STACK_FRAME_OVERHEAD, KVADDR, ®s, sizeof(regs), - "exception frame", FAULT_ON_ERROR); - - switch(regs.trap & ~0xF) { + switch(regs->trap & ~0xF) { case 0x200: - fprintf(fp, "machine check"); - break; + return "machine check"; case 0x300: - fprintf(fp, "address error (store)"); - break; + return "address error (store)"; case 0x400: - fprintf(fp, "instruction bus error"); - break; + return "instruction bus error"; case 0x500: - fprintf(fp, "interrupt"); - break; + return "interrupt"; case 0x600: - fprintf(fp, "alingment"); - break; + return "alingment"; case 0x700: - fprintf(fp, "breakpoint trap"); - break; + return "breakpoint trap"; case 0x800: - fprintf(fp, "fpu unavailable"); - break; + return "fpu unavailable"; case 0x900: - fprintf(fp, "decrementer"); - break; + return "decrementer"; case 0xa00: - fprintf(fp, "reserved"); - break; + return "reserved"; case 0xb00: - fprintf(fp, "reserved"); - break; + return "reserved"; case 0xc00: - fprintf(fp, "syscall"); - break; + return "syscall"; case 0xd00: - fprintf(fp, "single-step/watch"); - break; + return "single-step/watch"; case 0xe00: - fprintf(fp, "fp assist"); - break; - default: /* back trace ended, but no exception frame exists */ - return; + return "fp assist"; } + /* No exception frame exists */ + return NULL; +} - fprintf(fp, " [%lx] exception frame:", regs.trap); +static void +ppc_print_regs(struct ppc_pt_regs *regs) +{ + int i; /* print out the gprs... */ for(i=0; i<32; i++) { @@ -1018,24 +1014,45 @@ ppc_exception_frame(ulong addr, struct bt_info *bt, struct gnu_request *req) fprintf(fp, "\n"); fprintf(fp, "R%d:%s %08lx ", i, - ((i < 10) ? " " : ""), regs.gpr[i]); + ((i < 10) ? " " : ""), regs->gpr[i]); + /* + * In 2.6, some stack frame contains only partial regs set. + * For the partial set, only 14 regs will be saved and trap + * field will contain 1 in the least significant bit. + */ + if ((i == 13) && (regs->trap & 1)) + break; } fprintf(fp, "\n"); /* print out the rest of the registers */ - fprintf(fp, "NIP: %08lx ", regs.nip); - fprintf(fp, "MSR: %08lx ", regs.msr); - fprintf(fp, "OR3: %08lx ", regs.orig_gpr3); - fprintf(fp, "CTR: %08lx\n", regs.ctr); - - fprintf(fp, "LR: %08lx ", regs.link); - fprintf(fp, "XER: %08lx ", regs.xer); - fprintf(fp, "CCR: %08lx ", regs.ccr); - fprintf(fp, "MQ: %08lx\n", regs.mq); - fprintf(fp, "DAR: %08lx ", regs.dar); - fprintf(fp, "DSISR: %08lx ", regs.dsisr); - fprintf(fp, " Syscall Result: %08lx\n", regs.result); + fprintf(fp, "NIP: %08lx ", regs->nip); + fprintf(fp, "MSR: %08lx ", regs->msr); + fprintf(fp, "OR3: %08lx ", regs->orig_gpr3); + fprintf(fp, "CTR: %08lx\n", regs->ctr); + + fprintf(fp, "LR: %08lx ", regs->link); + fprintf(fp, "XER: %08lx ", regs->xer); + fprintf(fp, "CCR: %08lx ", regs->ccr); + fprintf(fp, "MQ: %08lx\n", regs->mq); + fprintf(fp, "DAR: %08lx ", regs->dar); + fprintf(fp, "DSISR: %08lx ", regs->dsisr); + fprintf(fp, " Syscall Result: %08lx\n", regs->result); +} + +/* + * Print the exception frame information + */ +static void +ppc_print_eframe(char *efrm_str, struct ppc_pt_regs *regs, struct bt_info *bt) +{ + if (BT_REFERENCE_CHECK(bt)) + return; + + fprintf(fp, " %s [%lx] exception frame:", efrm_str, regs->trap); + ppc_print_regs(regs); + fprintf(fp, "\n"); } /* -- 1.7.6.rc2.11.g13b7
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility