From 2d1eb995a13a7af244c7ef168aa965b6674fd605 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Feb 2004 15:30:14 -0800 Subject: [PATCH] [PATCH] various xmon cleanups Heres a patch I've had for a while, it removes a bunch of debugger code which is good :) The next patch will sanitise it (and the rest of the debugger hooks). Various xmon cleanups - recover from bad SPR read/write (we get a program check) - remove some old code (bat and segment register stuff) - update the help text to match reality - add a "press ? for help" when xmon first appears to make rusty happy - protect against flushing bad parts of memory from Milton - dont print iseries specific stuff on pseries in SPR dump (S) - add code to dump the segment table or SLB - remove a number of functions that wouldnt work on LPAR --- arch/ppc64/kernel/traps.c | 7 + arch/ppc64/xmon/privinst.h | 28 --- arch/ppc64/xmon/xmon.c | 412 ++++++++++++------------------------- 3 files changed, 133 insertions(+), 314 deletions(-) diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index e11e2c52c4a7b..6df8cfca3ba07 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -372,6 +372,13 @@ ProgramCheckException(struct pt_regs *regs) { siginfo_t info; +#ifdef CONFIG_DEBUG_KERNEL + if (debugger_fault_handler) { + debugger_fault_handler(regs); + return; + } +#endif + if (regs->msr & 0x100000) { /* IEEE FP exception */ diff --git a/arch/ppc64/xmon/privinst.h b/arch/ppc64/xmon/privinst.h index 3fda8922323ba..183c3e4002588 100644 --- a/arch/ppc64/xmon/privinst.h +++ b/arch/ppc64/xmon/privinst.h @@ -43,39 +43,12 @@ GSETSPR(274, sprg2) GSETSPR(275, sprg3) GSETSPR(282, ear) GSETSPR(287, pvr) -GSETSPR(528, bat0u) -GSETSPR(529, bat0l) -GSETSPR(530, bat1u) -GSETSPR(531, bat1l) -GSETSPR(532, bat2u) -GSETSPR(533, bat2l) -GSETSPR(534, bat3u) -GSETSPR(535, bat3l) GSETSPR(1008, hid0) GSETSPR(1009, hid1) GSETSPR(1010, iabr) GSETSPR(1013, dabr) GSETSPR(1023, pir) -static inline int get_sr(int n) -{ - int ret; - -#if 0 - // DRENG does not assemble - asm (" mfsrin %0,%1" : "=r" (ret) : "r" (n << 28)); -#endif - return ret; -} - -static inline void set_sr(int n, int val) -{ -#if 0 - // DRENG does not assemble - asm ("mtsrin %0,%1" : : "r" (val), "r" (n << 28)); -#endif -} - static inline void store_inst(void *p) { asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p)); @@ -90,4 +63,3 @@ static inline void cinval(void *p) { asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); } - diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index 52cd2c8210a73..16ebf3dccc660 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c @@ -115,10 +115,7 @@ static void cpu_cmd(void); #endif /* CONFIG_SMP */ static void csum(void); static void bootcmds(void); -static void mem_translate(void); -static void mem_check(void); -static void mem_find_real(void); -static void mem_find_vsid(void); +void dump_segments(void); static void debug_trace(void); @@ -149,7 +146,15 @@ Commands:\n\ b show breakpoints\n\ bd set data breakpoint\n\ bi set instruction breakpoint\n\ - bc clear breakpoint\n\ + bc clear breakpoint\n" +#ifdef CONFIG_SMP + "\ + c print cpus stopped in xmon\n\ + ci send xmon interrupt to all other cpus\n\ + c# try to switch to cpu number h (in hex)\n" +#endif + "\ + C checksum\n\ d dump bytes\n\ di dump instructions\n\ df dump float values\n\ @@ -162,7 +167,6 @@ Commands:\n\ md compare two blocks of memory\n\ ml locate a block of memory\n\ mz zero a block of memory\n\ - mx translation information for an effective address\n\ mi show information about memory allocation\n\ p show the task list\n\ r print registers\n\ @@ -171,7 +175,14 @@ Commands:\n\ t print backtrace\n\ T Enable/Disable PPCDBG flags\n\ x exit monitor\n\ -"; + u dump segment table or SLB\n\ + ? help\n" +#ifndef CONFIG_PPC_ISERIES + "\ + zr reboot\n\ + zh halt\n" +#endif +; static int xmon_trace[NR_CPUS]; #define SSTEP 1 /* stepping because of 's' command */ @@ -308,6 +319,7 @@ xmon(struct pt_regs *excp) #endif /* CONFIG_SMP */ remove_bpts(); disable_surveillance(); + printf("press ? for help "); cmd = cmds(excp); if (cmd == 's') { xmon_trace[smp_processor_id()] = SSTEP; @@ -332,17 +344,6 @@ xmon(struct pt_regs *excp) set_msrd(msr); /* restore interrupt enable */ } -void -xmon_irq(int irq, void *d, struct pt_regs *regs) -{ - unsigned long flags; - local_save_flags(flags); - local_irq_disable(); - printf("Keyboard interrupt\n"); - xmon(regs); - local_irq_restore(flags); -} - int xmon_bpt(struct pt_regs *regs) { @@ -524,18 +525,6 @@ cmds(struct pt_regs *excp) case 'z': memzcan(); break; - case 'x': - mem_translate(); - break; - case 'c': - mem_check(); - break; - case 'f': - mem_find_real(); - break; - case 'e': - mem_find_vsid(); - break; case 'i': show_mem(); break; @@ -587,11 +576,16 @@ cmds(struct pt_regs *excp) cpu_cmd(); break; #endif /* CONFIG_SMP */ +#ifndef CONFIG_PPC_ISERIES case 'z': bootcmds(); +#endif case 'T': debug_trace(); break; + case 'u': + dump_segments(); + break; default: printf("Unrecognized command: "); do { @@ -1057,14 +1051,23 @@ cacheflush(void) termch = 0; nflush = 1; scanhex(&nflush); - nflush = (nflush + 31) / 32; - if (cmd != 'i') { - for (; nflush > 0; --nflush, adrs += 0x20) - cflush((void *) adrs); - } else { - for (; nflush > 0; --nflush, adrs += 0x20) - cinval((void *) adrs); + nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES; + if( setjmp(bus_error_jmp) == 0 ) { + debugger_fault_handler = handle_fault; + sync(); + + if (cmd != 'i') { + for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES) + cflush((void *) adrs); + } else { + for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES) + cinval((void *) adrs); + } + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); } + debugger_fault_handler = 0; } unsigned long @@ -1073,6 +1076,7 @@ read_spr(int n) unsigned int instrs[2]; unsigned long (*code)(void); unsigned long opd[3]; + unsigned long ret = -1UL; instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); instrs[1] = 0x4e800020; @@ -1083,7 +1087,22 @@ read_spr(int n) store_inst(instrs+1); code = (unsigned long (*)(void)) opd; - return code(); + if (setjmp(bus_error_jmp) == 0) { + debugger_fault_handler = handle_fault; + sync(); + + ret = code(); + + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); + } else { + printf("*** Error reading spr %x\n", n); + } + + debugger_fault_handler = 0; + + return ret; } void @@ -1102,7 +1121,20 @@ write_spr(int n, unsigned long val) store_inst(instrs+1); code = (unsigned long (*)(unsigned long)) opd; - code(val); + if (setjmp(bus_error_jmp) == 0) { + debugger_fault_handler = handle_fault; + sync(); + + code(val); + + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); + } else { + printf("*** Error writing spr %x\n", n); + } + + debugger_fault_handler = 0; } static unsigned long regno; @@ -1112,11 +1144,14 @@ extern char dec_exc; void super_regs() { - int i, cmd; + int cmd; unsigned long val; - struct paca_struct* ptrPaca = NULL; - struct ItLpPaca* ptrLpPaca = NULL; - struct ItLpRegSave* ptrLpRegSave = NULL; +#ifdef CONFIG_PPC_ISERIES + int i; + struct paca_struct *ptrPaca = NULL; + struct ItLpPaca *ptrLpPaca = NULL; + struct ItLpRegSave *ptrLpRegSave = NULL; +#endif cmd = skipbl(); if (cmd == '\n') { @@ -1130,10 +1165,7 @@ super_regs() printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3()); printf("toc = %.16lx dar = %.16lx\n", toc, get_dar()); printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1()); - printf("asr = %.16lx\n", mfasr()); - for (i = 0; i < 8; ++i) - printf("sr%.2ld = %.16lx sr%.2ld = %.16lx\n", i, get_sr(i), i+8, get_sr(i+8)); - +#ifdef CONFIG_PPC_ISERIES // Dump out relevant Paca data areas. printf("Paca: \n"); ptrPaca = get_paca(); @@ -1149,7 +1181,8 @@ super_regs() printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); - +#endif + return; } @@ -1163,11 +1196,6 @@ super_regs() case 'r': printf("spr %lx = %lx\n", regno, read_spr(regno)); break; - case 's': - val = get_sr(regno); - scanhex(&val); - set_sr(regno, val); - break; case 'm': val = get_msr(); scanhex(&val); @@ -1924,240 +1952,8 @@ void __xmon_print_symbol(const char *fmt, unsigned long address) } } -void -mem_translate() -{ - int c; - unsigned long ea, va, vsid, vpn, page, hpteg_slot_primary, hpteg_slot_secondary, primary_hash, i, *steg, esid, stabl; - HPTE * hpte; - struct mm_struct * mm; - pte_t *ptep = NULL; - void * pgdir; - - c = inchar(); - if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') - termch = c; - scanhex((void *)&ea); - - if ((ea >= KRANGE_START) && (ea <= (KRANGE_START + (1UL<<60)))) { - ptep = 0; - vsid = get_kernel_vsid(ea); - va = ( vsid << 28 ) | ( ea & 0x0fffffff ); - } else { - // if in vmalloc range, use the vmalloc page directory - if ( ( ea >= VMALLOC_START ) && ( ea <= VMALLOC_END ) ) { - mm = &init_mm; - vsid = get_kernel_vsid( ea ); - } - // if in ioremap range, use the ioremap page directory - else if ( ( ea >= IMALLOC_START ) && ( ea <= IMALLOC_END ) ) { - mm = &ioremap_mm; - vsid = get_kernel_vsid( ea ); - } - // if in user range, use the current task's page directory - else if ( ( ea >= USER_START ) && ( ea <= USER_END ) ) { - mm = current->mm; - vsid = get_vsid(mm->context, ea ); - } - pgdir = mm->pgd; - va = ( vsid << 28 ) | ( ea & 0x0fffffff ); - ptep = find_linux_pte( pgdir, ea ); - } - - vpn = ((vsid << 28) | (((ea) & 0xFFFF000))) >> 12; - page = vpn & 0xffff; - esid = (ea >> 28) & 0xFFFFFFFFF; - - // Search the primary group for an available slot - primary_hash = ( vsid & 0x7fffffffff ) ^ page; - hpteg_slot_primary = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP; - hpteg_slot_secondary = ( ~primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP; - - printf("ea : %.16lx\n", ea); - printf("esid : %.16lx\n", esid); - printf("vsid : %.16lx\n", vsid); - - printf("\nSoftware Page Table\n-------------------\n"); - printf("ptep : %.16lx\n", ((unsigned long *)ptep)); - if(ptep) { - printf("*ptep : %.16lx\n", *((unsigned long *)ptep)); - } - - hpte = htab_data.htab + hpteg_slot_primary; - printf("\nHardware Page Table\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("slot primary : %.16lx\n", hpteg_slot_primary); - printf("slot secondary : %.16lx\n", hpteg_slot_secondary); - printf("\nPrimary Group\n"); - for (i=0; i<8; ++i) { - if ( hpte->dw0.dw0.v != 0 ) { - printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1); - printf(" vsid: %.13lx api: %.2lx hash: %.1lx\n", - (hpte->dw0.dw0.avpn)>>5, - (hpte->dw0.dw0.avpn) & 0x1f, - (hpte->dw0.dw0.h)); - printf(" rpn: %.13lx \n", (hpte->dw1.dw1.rpn)); - printf(" pp: %.1lx \n", - ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp)); - printf(" wimgn: %.2lx reference: %.1lx change: %.1lx\n", - ((hpte->dw1.dw1.w)<<4)| - ((hpte->dw1.dw1.i)<<3)| - ((hpte->dw1.dw1.m)<<2)| - ((hpte->dw1.dw1.g)<<1)| - ((hpte->dw1.dw1.n)<<0), - hpte->dw1.dw1.r, hpte->dw1.dw1.c); - } - hpte++; - } - - printf("\nSecondary Group\n"); - // Search the secondary group - hpte = htab_data.htab + hpteg_slot_secondary; - for (i=0; i<8; ++i) { - if(hpte->dw0.dw0.v) { - printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1); - printf(" vsid: %.13lx api: %.2lx hash: %.1lx\n", - (hpte->dw0.dw0.avpn)>>5, - (hpte->dw0.dw0.avpn) & 0x1f, - (hpte->dw0.dw0.h)); - printf(" rpn: %.13lx \n", (hpte->dw1.dw1.rpn)); - printf(" pp: %.1lx \n", - ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp)); - printf(" wimgn: %.2lx reference: %.1lx change: %.1lx\n", - ((hpte->dw1.dw1.w)<<4)| - ((hpte->dw1.dw1.i)<<3)| - ((hpte->dw1.dw1.m)<<2)| - ((hpte->dw1.dw1.g)<<1)| - ((hpte->dw1.dw1.n)<<0), - hpte->dw1.dw1.r, hpte->dw1.dw1.c); - } - hpte++; - } - - printf("\nHardware Segment Table\n-----------------------\n"); - stabl = (unsigned long)(KERNELBASE+(_ASR&0xFFFFFFFFFFFFFFFE)); - steg = (unsigned long *)((stabl) | ((esid & 0x1f) << 7)); - - printf("stab base : %.16lx\n", stabl); - printf("slot : %.16lx\n", steg); - - for (i=0; i<8; ++i) { - printf("%d: (ste) %.16lx %.16lx\n", i, - *((unsigned long *)(steg+i*2)),*((unsigned long *)(steg+i*2+1)) ); - } -} - -void mem_check() -{ - unsigned long htab_size_bytes; - unsigned long htab_end; - unsigned long last_rpn; - HPTE *hpte1, *hpte2; - - htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG - htab_end = (unsigned long)htab_data.htab + htab_size_bytes; - // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; - last_rpn = 0xfffff; - - printf("\nHardware Page Table Check\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("htab size : %.16lx\n", htab_size_bytes); - -#if 1 - for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { - if ( hpte1->dw0.dw0.v != 0 ) { - if ( hpte1->dw1.dw1.rpn <= last_rpn ) { - for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) { - if ( hpte2->dw0.dw0.v != 0 ) { - if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) { - printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); - printf(" hpte1: %16.16lx *hpte1: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - printf(" hpte2: %16.16lx *hpte2: %16.16lx %16.16lx\n", - hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1); - } - } - } - } else { - printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); - printf(" hpte: %16.16lx *hpte: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - } - } - } -#endif - printf("\nDone -------------------\n"); -} - -void mem_find_real() +static void debug_trace(void) { - unsigned long htab_size_bytes; - unsigned long htab_end; - unsigned long last_rpn; - HPTE *hpte1; - unsigned long pa, rpn; - int c; - - c = inchar(); - if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') - termch = c; - scanhex((void *)&pa); - rpn = pa >> 12; - - htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG - htab_end = (unsigned long)htab_data.htab + htab_size_bytes; - // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; - last_rpn = 0xfffff; - - printf("\nMem Find RPN\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("htab size : %.16lx\n", htab_size_bytes); - - for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { - if ( hpte1->dw0.dw0.v != 0 ) { - if ( hpte1->dw1.dw1.rpn == rpn ) { - printf(" Found rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); - printf(" hpte: %16.16lx *hpte1: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - } - } - } - printf("\nDone -------------------\n"); -} - -void mem_find_vsid() -{ - unsigned long htab_size_bytes; - unsigned long htab_end; - HPTE *hpte1; - unsigned long vsid; - int c; - - c = inchar(); - if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') - termch = c; - scanhex((void *)&vsid); - - htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG - htab_end = (unsigned long)htab_data.htab + htab_size_bytes; - - printf("\nMem Find VSID\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("htab size : %.16lx\n", htab_size_bytes); - - for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { - if ( hpte1->dw0.dw0.v != 0 ) { - if ( ((hpte1->dw0.dw0.avpn)>>5) == vsid ) { - printf(" Found vsid: %.16lx \n", ((hpte1->dw0.dw0.avpn) >> 5)); - printf(" hpte: %16.16lx *hpte1: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - } - } - } - printf("\nDone -------------------\n"); -} - -static void debug_trace(void) { unsigned long val, cmd, on; cmd = skipbl(); @@ -2204,3 +2000,47 @@ static void debug_trace(void) { cmd = skipbl(); } } + +static void dump_slb(void) +{ + int i; + unsigned long tmp; + + printf("SLB contents of cpu %d\n", smp_processor_id()); + + for (i = 0; i < naca->slb_size; i++) { + asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i)); + printf("%02d %016lx ", i, tmp); + + asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i)); + printf("%016lx\n", tmp); + } +} + +static void dump_stab(void) +{ + int i; + unsigned long *tmp = (unsigned long *)get_paca()->xStab_data.virt; + + printf("Segment table contents of cpu %d\n", smp_processor_id()); + + for (i = 0; i < PAGE_SIZE/16; i++) { + unsigned long a, b; + + a = *tmp++; + b = *tmp++; + + if (a || b) { + printf("%03d %016lx ", i, a); + printf("%016lx\n", b); + } + } +} + +void dump_segments(void) +{ + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) + dump_slb(); + else + dump_stab(); +} -- 2.53.0