Commit fc8ab213 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/export

into samba.org:/scratch/anton/linux-2.5_ppc64
parents 979bd8fe 4f6b41e5
...@@ -18,7 +18,7 @@ KERNELLOAD := 0xc000000000000000 ...@@ -18,7 +18,7 @@ KERNELLOAD := 0xc000000000000000
LDFLAGS := -m elf64ppc LDFLAGS := -m elf64ppc
LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \
-mtraceback=full -mcpu=power4 -mcpu=power4
have_zero_bss := $(shell if $(CC) -fno-zero-initialized-in-bss -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) have_zero_bss := $(shell if $(CC) -fno-zero-initialized-in-bss -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/kallsyms.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -350,14 +351,11 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -350,14 +351,11 @@ int show_interrupts(struct seq_file *p, void *v)
return 0; return 0;
} }
extern char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen); static inline int handle_irq_event(int irq, struct pt_regs *regs,
struct irqaction *action)
static inline void handle_irq_event(int irq, struct pt_regs *regs,
struct irqaction *action)
{ {
int status = 0; int status = 0;
int retval = 0; int retval = 0;
struct irqaction *first_action = action;
if (!(action->flags & SA_INTERRUPT)) if (!(action->flags & SA_INTERRUPT))
local_irq_enable(); local_irq_enable();
...@@ -370,30 +368,90 @@ static inline void handle_irq_event(int irq, struct pt_regs *regs, ...@@ -370,30 +368,90 @@ static inline void handle_irq_event(int irq, struct pt_regs *regs,
if (status & SA_SAMPLE_RANDOM) if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq); add_interrupt_randomness(irq);
local_irq_disable(); local_irq_disable();
if (retval != 1) { return retval;
static int count = 100; }
char name_buf[256];
if (count) { static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
count--; {
if (retval) { struct irqaction *action;
printk("irq event %d: bogus retval mask %x\n",
irq, retval); if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
} else { printk(KERN_ERR "irq event %d: bogus return value %x\n",
printk("irq %d: nobody cared!\n", irq); irq, action_ret);
} } else {
dump_stack(); printk(KERN_ERR "irq %d: nobody cared!\n", irq);
printk("handlers:\n"); }
action = first_action; dump_stack();
do { printk(KERN_ERR "handlers:\n");
printk("[<%p>]", action->handler); action = desc->action;
printk(" (%s)\n", do {
ppc_find_proc_name((unsigned *)action->handler, name_buf, 256)); printk(KERN_ERR "[<%p>]", action->handler);
action = action->next; print_symbol(" (%s)",
} while (action); (unsigned long)action->handler);
} printk("\n");
action = action->next;
} while (action);
}
static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
{
static int count = 100;
if (count) {
count--;
__report_bad_irq(irq, desc, action_ret);
} }
} }
static int noirqdebug;
static int __init noirqdebug_setup(char *str)
{
noirqdebug = 1;
printk("IRQ lockup detection disabled\n");
return 1;
}
__setup("noirqdebug", noirqdebug_setup);
/*
* If 99,900 of the previous 100,000 interrupts have not been handled then
* assume that the IRQ is stuck in some manner. Drop a diagnostic and try to
* turn the IRQ off.
*
* (The other 100-of-100,000 interrupts may have been a correctly-functioning
* device sharing an IRQ with the failing one)
*
* Called under desc->lock
*/
static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret)
{
if (action_ret != IRQ_HANDLED) {
desc->irqs_unhandled++;
if (action_ret != IRQ_NONE)
report_bad_irq(irq, desc, action_ret);
}
desc->irq_count++;
if (desc->irq_count < 100000)
return;
desc->irq_count = 0;
if (desc->irqs_unhandled > 99900) {
/*
* The interrupt is stuck
*/
__report_bad_irq(irq, desc, action_ret);
/*
* Now kill the IRQ
*/
printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
desc->status |= IRQ_DISABLED;
desc->handler->disable(irq);
}
desc->irqs_unhandled = 0;
}
/* /*
* Eventually, this should take an array of interrupts and an array size * Eventually, this should take an array of interrupts and an array size
* so it can dispatch multiple interrupts. * so it can dispatch multiple interrupts.
...@@ -462,10 +520,13 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -462,10 +520,13 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
* SMP environment. * SMP environment.
*/ */
for (;;) { for (;;) {
irqreturn_t action_ret;
spin_unlock(&desc->lock); spin_unlock(&desc->lock);
handle_irq_event(irq, regs, action); action_ret = handle_irq_event(irq, regs, action);
spin_lock(&desc->lock); spin_lock(&desc->lock);
if (!noirqdebug)
note_interrupt(irq, desc, action_ret);
if (likely(!(desc->status & IRQ_PENDING))) if (likely(!(desc->status & IRQ_PENDING)))
break; break;
desc->status &= ~IRQ_PENDING; desc->status &= ~IRQ_PENDING;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/init_task.h> #include <linux/init_task.h>
#include <linux/prctl.h> #include <linux/prctl.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/kallsyms.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -130,12 +131,9 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -130,12 +131,9 @@ struct task_struct *__switch_to(struct task_struct *prev,
return last; return last;
} }
char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen);
void show_regs(struct pt_regs * regs) void show_regs(struct pt_regs * regs)
{ {
int i; int i;
char name_buf[256];
printk("NIP: %016lX XER: %016lX LR: %016lX\n", printk("NIP: %016lX XER: %016lX LR: %016lX\n",
regs->nip, regs->xer, regs->link); regs->nip, regs->xer, regs->link);
...@@ -170,8 +168,7 @@ void show_regs(struct pt_regs * regs) ...@@ -170,8 +168,7 @@ void show_regs(struct pt_regs * regs)
* above info out without failing * above info out without failing
*/ */
printk("NIP [%016lx] ", regs->nip); printk("NIP [%016lx] ", regs->nip);
printk("%s\n", ppc_find_proc_name((unsigned *)regs->nip, print_symbol("%s\n", regs->nip);
name_buf, 256));
show_stack(current, (unsigned long *)regs->gpr[1]); show_stack(current, (unsigned long *)regs->gpr[1]);
} }
...@@ -385,62 +382,6 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, ...@@ -385,62 +382,6 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
return error; return error;
} }
char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen)
{
unsigned long tb_flags;
unsigned short name_len;
unsigned long tb_start, code_start, code_ptr, code_offset;
unsigned int code_len;
unsigned long end;
strcpy(buf, "Unknown");
code_ptr = (unsigned long)p;
code_offset = 0;
/* handle functions in text and init sections */
if (((unsigned long)p >= (unsigned long)_stext) &&
((unsigned long)p < (unsigned long)_etext))
end = (unsigned long)_etext;
else if (((unsigned long)p >= (unsigned long)__init_begin) &&
((unsigned long)p < (unsigned long)__init_end))
end = (unsigned long)__init_end;
else
return buf;
while ((unsigned long)p < end) {
if (*p == 0) {
tb_start = (unsigned long)p;
++p; /* Point to traceback flags */
tb_flags = *((unsigned long *)p);
p += 2; /* Skip over traceback flags */
if (tb_flags & TB_NAME_PRESENT) {
if (tb_flags & TB_PARMINFO)
++p; /* skip over parminfo data */
if (tb_flags & TB_HAS_TBOFF) {
code_len = *p; /* get code length */
code_start = tb_start - code_len;
code_offset = code_ptr - code_start + 1;
if (code_offset > 0x100000)
break;
++p; /* skip over code size */
}
name_len = *((unsigned short *)p);
if (name_len > (buflen-20))
name_len = buflen-20;
memcpy(buf, ((char *)p)+2, name_len);
buf[name_len] = 0;
if (code_offset)
sprintf(buf+name_len, "+0x%lx",
code_offset-1);
}
break;
}
++p;
}
return buf;
}
/* /*
* These bracket the sleeping functions.. * These bracket the sleeping functions..
*/ */
...@@ -480,7 +421,6 @@ void show_stack(struct task_struct *p, unsigned long *_sp) ...@@ -480,7 +421,6 @@ void show_stack(struct task_struct *p, unsigned long *_sp)
unsigned long ip; unsigned long ip;
unsigned long stack_page = (unsigned long)p->thread_info; unsigned long stack_page = (unsigned long)p->thread_info;
int count = 0; int count = 0;
char name_buf[256];
unsigned long sp = (unsigned long)_sp; unsigned long sp = (unsigned long)_sp;
if (!p) if (!p)
...@@ -499,8 +439,7 @@ void show_stack(struct task_struct *p, unsigned long *_sp) ...@@ -499,8 +439,7 @@ void show_stack(struct task_struct *p, unsigned long *_sp)
if (__get_user(ip, (unsigned long *)(sp + 16))) if (__get_user(ip, (unsigned long *)(sp + 16)))
break; break;
printk("[%016lx] ", ip); printk("[%016lx] ", ip);
printk("%s\n", ppc_find_proc_name((unsigned *)ip, print_symbol("%s\n", ip);
name_buf, 256));
} while (count++ < 32); } while (count++ < 32);
} }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kallsyms.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/string.h> #include <asm/string.h>
#include <asm/prom.h> #include <asm/prom.h>
...@@ -27,6 +29,7 @@ ...@@ -27,6 +29,7 @@
#include <asm/paca.h> #include <asm/paca.h>
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/cputable.h> #include <asm/cputable.h>
#include "nonstdio.h" #include "nonstdio.h"
#include "privinst.h" #include "privinst.h"
...@@ -59,7 +62,6 @@ struct bpt { ...@@ -59,7 +62,6 @@ struct bpt {
unsigned instr; unsigned instr;
unsigned long count; unsigned long count;
unsigned char enabled; unsigned char enabled;
char funcname[64]; /* function name for humans */
}; };
#define NBPTS 16 #define NBPTS 16
...@@ -79,10 +81,6 @@ static void memex(void); ...@@ -79,10 +81,6 @@ static void memex(void);
static int bsesc(void); static int bsesc(void);
static void dump(void); static void dump(void);
static void prdump(unsigned long, long); static void prdump(unsigned long, long);
#ifdef __MWERKS__
static void prndump(unsigned, int);
static int nvreadb(unsigned);
#endif
static int ppc_inst_dump(unsigned long, long); static int ppc_inst_dump(unsigned long, long);
void print_address(unsigned long); void print_address(unsigned long);
static int getsp(void); static int getsp(void);
...@@ -105,7 +103,6 @@ static void take_input(char *); ...@@ -105,7 +103,6 @@ static void take_input(char *);
static unsigned long read_spr(int); static unsigned long read_spr(int);
static void write_spr(int, unsigned long); static void write_spr(int, unsigned long);
static void super_regs(void); static void super_regs(void);
static void print_sysmap(void);
static void remove_bpts(void); static void remove_bpts(void);
static void insert_bpts(void); static void insert_bpts(void);
static struct bpt *at_breakpoint(unsigned long pc); static struct bpt *at_breakpoint(unsigned long pc);
...@@ -181,6 +178,13 @@ static int xmon_trace[NR_CPUS]; ...@@ -181,6 +178,13 @@ static int xmon_trace[NR_CPUS];
static struct pt_regs *xmon_regs[NR_CPUS]; static struct pt_regs *xmon_regs[NR_CPUS];
void __xmon_print_symbol(const char *fmt, unsigned long address);
#define xmon_print_symbol(fmt, addr) \
do { \
__check_printsym_format(fmt, ""); \
__xmon_print_symbol(fmt, addr); \
} while(0)
/* /*
* Stuff for reading and writing memory safely * Stuff for reading and writing memory safely
*/ */
...@@ -209,42 +213,6 @@ extern inline void sync(void) ...@@ -209,42 +213,6 @@ extern inline void sync(void)
no functions have been called from the current function. no functions have been called from the current function.
*/ */
/*
A traceback table typically follows each function.
The find_tb_table() func will fill in this struct. Note that the struct
is not an exact match with the encoded table defined by the ABI. It is
defined here more for programming convenience.
*/
struct tbtable {
unsigned long flags; /* flags: */
#define TBTAB_FLAGSGLOBALLINK (1L<<47)
#define TBTAB_FLAGSISEPROL (1L<<46)
#define TBTAB_FLAGSHASTBOFF (1L<<45)
#define TBTAB_FLAGSINTPROC (1L<<44)
#define TBTAB_FLAGSHASCTL (1L<<43)
#define TBTAB_FLAGSTOCLESS (1L<<42)
#define TBTAB_FLAGSFPPRESENT (1L<<41)
#define TBTAB_FLAGSNAMEPRESENT (1L<<38)
#define TBTAB_FLAGSUSESALLOCA (1L<<37)
#define TBTAB_FLAGSSAVESCR (1L<<33)
#define TBTAB_FLAGSSAVESLR (1L<<32)
#define TBTAB_FLAGSSTORESBC (1L<<31)
#define TBTAB_FLAGSFIXUP (1L<<30)
#define TBTAB_FLAGSPARMSONSTK (1L<<0)
unsigned char fp_saved; /* num fp regs saved f(32-n)..f31 */
unsigned char gpr_saved; /* num gpr's saved */
unsigned char fixedparms; /* num fixed point parms */
unsigned char floatparms; /* num float parms */
unsigned char parminfo[32]; /* types of args. null terminated */
#define TBTAB_PARMFIXED 1
#define TBTAB_PARMSFLOAT 2
#define TBTAB_PARMDFLOAT 3
unsigned int tb_offset; /* offset from start of func */
unsigned long funcstart; /* addr of start of function */
char name[64]; /* name of function (null terminated)*/
};
static int find_tb_table(unsigned long codeaddr, struct tbtable *tab);
#define SURVEILLANCE_TOKEN 9000 #define SURVEILLANCE_TOKEN 9000
static inline void disable_surveillance(void) static inline void disable_surveillance(void)
...@@ -302,8 +270,7 @@ xmon(struct pt_regs *excp) ...@@ -302,8 +270,7 @@ xmon(struct pt_regs *excp)
std 29,232(%0)\n\ std 29,232(%0)\n\
std 30,240(%0)\n\ std 30,240(%0)\n\
std 31,248(%0)" : : "b" (&regs)); std 31,248(%0)" : : "b" (&regs));
/* Fetch the link reg for this stack frame.
NOTE: the prev printf fills in the lr. */
regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2]; regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
regs.msr = get_msr(); regs.msr = get_msr();
regs.ctr = get_ctr(); regs.ctr = get_ctr();
...@@ -378,7 +345,9 @@ xmon_bpt(struct pt_regs *regs) ...@@ -378,7 +345,9 @@ xmon_bpt(struct pt_regs *regs)
xmon_trace[smp_processor_id()] = BRSTEP; xmon_trace[smp_processor_id()] = BRSTEP;
regs->msr |= MSR_SE; regs->msr |= MSR_SE;
} else { } else {
printf("Stopped at breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname); printf("Stopped at breakpoint %x (%lx ", (bp - bpts) + 1,
bp->address);
xmon_print_symbol("%s)\n", bp->address);
xmon(regs); xmon(regs);
} }
return 1; return 1;
...@@ -576,9 +545,6 @@ cmds(struct pt_regs *excp) ...@@ -576,9 +545,6 @@ cmds(struct pt_regs *excp)
else else
excprint(excp); excprint(excp);
break; break;
case 'M':
print_sysmap();
break;
case 'S': case 'S':
super_regs(); super_regs();
break; break;
...@@ -768,7 +734,6 @@ bpt_cmds(void) ...@@ -768,7 +734,6 @@ bpt_cmds(void)
unsigned long a; unsigned long a;
int mode, i; int mode, i;
struct bpt *bp; struct bpt *bp;
struct tbtable tab;
cmd = inchar(); cmd = inchar();
switch (cmd) { switch (cmd) {
...@@ -824,7 +789,9 @@ bpt_cmds(void) ...@@ -824,7 +789,9 @@ bpt_cmds(void)
if (bp == 0) { if (bp == 0) {
printf("No breakpoint at %x\n", a); printf("No breakpoint at %x\n", a);
} else { } else {
printf("Cleared breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname); printf("Cleared breakpoint %x (%lx ",
(bp - bpts) + 1, bp->address);
xmon_print_symbol("%s)\n", bp->address);
bp->enabled = 0; bp->enabled = 0;
} }
} }
...@@ -858,8 +825,11 @@ bpt_cmds(void) ...@@ -858,8 +825,11 @@ bpt_cmds(void)
printf(" inst %.16lx %8x\n", iabr.address & ~3, printf(" inst %.16lx %8x\n", iabr.address & ~3,
iabr.count); iabr.count);
for (bp = bpts, bpnum = 1; bp < &bpts[NBPTS]; ++bp, ++bpnum) for (bp = bpts, bpnum = 1; bp < &bpts[NBPTS]; ++bp, ++bpnum)
if (bp->enabled) if (bp->enabled) {
printf("%2x trap %.16lx %8x %s\n", bpnum, bp->address, bp->count, bp->funcname); printf("%2x trap %.16lx %8x ",
bpnum, bp->address, bp->count);
xmon_print_symbol("%s\n", bp->address);
}
break; break;
} }
bp = at_breakpoint(a); bp = at_breakpoint(a);
...@@ -876,14 +846,9 @@ bpt_cmds(void) ...@@ -876,14 +846,9 @@ bpt_cmds(void)
bp->address = a; bp->address = a;
bp->count = 0; bp->count = 0;
scanhex(&bp->count); scanhex(&bp->count);
/* Find the function name just once. */ printf("Set breakpoint %2x trap %.16lx %8x ", (bp-bpts) + 1,
bp->funcname[0] = '\0'; bp->address, bp->count);
if (find_tb_table(bp->address, &tab) && tab.name[0]) { xmon_print_symbol("%s\n", bp->address);
/* Got a nice name for it. */
int delta = bp->address - tab.funcstart;
sprintf(bp->funcname, "%s+0x%x", tab.name, delta);
}
printf("Set breakpoint %2x trap %.16lx %8x %s\n", (bp-bpts)+1, bp->address, bp->count, bp->funcname);
break; break;
} }
} }
...@@ -920,7 +885,6 @@ backtrace(struct pt_regs *excp) ...@@ -920,7 +885,6 @@ backtrace(struct pt_regs *excp)
unsigned long lr; unsigned long lr;
unsigned long stack[3]; unsigned long stack[3];
struct pt_regs regs; struct pt_regs regs;
struct tbtable tab;
int framecount; int framecount;
char *funcname; char *funcname;
/* declare these as raw ptrs so we don't get func descriptors */ /* declare these as raw ptrs so we don't get func descriptors */
...@@ -966,14 +930,8 @@ backtrace(struct pt_regs *excp) ...@@ -966,14 +930,8 @@ backtrace(struct pt_regs *excp)
break; break;
printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112); printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112);
printf(" %.16lx", regs.nip); printf(" %.16lx", regs.nip);
if ((regs.nip & 0xffffffff00000000UL) && if (regs.nip & 0xffffffff00000000UL)
find_tb_table(regs.nip, &tab)) { xmon_print_symbol(" %s", regs.nip);
int delta = regs.nip-tab.funcstart;
if (delta < 0)
printf(" <unknown code>");
else
printf(" %s+0x%x", tab.name, delta);
}
printf("\n"); printf("\n");
if (regs.gpr[1] < sp) { if (regs.gpr[1] < sp) {
printf("<Stack drops into userspace %.16lx>\n", regs.gpr[1]); printf("<Stack drops into userspace %.16lx>\n", regs.gpr[1]);
...@@ -984,13 +942,8 @@ backtrace(struct pt_regs *excp) ...@@ -984,13 +942,8 @@ backtrace(struct pt_regs *excp)
if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
break; break;
} else { } else {
if (stack[2] && find_tb_table(stack[2], &tab)) { if (stack[2])
int delta = stack[2]-tab.funcstart; xmon_print_symbol(" %s", stack[2]);
if (delta < 0)
printf(" <unknown code>");
else
printf(" %s+0x%x", tab.name, delta);
}
printf("\n"); printf("\n");
} }
if (stack[0] && stack[0] <= sp) { if (stack[0] && stack[0] <= sp) {
...@@ -1019,8 +972,6 @@ spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED; ...@@ -1019,8 +972,6 @@ spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED;
void void
excprint(struct pt_regs *fp) excprint(struct pt_regs *fp)
{ {
struct task_struct *c;
struct tbtable tab;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&exception_print_lock, flags); spin_lock_irqsave(&exception_print_lock, flags);
...@@ -1029,21 +980,13 @@ excprint(struct pt_regs *fp) ...@@ -1029,21 +980,13 @@ excprint(struct pt_regs *fp)
printf("cpu %d: ", smp_processor_id()); printf("cpu %d: ", smp_processor_id());
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(fp->trap), fp); printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(fp->trap), fp);
printf(" pc: %lx", fp->nip); printf(" pc: %lx", fp->nip);
if (find_tb_table(fp->nip, &tab) && tab.name[0]) { xmon_print_symbol(" (%s)\n", fp->nip);
/* Got a nice name for it */
int delta = fp->nip - tab.funcstart;
printf(" (%s+0x%x)", tab.name, delta);
}
printf("\n");
printf(" lr: %lx", fp->link); printf(" lr: %lx", fp->link);
if (find_tb_table(fp->link, &tab) && tab.name[0]) { xmon_print_symbol(" (%s)\n", fp->link);
/* Got a nice name for it */
int delta = fp->link - tab.funcstart;
printf(" (%s+0x%x)", tab.name, delta);
}
printf("\n");
printf(" sp: %lx\n", fp->gpr[1]); printf(" sp: %lx\n", fp->gpr[1]);
printf(" msr: %lx\n", fp->msr); printf(" msr: %lx\n", fp->msr);
...@@ -1052,13 +995,11 @@ excprint(struct pt_regs *fp) ...@@ -1052,13 +995,11 @@ excprint(struct pt_regs *fp)
printf(" dsisr: %lx\n", fp->dsisr); printf(" dsisr: %lx\n", fp->dsisr);
} }
/* XXX: need to copy current or we die. Why? */ printf(" current = 0x%lx\n", current);
c = current;
printf(" current = 0x%lx\n", c);
printf(" paca = 0x%lx\n", get_paca()); printf(" paca = 0x%lx\n", get_paca());
if (c) { if (current) {
printf(" current = %lx, pid = %ld, comm = %s\n", printf(" pid = %ld, comm = %s\n",
c, c->pid, c->comm); current->pid, current->comm);
} }
spin_unlock_irqrestore(&exception_print_lock, flags); spin_unlock_irqrestore(&exception_print_lock, flags);
...@@ -1147,14 +1088,6 @@ static unsigned long regno; ...@@ -1147,14 +1088,6 @@ static unsigned long regno;
extern char exc_prolog; extern char exc_prolog;
extern char dec_exc; extern char dec_exc;
void
print_sysmap(void)
{
extern char *sysmap;
if ( sysmap )
printf("System.map: \n%s", sysmap);
}
void void
super_regs() super_regs()
{ {
...@@ -1922,111 +1855,52 @@ char *str; ...@@ -1922,111 +1855,52 @@ char *str;
lineptr = str; lineptr = str;
} }
/* xmon version of __print_symbol */
/* Starting at codeaddr scan forward for a tbtable and fill in the void __xmon_print_symbol(const char *fmt, unsigned long address)
given table. Return non-zero if successful at doing something.
*/
static int
find_tb_table(unsigned long codeaddr, struct tbtable *tab)
{ {
unsigned long codeaddr_max; char *modname;
unsigned long tbtab_start; const char *name;
int nr; unsigned long offset, size;
int instr; char namebuf[128];
int num_parms;
/* don't look for traceback table in userspace */
if (codeaddr < PAGE_OFFSET)
return 0;
if (tab == NULL) if (setjmp(bus_error_jmp) == 0) {
return 0; debugger_fault_handler = handle_fault;
memset(tab, 0, sizeof(tab)); sync();
name = kallsyms_lookup(address, &size, &offset, &modname,
/* Scan instructions starting at codeaddr for 128k max */ namebuf);
for (codeaddr_max = codeaddr + 128*1024*4; sync();
codeaddr < codeaddr_max; /* wait a little while to see if we get a machine check */
codeaddr += 4) { __delay(200);
nr = mread(codeaddr, &instr, 4); } else {
if (nr != 4) name = "symbol lookup failed";
return 0; /* Bad read. Give up promptly. */ }
if (instr == 0) {
/* table should follow. */ debugger_fault_handler = 0;
int version;
unsigned long flags; if (!name) {
tbtab_start = codeaddr; /* save it to compute func start addr */ char addrstr[sizeof("0x%lx") + (BITS_PER_LONG*3/10)];
codeaddr += 4;
nr = mread(codeaddr, &flags, 8); sprintf(addrstr, "0x%lx", address);
if (nr != 8) printf(fmt, addrstr);
return 0; /* Bad read or no tb table. */ return;
tab->flags = flags; }
version = (flags >> 56) & 0xff;
if (version != 0) if (modname) {
continue; /* No tb table here. */ /* This is pretty small. */
/* Now, like the version, some of the flags are values char buffer[sizeof("%s+%#lx/%#lx [%s]")
that are more conveniently extracted... */ + strlen(name) + 2*(BITS_PER_LONG*3/10)
tab->fp_saved = (flags >> 24) & 0x3f; + strlen(modname)];
tab->gpr_saved = (flags >> 16) & 0x3f;
tab->fixedparms = (flags >> 8) & 0xff; sprintf(buffer, "%s+%#lx/%#lx [%s]",
tab->floatparms = (flags >> 1) & 0x7f; name, offset, size, modname);
codeaddr += 8; printf(fmt, buffer);
num_parms = tab->fixedparms + tab->floatparms; } else {
if (num_parms) { char buffer[sizeof("%s+%#lx/%#lx")
unsigned int parminfo; + strlen(name) + 2*(BITS_PER_LONG*3/10)];
int parm;
if (num_parms > 32) sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
return 1; /* incomplete */ printf(fmt, buffer);
nr = mread(codeaddr, &parminfo, 4);
if (nr != 4)
return 1; /* incomplete */
/* decode parminfo...32 bits.
A zero means fixed. A one means float and the
following bit determines single (0) or double (1).
*/
for (parm = 0; parm < num_parms; parm++) {
if (parminfo & 0x80000000) {
parminfo <<= 1;
if (parminfo & 0x80000000)
tab->parminfo[parm] = TBTAB_PARMDFLOAT;
else
tab->parminfo[parm] = TBTAB_PARMSFLOAT;
} else {
tab->parminfo[parm] = TBTAB_PARMFIXED;
}
parminfo <<= 1;
}
codeaddr += 4;
}
if (flags & TBTAB_FLAGSHASTBOFF) {
nr = mread(codeaddr, &tab->tb_offset, 4);
if (nr != 4)
return 1; /* incomplete */
if (tab->tb_offset > 0) {
tab->funcstart = tbtab_start - tab->tb_offset;
}
codeaddr += 4;
}
/* hand_mask appears to be always be omitted. */
if (flags & TBTAB_FLAGSHASCTL) {
/* Assume this will never happen for C or asm */
return 1; /* incomplete */
}
if (flags & TBTAB_FLAGSNAMEPRESENT) {
short namlen;
nr = mread(codeaddr, &namlen, 2);
if (nr != 2)
return 1; /* incomplete */
if (namlen >= sizeof(tab->name))
namlen = sizeof(tab->name)-1;
codeaddr += 2;
nr = mread(codeaddr, tab->name, namlen);
tab->name[namlen] = '\0';
codeaddr += namlen;
}
return 1;
}
} }
return 0; /* hit max...sorry. */
} }
void void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment