X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc%2Fxmon%2Fxmon.c;h=06fa44b5c647130e7beb65514d2573e15016cb02;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=8565f49b8b0b879fc0c743c6a7a4f69dbb6e94dc;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 8565f49b8..06fa44b5c 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -9,15 +9,11 @@ #include #include #include +#include #include #include -#include -#include #include #include -#ifdef CONFIG_PMAC_BACKLIGHT -#include -#endif #include "nonstdio.h" #include "privinst.h" @@ -93,21 +89,16 @@ static void take_input(char *); static unsigned read_spr(int); static void write_spr(int, unsigned); static void super_regs(void); -static void print_sysmap(void); -static void sysmap_lookup(void); +static void symbol_lookup(void); static void remove_bpts(void); static void insert_bpts(void); static struct bpt *at_breakpoint(unsigned pc); static void bpt_cmds(void); -static void cacheflush(void); +void cacheflush(void); #ifdef CONFIG_SMP static void cpu_cmd(void); #endif /* CONFIG_SMP */ -static int pretty_print_addr(unsigned long addr); static void csum(void); -#ifdef CONFIG_BOOTX_TEXT -static void vidcmds(void); -#endif static void bootcmds(void); static void proccall(void); static void printtime(void); @@ -120,8 +111,6 @@ extern void longjmp(u_int *, int); extern void xmon_enter(void); extern void xmon_leave(void); -extern char* xmon_find_symbol(unsigned long addr, unsigned long* saddr); -extern unsigned long xmon_symbol_to_addr(char* symbol); static unsigned start_tb[NR_CPUS][2]; static unsigned stop_tb[NR_CPUS][2]; @@ -148,13 +137,17 @@ Commands:\n\ mm move a block of memory\n\ ms set a block of memory\n\ md compare two blocks of memory\n\ - M print System.map\n\ r print registers\n\ S print special registers\n\ t print backtrace\n\ - la lookup address in system.map\n\ - ls lookup symbol in system.map\n\ + la lookup address\n\ + ls lookup symbol\n\ + C checksum\n\ + p call function with arguments\n\ + T print time\n\ x exit monitor\n\ + zr reboot\n\ + zh halt\n\ "; static int xmon_trace[NR_CPUS]; @@ -175,6 +168,35 @@ extern inline void __delay(unsigned int loops) "r" (loops) : "ctr"); } +/* Print an address in numeric and symbolic form (if possible) */ +static void xmon_print_symbol(unsigned long address, const char *mid, + const char *after) +{ + char *modname; + const char *name = NULL; + unsigned long offset, size; + static char tmpstr[128]; + + printf("%.8lx", address); + if (setjmp(bus_error_jmp) == 0) { + debugger_fault_handler = handle_fault; + sync(); + name = kallsyms_lookup(address, &size, &offset, &modname, + tmpstr); + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); + } + debugger_fault_handler = NULL; + + if (name) { + printf("%s%s+%#lx/%#lx", mid, name, offset, size); + if (modname) + printf(" [%s]", modname); + } + printf("%s", after); +} + static void get_tb(unsigned *p) { unsigned hi, lo, hiagain; @@ -190,8 +212,7 @@ static void get_tb(unsigned *p) p[1] = lo; } -void -xmon(struct pt_regs *excp) +int xmon(struct pt_regs *excp) { struct pt_regs regs; int msr, cmd; @@ -231,16 +252,6 @@ xmon(struct pt_regs *excp) */ #endif /* CONFIG_SMP */ remove_bpts(); -#ifdef CONFIG_PMAC_BACKLIGHT - if( setjmp(bus_error_jmp) == 0 ) { - debugger_fault_handler = handle_fault; - sync(); - set_backlight_enable(1); - set_backlight_level(BACKLIGHT_MAX); - sync(); - } - debugger_fault_handler = NULL; -#endif /* CONFIG_PMAC_BACKLIGHT */ cmd = cmds(excp); if (cmd == 's') { xmon_trace[smp_processor_id()] = SSTEP; @@ -260,6 +271,8 @@ xmon(struct pt_regs *excp) #endif /* CONFIG_SMP */ set_msr(msr); /* restore interrupt enable */ get_tb(start_tb[smp_processor_id()]); + + return cmd != 'X'; } irqreturn_t @@ -454,7 +467,7 @@ cmds(struct pt_regs *excp) dump(); break; case 'l': - sysmap_lookup(); + symbol_lookup(); break; case 'r': if (excp != NULL) @@ -466,9 +479,6 @@ cmds(struct pt_regs *excp) else excprint(excp); break; - case 'M': - print_sysmap(); - break; case 'S': super_regs(); break; @@ -507,11 +517,6 @@ cmds(struct pt_regs *excp) cpu_cmd(); break; #endif /* CONFIG_SMP */ -#ifdef CONFIG_BOOTX_TEXT - case 'v': - vidcmds(); - break; -#endif case 'z': bootcmds(); break; @@ -603,43 +608,6 @@ static void cpu_cmd(void) } #endif /* CONFIG_SMP */ -#ifdef CONFIG_BOOTX_TEXT -extern boot_infos_t disp_bi; - -static void vidcmds(void) -{ - int c = inchar(); - unsigned int val, w; - extern int boot_text_mapped; - - if (!boot_text_mapped) - return; - if (c != '\n' && scanhex(&val)) { - switch (c) { - case 'd': - w = disp_bi.dispDeviceRowBytes - / (disp_bi.dispDeviceDepth >> 3); - disp_bi.dispDeviceDepth = val; - disp_bi.dispDeviceRowBytes = w * (val >> 3); - return; - case 'p': - disp_bi.dispDeviceRowBytes = val; - return; - case 'w': - disp_bi.dispDeviceRect[2] = val; - return; - case 'h': - disp_bi.dispDeviceRect[3] = val; - return; - } - } - printf("W = %d (0x%x) H = %d (0x%x) D = %d (0x%x) P = %d (0x%x)\n", - disp_bi.dispDeviceRect[2], disp_bi.dispDeviceRect[2], - disp_bi.dispDeviceRect[3], disp_bi.dispDeviceRect[3], - disp_bi.dispDeviceDepth, disp_bi.dispDeviceDepth, - disp_bi.dispDeviceRowBytes, disp_bi.dispDeviceRowBytes); -} -#endif /* CONFIG_BOOTX_TEXT */ static unsigned short fcstab[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, @@ -825,20 +793,19 @@ backtrace(struct pt_regs *excp) for (; sp != 0; sp = stack[0]) { if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) break; - pretty_print_addr(stack[1]); - printf(" "); + printf("[%.8lx] ", stack); + xmon_print_symbol(stack[1], " ", "\n"); if (stack[1] == (unsigned) &ret_from_except || stack[1] == (unsigned) &ret_from_except_full || stack[1] == (unsigned) &ret_from_syscall) { if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs)) break; - printf("\nexception:%x [%x] %x ", regs.trap, sp+16, + printf("exception:%x [%x] %x\n", regs.trap, sp+16, regs.nip); sp = regs.gpr[1]; if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) break; } - printf("\n"); } } @@ -859,11 +826,10 @@ excprint(struct pt_regs *fp) #ifdef CONFIG_SMP printf("cpu %d: ", smp_processor_id()); #endif /* CONFIG_SMP */ - printf("vector: %x at pc = ", fp->trap); - pretty_print_addr(fp->nip); - printf(", lr = "); - pretty_print_addr(fp->link); - printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp); + printf("vector: %x at pc=", fp->trap); + xmon_print_symbol(fp->nip, ": ", ", lr="); + xmon_print_symbol(fp->link, ": ", "\n"); + printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp); trap = TRAP(fp); if (trap == 0x300 || trap == 0x600) printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr); @@ -950,24 +916,6 @@ static unsigned int regno; extern char exc_prolog; extern char dec_exc; -void -print_sysmap(void) -{ - extern char *sysmap; - if ( sysmap ) { - printf("System.map: \n"); - if( setjmp(bus_error_jmp) == 0 ) { - debugger_fault_handler = handle_fault; - sync(); - xmon_puts(sysmap); - sync(); - } - debugger_fault_handler = NULL; - } - else - printf("No System.map\n"); -} - void super_regs(void) { @@ -1025,7 +973,6 @@ dump_hash_table(void) } #else -#ifndef CONFIG_PPC64BRIDGE static void dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) { @@ -1084,66 +1031,6 @@ dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) printf(" ... %x\n", last_va); } -#else /* CONFIG_PPC64BRIDGE */ -static void -dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) -{ - extern void *Hash; - extern unsigned long Hash_size; - unsigned *htab = Hash; - unsigned hsize = Hash_size; - unsigned v, hmask, va, last_va; - int found, last_found, i; - unsigned *hg, w1, last_w2, last_va0; - - last_found = 0; - hmask = hsize / 128 - 1; - va = start; - start = (start >> 12) & 0xffff; - end = (end >> 12) & 0xffff; - for (v = start; v < end; ++v) { - found = 0; - hg = htab + (((v ^ seg) & hmask) * 32); - w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4); - for (i = 0; i < 8; ++i, hg += 4) { - if (hg[1] == w1) { - found = 1; - break; - } - } - if (!found) { - w1 ^= 2; - hg = htab + ((~(v ^ seg) & hmask) * 32); - for (i = 0; i < 8; ++i, hg += 4) { - if (hg[1] == w1) { - found = 1; - break; - } - } - } - if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) { - if (last_found) { - if (last_va != last_va0) - printf(" ... %x", last_va); - printf("\n"); - } - if (found) { - printf("%x to %x", va, hg[3]); - last_va0 = va; - } - last_found = found; - } - if (found) { - last_w2 = hg[3] & ~0x180; - last_va = va; - } - va += 4096; - } - if (last_found) - printf(" ... %x\n", last_va); -} -#endif /* CONFIG_PPC64BRIDGE */ - static unsigned hash_ctx; static unsigned hash_start; static unsigned hash_end; @@ -1738,7 +1625,7 @@ scanhex(unsigned *vp) printf("invalid register name '%%%s'\n", regname); return 0; } else if (c == '$') { - static char symname[64]; + static char symname[128]; int i; for (i=0; i<63; i++) { c = inchar(); @@ -1749,7 +1636,14 @@ scanhex(unsigned *vp) symname[i] = c; } symname[i++] = 0; - *vp = xmon_symbol_to_addr(symname); + *vp = 0; + if (setjmp(bus_error_jmp) == 0) { + debugger_fault_handler = handle_fault; + sync(); + *vp = kallsyms_lookup_name(symname); + sync(); + } + debugger_fault_handler = NULL; if (!(*vp)) { printf("unknown symbol\n"); return 0; @@ -1840,169 +1734,34 @@ take_input(char *str) lineptr = str; } -void -sysmap_lookup(void) +static void +symbol_lookup(void) { int type = inchar(); unsigned addr; - static char tmp[64]; - char* cur; + static char tmp[128]; - extern char *sysmap; - extern unsigned long sysmap_size; - if ( !sysmap || !sysmap_size ) - return; - - switch(type) { - case 'a': - if (scanhex(&addr)) { - pretty_print_addr(addr); - printf("\n"); - } - termch = 0; - break; - case 's': - getstring(tmp, 64); - if( setjmp(bus_error_jmp) == 0 ) { - debugger_fault_handler = handle_fault; - sync(); - cur = sysmap; - do { - cur = strstr(cur, tmp); - if (cur) { - static char res[64]; - char *p, *d; - p = cur; - while(p > sysmap && *p != 10) - p--; - if (*p == 10) p++; - d = res; - while(*p && p < (sysmap + sysmap_size) && *p != 10) - *(d++) = *(p++); - *(d++) = 0; - printf("%s\n", res); - cur++; - } - } while (cur); - sync(); - } - debugger_fault_handler = NULL; - termch = 0; - break; - } -} - -static int -pretty_print_addr(unsigned long addr) -{ - char *sym; - unsigned long saddr; - - printf("%08x", addr); - sym = xmon_find_symbol(addr, &saddr); - if (sym) - printf(" (%s+0x%x)", sym, addr-saddr); - return (sym != 0); -} - -char* -xmon_find_symbol(unsigned long addr, unsigned long* saddr) -{ - static char rbuffer[64]; - char *p, *ep, *limit; - unsigned long prev, next; - char* psym; - - extern char *sysmap; - extern unsigned long sysmap_size; - if ( !sysmap || !sysmap_size ) - return NULL; - - prev = 0; - psym = NULL; - p = sysmap; - limit = p + sysmap_size; - if( setjmp(bus_error_jmp) == 0 ) { - debugger_fault_handler = handle_fault; - sync(); - do { - next = simple_strtoul(p, &p, 16); - if (next > addr && prev <= addr) { - if (!psym) - goto bail; - ep = rbuffer; - p = psym; - while(*p && p < limit && *p == 32) - p++; - while(*p && p < limit && *p != 10 && (ep - rbuffer) < 63) - *(ep++) = *(p++); - *(ep++) = 0; - if (saddr) - *saddr = prev; - debugger_fault_handler = NULL; - return rbuffer; - } - prev = next; - psym = p; - while(*p && p < limit && *p != 10) - p++; - if (*p) p++; - } while(*p && p < limit && next); -bail: - sync(); + switch (type) { + case 'a': + if (scanhex(&addr)) + xmon_print_symbol(addr, ": ", "\n"); + termch = 0; + break; + case 's': + getstring(tmp, 64); + if (setjmp(bus_error_jmp) == 0) { + debugger_fault_handler = handle_fault; + sync(); + addr = kallsyms_lookup_name(tmp); + if (addr) + printf("%s: %lx\n", tmp, addr); + else + printf("Symbol '%s' not found.\n", tmp); + sync(); + } + debugger_fault_handler = NULL; + termch = 0; + break; } - debugger_fault_handler = NULL; - return NULL; } -unsigned long -xmon_symbol_to_addr(char* symbol) -{ - char *p, *cur; - char *match = NULL; - int goodness = 0; - int result = 0; - - extern char *sysmap; - extern unsigned long sysmap_size; - if ( !sysmap || !sysmap_size ) - return 0; - - if( setjmp(bus_error_jmp) == 0 ) { - debugger_fault_handler = handle_fault; - sync(); - cur = sysmap; - while(cur) { - cur = strstr(cur, symbol); - if (cur) { - int gd = 1; - - /* best match if equal, better match if - * begins with - */ - if (cur == sysmap || *(cur-1) == ' ') { - gd++; - if (cur[strlen(symbol)] == 10) - gd++; - } - if (gd > goodness) { - match = cur; - goodness = gd; - if (gd == 3) - break; - } - cur++; - } - } - if (goodness) { - p = match; - while(p > sysmap && *p != 10) - p--; - if (*p == 10) p++; - result = simple_strtoul(p, &p, 16); - } - sync(); - } - debugger_fault_handler = NULL; - return result; -}