📄 xmon.c
字号:
voidmemdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr){ unsigned n, prt; prt = 0; for( n = nb; n > 0; --n ) if( *p1++ != *p2++ ) if( ++prt <= maxpr ) printf("%.16x %.2x # %.16x %.2x\n", p1 - 1, p1[-1], p2 - 1, p2[-1]); if( prt > maxpr ) printf("Total of %d differences\n", prt);}static unsigned mend;static unsigned mask;voidmemlocate(){ unsigned a, n; unsigned char val[4]; last_cmd = "ml"; scanhex((void *)&mdest); if (termch != '\n') { termch = 0; scanhex((void *)&mend); if (termch != '\n') { termch = 0; scanhex((void *)&mval); mask = ~0; if (termch != '\n') termch = 0; scanhex((void *)&mask); } } n = 0; for (a = mdest; a < mend; a += 4) { if (mread(a, val, 4) == 4 && ((GETWORD(val) ^ mval) & mask) == 0) { printf("%.16x: %.16x\n", a, GETWORD(val)); if (++n >= 10) break; } }}static unsigned long mskip = 0x1000;static unsigned long mlim = 0xffffffff;voidmemzcan(){ unsigned char v; unsigned a; int ok, ook; scanhex(&mdest); if (termch != '\n') termch = 0; scanhex(&mskip); if (termch != '\n') termch = 0; scanhex(&mlim); ook = 0; for (a = mdest; a < mlim; a += mskip) { ok = mread(a, &v, 1); if (ok && !ook) { printf("%.8x .. ", a); fflush(stdout); } else if (!ok && ook) printf("%.8x\n", a - mskip); ook = ok; if (a + mskip < a) break; } if (ook) printf("%.8x\n", a - mskip);}/* Input scanning routines */intskipbl(){ int c; if( termch != 0 ){ c = termch; termch = 0; } else c = inchar(); while( c == ' ' || c == '\t' ) c = inchar(); return c;}#define N_PTREGS 44static char *regnames[N_PTREGS] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq", "trap", "dar", "dsisr", "res"};intscanhex(vp)unsigned long *vp;{ int c, d; unsigned long v; c = skipbl(); if (c == '%') { /* parse register name */ char regname[8]; int i; for (i = 0; i < sizeof(regname) - 1; ++i) { c = inchar(); if (!isalnum(c)) { termch = c; break; } regname[i] = c; } regname[i] = 0; for (i = 0; i < N_PTREGS; ++i) { if (strcmp(regnames[i], regname) == 0) { unsigned long *rp = (unsigned long *) xmon_regs[smp_processor_id()]; if (rp == NULL) { printf("regs not available\n"); return 0; } *vp = rp[i]; return 1; } } printf("invalid register name '%%%s'\n", regname); return 0; } d = hexdigit(c); if( d == EOF ){ termch = c; return 0; } v = 0; do { v = (v << 4) + d; c = inchar(); d = hexdigit(c); } while( d != EOF ); termch = c; *vp = v; return 1;}voidscannl(){ int c; c = termch; termch = 0; while( c != '\n' ) c = inchar();}inthexdigit(int c){ if( '0' <= c && c <= '9' ) return c - '0'; if( 'A' <= c && c <= 'F' ) return c - ('A' - 10); if( 'a' <= c && c <= 'f' ) return c - ('a' - 10); return EOF;}voidgetstring(char *s, int size){ int c; c = skipbl(); do { if( size > 1 ){ *s++ = c; --size; } c = inchar(); } while( c != ' ' && c != '\t' && c != '\n' ); termch = c; *s = 0;}static char line[256];static char *lineptr;voidflush_input(){ lineptr = NULL;}intinchar(){ if (lineptr == NULL || *lineptr == 0) { if (fgets(line, sizeof(line), stdin) == NULL) { lineptr = NULL; return EOF; } lineptr = line; } return *lineptr++;}voidtake_input(str)char *str;{ lineptr = str;}/* Starting at codeaddr scan forward for a tbtable and fill in the given table. Return non-zero if successful at doing something. */static intfind_tb_table(unsigned long codeaddr, struct tbtable *tab){ unsigned long codeaddr_max; unsigned long tbtab_start; int nr; int instr; int num_parms; if (tab == NULL) return 0; memset(tab, 0, sizeof(tab)); /* Scan instructions starting at codeaddr for 128k max */ for (codeaddr_max = codeaddr + 128*1024*4; codeaddr < codeaddr_max; codeaddr += 4) { nr = mread(codeaddr, &instr, 4); if (nr != 4) return 0; /* Bad read. Give up promptly. */ if (instr == 0) { /* table should follow. */ int version; unsigned long flags; tbtab_start = codeaddr; /* save it to compute func start addr */ codeaddr += 4; nr = mread(codeaddr, &flags, 8); if (nr != 8) return 0; /* Bad read or no tb table. */ tab->flags = flags; version = (flags >> 56) & 0xff; if (version != 0) continue; /* No tb table here. */ /* Now, like the version, some of the flags are values that are more conveniently extracted... */ tab->fp_saved = (flags >> 24) & 0x3f; tab->gpr_saved = (flags >> 16) & 0x3f; tab->fixedparms = (flags >> 8) & 0xff; tab->floatparms = (flags >> 1) & 0x7f; codeaddr += 8; num_parms = tab->fixedparms + tab->floatparms; if (num_parms) { unsigned int parminfo; int parm; if (num_parms > 32) return 1; /* incomplete */ 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. */}voidmem_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(){ 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(); if (cmd == '\n') { /* show current state */ unsigned long i; printf("naca->debug_switch = 0x%lx\n", naca->debug_switch); for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) { on = PPCDBG_BITVAL(i) & naca->debug_switch; printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : ""); if (((i+1) % 3) == 0) printf("\n"); } printf("\n"); return; } while (cmd != '\n') { on = 1; /* default if no sign given */ while (cmd == '+' || cmd == '-') { on = (cmd == '+'); cmd = inchar(); if (cmd == ' ' || cmd == '\n') { /* Turn on or off based on + or - */ naca->debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE; printf("Setting all values to %s...\n", on ? "on" : "off"); if (cmd == '\n') return; else cmd = skipbl(); } else termch = cmd; } termch = cmd; /* not +/- ... let scanhex see it */ scanhex((void *)&val); if (val >= 64) { printf("Value %x out of range:\n", val); return; } if (on) { naca->debug_switch |= PPCDBG_BITVAL(val); printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : ""); } else { naca->debug_switch &= ~PPCDBG_BITVAL(val); printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : ""); } cmd = skipbl(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -