1/* 2 * Routines providing a simple monitor for use on the PowerMac. 3 * 4 * Copyright (C) 1996 Paul Mackerras. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11#include <linux/config.h> 12#include <linux/errno.h> 13#include <linux/sched.h> 14#include <linux/smp.h> 15#include <linux/mm.h> 16#include <linux/reboot.h> 17#include <asm/ptrace.h> 18#include <asm/string.h> 19#include <asm/prom.h> 20#include <asm/machdep.h> 21#include <asm/processor.h> 22#include <asm/pgtable.h> 23#include <asm/mmu.h> 24#include <asm/mmu_context.h> 25#include <asm/naca.h> 26#include <asm/paca.h> 27#include <asm/ppcdebug.h> 28#include "nonstdio.h" 29#include "privinst.h" 30 31#define scanhex xmon_scanhex 32#define skipbl xmon_skipbl 33 34#ifdef CONFIG_SMP 35static unsigned long cpus_in_xmon = 0; 36static unsigned long got_xmon = 0; 37static volatile int take_xmon = -1; 38#endif /* CONFIG_SMP */ 39 40static unsigned long adrs; 41static int size = 1; 42static unsigned long ndump = 64; 43static unsigned long nidump = 16; 44static unsigned long ncsum = 4096; 45static int termch; 46 47static u_int bus_error_jmp[100]; 48#define setjmp xmon_setjmp 49#define longjmp xmon_longjmp 50 51#define memlist_entry list_entry 52#define memlist_next(x) ((x)->next) 53#define memlist_prev(x) ((x)->prev) 54 55 56/* Max number of stack frames we are willing to produce on a backtrace. */ 57#define MAXFRAMECOUNT 50 58 59/* Breakpoint stuff */ 60struct bpt { 61 unsigned long address; 62 unsigned instr; 63 unsigned long count; 64 unsigned char enabled; 65 char funcname[64]; /* function name for humans */ 66}; 67 68#define NBPTS 16 69static struct bpt bpts[NBPTS]; 70static struct bpt dabr; 71static struct bpt iabr; 72static unsigned bpinstr = 0x7fe00008; /* trap */ 73 74/* Prototypes */ 75extern void (*debugger_fault_handler)(struct pt_regs *); 76static int cmds(struct pt_regs *); 77static int mread(unsigned long, void *, int); 78static int mwrite(unsigned long, void *, int); 79static void handle_fault(struct pt_regs *); 80static void byterev(unsigned char *, int); 81static void memex(void); 82static int bsesc(void); 83static void dump(void); 84static void prdump(unsigned long, long); 85#ifdef __MWERKS__ 86static void prndump(unsigned, int); 87static int nvreadb(unsigned); 88#endif 89static int ppc_inst_dump(unsigned long, long); 90void print_address(unsigned long); 91static int getsp(void); 92static void dump_hash_table(void); 93static void backtrace(struct pt_regs *); 94static void excprint(struct pt_regs *); 95static void prregs(struct pt_regs *); 96static void memops(int); 97static void memlocate(void); 98static void memzcan(void); 99static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned); 100int skipbl(void); 101int scanhex(unsigned long *valp); 102static void scannl(void); 103static int hexdigit(int); 104void getstring(char *, int); 105static void flush_input(void); 106static int inchar(void); 107static void take_input(char *); 108/* static void openforth(void); */ 109static unsigned long read_spr(int); 110static void write_spr(int, unsigned long); 111static void super_regs(void); 112static void print_sysmap(void); 113static void remove_bpts(void); 114static void insert_bpts(void); 115static struct bpt *at_breakpoint(unsigned long pc); 116static void bpt_cmds(void); 117static void cacheflush(void); 118#ifdef CONFIG_SMP 119static void cpu_cmd(void); 120#endif /* CONFIG_SMP */ 121static void csum(void); 122static void mem_translate(void); 123static void mem_check(void); 124static void mem_find_real(void); 125static void mem_find_vsid(void); 126static void mem_check_pagetable_vsids (void); 127 128static void mem_map_check_slab(void); 129static void mem_map_lock_pages(void); 130static void mem_check_dup_rpn (void); 131static void debug_trace(void); 132 133extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long); 134extern void printf(const char *fmt, ...); 135extern void xmon_vfprintf(void *f, const char *fmt, va_list ap); 136extern int xmon_putc(int c, void *f); 137extern int putchar(int ch); 138extern int xmon_read_poll(void); 139extern int setjmp(u_int *); 140extern void longjmp(u_int *, int); 141extern unsigned long _ASR; 142 143pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va); /* from htab.c */ 144 145#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3]) 146 147static char *help_string = "\ 148Commands:\n\ 149 b show breakpoints\n\ 150 bd set data breakpoint\n\ 151 bi set instruction breakpoint\n\ 152 bc clear breakpoint\n\ 153 d dump bytes\n\ 154 di dump instructions\n\ 155 df dump float values\n\ 156 dd dump double values\n\ 157 e print exception information\n\ 158 f flush cache\n\ 159 h dump hash table\n\ 160 m examine/change memory\n\ 161 mm move a block of memory\n\ 162 ms set a block of memory\n\ 163 md compare two blocks of memory\n\ 164 ml locate a block of memory\n\ 165 mz zero a block of memory\n\ 166 mx translation information for an effective address\n\ 167 mi show information about memory allocation\n\ 168 M print System.map\n\ 169 p show the task list\n\ 170 r print registers\n\ 171 s single step\n\ 172 S print special registers\n\ 173 t print backtrace\n\ 174 T Enable/Disable PPCDBG flags\n\ 175 x exit monitor\n\ 176 z reboot\n\ 177 Z halt\n\ 178"; 179 180static int xmon_trace[NR_CPUS]; 181#define SSTEP 1 /* stepping because of 's' command */ 182#define BRSTEP 2 /* stepping over breakpoint */ 183 184/* 185 * Stuff for reading and writing memory safely 186 */ 187extern inline void sync(void) 188{ 189 asm volatile("sync; isync"); 190} 191 192/* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs). 193 A PPC stack frame looks like this: 194 195 High Address 196 Back Chain 197 FP reg save area 198 GP reg save area 199 Local var space 200 Parameter save area (SP+48) 201 TOC save area (SP+40) 202 link editor doubleword (SP+32) 203 compiler doubleword (SP+24) 204 LR save (SP+16) 205 CR save (SP+8) 206 Back Chain (SP+0) 207 208 Note that the LR (ret addr) may not be saved in the current frame if 209 no functions have been called from the current function. 210 */ 211 212/* 213 A traceback table typically follows each function. 214 The find_tb_table() func will fill in this struct. Note that the struct 215 is not an exact match with the encoded table defined by the ABI. It is 216 defined here more for programming convenience. 217 */ 218struct tbtable { 219 unsigned long flags; /* flags: */ 220#define TBTAB_FLAGSGLOBALLINK (1L<<47) 221#define TBTAB_FLAGSISEPROL (1L<<46) 222#define TBTAB_FLAGSHASTBOFF (1L<<45) 223#define TBTAB_FLAGSINTPROC (1L<<44) 224#define TBTAB_FLAGSHASCTL (1L<<43) 225#define TBTAB_FLAGSTOCLESS (1L<<42) 226#define TBTAB_FLAGSFPPRESENT (1L<<41) 227#define TBTAB_FLAGSNAMEPRESENT (1L<<38) 228#define TBTAB_FLAGSUSESALLOCA (1L<<37) 229#define TBTAB_FLAGSSAVESCR (1L<<33) 230#define TBTAB_FLAGSSAVESLR (1L<<32) 231#define TBTAB_FLAGSSTORESBC (1L<<31) 232#define TBTAB_FLAGSFIXUP (1L<<30) 233#define TBTAB_FLAGSPARMSONSTK (1L<<0) 234 unsigned char fp_saved; /* num fp regs saved f(32-n)..f31 */ 235 unsigned char gpr_saved; /* num gpr's saved */ 236 unsigned char fixedparms; /* num fixed point parms */ 237 unsigned char floatparms; /* num float parms */ 238 unsigned char parminfo[32]; /* types of args. null terminated */ 239#define TBTAB_PARMFIXED 1 240#define TBTAB_PARMSFLOAT 2 241#define TBTAB_PARMDFLOAT 3 242 unsigned int tb_offset; /* offset from start of func */ 243 unsigned long funcstart; /* addr of start of function */ 244 char name[64]; /* name of function (null terminated)*/ 245}; 246static int find_tb_table(unsigned long codeaddr, struct tbtable *tab); 247 248void 249xmon(struct pt_regs *excp) 250{ 251 struct pt_regs regs; 252 int cmd; 253 unsigned long msr; 254 255 if (excp == NULL) { 256 /* Ok, grab regs as they are now. 257 This won't do a particularily good job because the 258 prologue has already been executed. 259 ToDo: We could reach back into the callers save 260 area to do a better job of representing the 261 caller's state. 262 */ 263 asm volatile ("std 0,0(%0)\n\ 264 std 1,8(%0)\n\ 265 std 2,16(%0)\n\ 266 std 3,24(%0)\n\ 267 std 4,32(%0)\n\ 268 std 5,40(%0)\n\ 269 std 6,48(%0)\n\ 270 std 7,56(%0)\n\ 271 std 8,64(%0)\n\ 272 std 9,72(%0)\n\ 273 std 10,80(%0)\n\ 274 std 11,88(%0)\n\ 275 std 12,96(%0)\n\ 276 std 13,104(%0)\n\ 277 std 14,112(%0)\n\ 278 std 15,120(%0)\n\ 279 std 16,128(%0)\n\ 280 std 17,136(%0)\n\ 281 std 18,144(%0)\n\ 282 std 19,152(%0)\n\ 283 std 20,160(%0)\n\ 284 std 21,168(%0)\n\ 285 std 22,176(%0)\n\ 286 std 23,184(%0)\n\ 287 std 24,192(%0)\n\ 288 std 25,200(%0)\n\ 289 std 26,208(%0)\n\ 290 std 27,216(%0)\n\ 291 std 28,224(%0)\n\ 292 std 29,232(%0)\n\ 293 std 30,240(%0)\n\ 294 std 31,248(%0)" : : "b" (®s)); 295 printf("xmon called\n"); 296 /* Fetch the link reg for this stack frame. 297 NOTE: the prev printf fills in the lr. */ 298 regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2]; 299 regs.msr = get_msr(); 300 regs.ctr = get_ctr(); 301 regs.xer = get_xer(); 302 regs.ccr = get_cr(); 303 regs.trap = 0; 304 excp = ®s; 305 } 306 307 msr = get_msr(); 308 set_msrd(msr & ~MSR_EE); /* disable interrupts */ 309 excprint(excp); 310#ifdef CONFIG_SMP 311 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) 312 for (;;) 313 ; 314 while (test_and_set_bit(0, &got_xmon)) { 315 if (take_xmon == smp_processor_id()) { 316 take_xmon = -1; 317 break; 318 } 319 } 320#endif /* CONFIG_SMP */ 321 remove_bpts(); 322 cmd = cmds(excp); 323 if (cmd == 's') { 324 xmon_trace[smp_processor_id()] = SSTEP; 325 excp->msr |= 0x400; 326 } else if (at_breakpoint(excp->nip)) { 327 xmon_trace[smp_processor_id()] = BRSTEP; 328 excp->msr |= 0x400; 329 } else { 330 xmon_trace[smp_processor_id()] = 0; 331 insert_bpts(); 332 } 333#ifdef CONFIG_SMP 334 clear_bit(0, &got_xmon); 335 clear_bit(smp_processor_id(), &cpus_in_xmon); 336#endif /* CONFIG_SMP */ 337 set_msrd(msr); /* restore interrupt enable */ 338} 339 340/* Code can call this to get a backtrace and continue. */ 341void 342xmon_backtrace(const char *fmt, ...) 343{ 344 va_list ap; 345 struct pt_regs regs; 346 347 348 /* Ok, grab regs as they are now. 349 This won't do a particularily good job because the 350 prologue has already been executed. 351 ToDo: We could reach back into the callers save 352 area to do a better job of representing the 353 caller's state. 354 */ 355 asm volatile ("std 0,0(%0)\n\ 356 std 1,8(%0)\n\ 357 std 2,16(%0)\n\ 358 std 3,24(%0)\n\ 359 std 4,32(%0)\n\ 360 std 5,40(%0)\n\ 361 std 6,48(%0)\n\ 362 std 7,56(%0)\n\ 363 std 8,64(%0)\n\ 364 std 9,72(%0)\n\ 365 std 10,80(%0)\n\ 366 std 11,88(%0)\n\ 367 std 12,96(%0)\n\ 368 std 13,104(%0)\n\ 369 std 14,112(%0)\n\ 370 std 15,120(%0)\n\ 371 std 16,128(%0)\n\ 372 std 17,136(%0)\n\ 373 std 18,144(%0)\n\ 374 std 19,152(%0)\n\ 375 std 20,160(%0)\n\ 376 std 21,168(%0)\n\ 377 std 22,176(%0)\n\ 378 std 23,184(%0)\n\ 379 std 24,192(%0)\n\ 380 std 25,200(%0)\n\ 381 std 26,208(%0)\n\ 382 std 27,216(%0)\n\ 383 std 28,224(%0)\n\ 384 std 29,232(%0)\n\ 385 std 30,240(%0)\n\ 386 std 31,248(%0)" : : "b" (®s)); 387 /* Fetch the link reg for this stack frame. 388 NOTE: the prev printf fills in the lr. */ 389 regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2]; 390 regs.msr = get_msr(); 391 regs.ctr = get_ctr(); 392 regs.xer = get_xer(); 393 regs.ccr = get_cr(); 394 regs.trap = 0; 395 396 va_start(ap, fmt); 397 xmon_vfprintf(stdout, fmt, ap); 398 xmon_putc('\n', stdout); 399 va_end(ap); 400 take_input("\n"); 401 backtrace(®s); 402} 403 404/* Call this to poll for ^C during busy operations. 405 * Returns true if the user has hit ^C. 406 */ 407int 408xmon_interrupted(void) 409{ 410 int ret = xmon_read_poll(); 411 if (ret == 3) { 412 printf("\n^C interrupted.\n"); 413 return 1; 414 } 415 return 0; 416} 417 418 419void 420xmon_irq(int irq, void *d, struct pt_regs *regs) 421{ 422 unsigned long flags; 423 __save_flags(flags); 424 __cli(); 425 printf("Keyboard interrupt\n"); 426 xmon(regs); 427 __restore_flags(flags); 428} 429 430int 431xmon_bpt(struct pt_regs *regs) 432{ 433 struct bpt *bp; 434 435 bp = at_breakpoint(regs->nip); 436 if (!bp) 437 return 0; 438 if (bp->count) { 439 --bp->count; 440 remove_bpts(); 441 excprint(regs); 442 xmon_trace[smp_processor_id()] = BRSTEP; 443 regs->msr |= 0x400; 444 } else { 445 printf("Stopped at breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname); 446 xmon(regs); 447 } 448 return 1; 449} 450 451int 452xmon_sstep(struct pt_regs *regs) 453{ 454 if (!xmon_trace[smp_processor_id()]) 455 return 0; 456 if (xmon_trace[smp_processor_id()] == BRSTEP) { 457 xmon_trace[smp_processor_id()] = 0; 458 insert_bpts(); 459 } else { 460 xmon(regs); 461 } 462 return 1; 463} 464 465int 466xmon_dabr_match(struct pt_regs *regs) 467{ 468 if (dabr.enabled && dabr.count) { 469 --dabr.count; 470 remove_bpts(); 471 excprint(regs); 472 xmon_trace[smp_processor_id()] = BRSTEP; 473 regs->msr |= 0x400; 474 } else { 475 dabr.instr = regs->nip; 476 xmon(regs); 477 } 478 return 1; 479} 480 481int 482xmon_iabr_match(struct pt_regs *regs) 483{ 484 if (iabr.enabled && iabr.count) { 485 --iabr.count; 486 remove_bpts(); 487 excprint(regs); 488 xmon_trace[smp_processor_id()] = BRSTEP; 489 regs->msr |= 0x400; 490 } else { 491 xmon(regs); 492 } 493 return 1; 494} 495 496static struct bpt * 497at_breakpoint(unsigned long pc) 498{ 499 int i; 500 struct bpt *bp; 501 502 if (dabr.enabled && pc == dabr.instr) 503 return &dabr; 504 if (iabr.enabled && pc == iabr.address) 505 return &iabr; 506 bp = bpts; 507 for (i = 0; i < NBPTS; ++i, ++bp) 508 if (bp->enabled && pc == bp->address) 509 return bp; 510 return 0; 511} 512 513static void 514insert_bpts() 515{ 516 int i; 517 struct bpt *bp; 518 519 if (naca->platform != PLATFORM_PSERIES) 520 return; 521 bp = bpts; 522 for (i = 0; i < NBPTS; ++i, ++bp) { 523 if (!bp->enabled) 524 continue; 525 if (mread(bp->address, &bp->instr, 4) != 4 526 || mwrite(bp->address, &bpinstr, 4) != 4) { 527 printf("Couldn't insert breakpoint at %x, disabling\n", 528 bp->address); 529 bp->enabled = 0; 530 } else { 531 store_inst((void *)bp->address); 532 } 533 } 534 535 if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) { 536 if (dabr.enabled) 537 set_dabr(dabr.address); 538 if (iabr.enabled) 539 set_iabr(iabr.address); 540 } 541} 542 543static void 544remove_bpts() 545{ 546 int i; 547 struct bpt *bp; 548 unsigned instr; 549 550 if (naca->platform != PLATFORM_PSERIES) 551 return; 552 if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) { 553 set_dabr(0); 554 set_iabr(0); 555 } 556 557 bp = bpts; 558 for (i = 0; i < NBPTS; ++i, ++bp) { 559 if (!bp->enabled) 560 continue; 561 if (mread(bp->address, &instr, 4) == 4 562 && instr == bpinstr 563 && mwrite(bp->address, &bp->instr, 4) != 4) 564 printf("Couldn't remove breakpoint at %x\n", 565 bp->address); 566 else 567 store_inst((void *)bp->address); 568 } 569} 570 571static char *last_cmd; 572 573/* Command interpreting routine */ 574static int 575cmds(struct pt_regs *excp) 576{ 577 int cmd; 578 579 last_cmd = NULL; 580 for(;;) { 581#ifdef CONFIG_SMP 582 printf("%d:", smp_processor_id()); 583#endif /* CONFIG_SMP */ 584 printf("mon> "); 585 fflush(stdout); 586 flush_input(); 587 termch = 0; 588 cmd = skipbl(); 589 if( cmd == '\n' ) { 590 if (last_cmd == NULL) 591 continue; 592 take_input(last_cmd); 593 last_cmd = NULL; 594 cmd = inchar(); 595 } 596 switch (cmd) { 597 case 'z': 598 printf("Rebooting machine now..."); 599 machine_restart(NULL); 600 break; 601 case 'Z': 602 printf("Halting machine now..."); 603 machine_halt(); 604 break; 605 case 'm': 606 cmd = inchar(); 607 switch (cmd) { 608 case 'm': 609 case 's': 610 case 'd': 611 memops(cmd); 612 break; 613 case 'l': 614 memlocate(); 615 break; 616 case 'z': 617 memzcan(); 618 break; 619 case 'x': 620 mem_translate(); 621 break; 622 case 'c': 623 mem_check(); 624 break; 625 case 'j': 626 mem_map_check_slab(); 627 break; 628 case 'f': 629 mem_find_real(); 630 break; 631 case 'e': 632 mem_find_vsid(); 633 break; 634 case 'r': 635 mem_check_dup_rpn(); 636 break; 637 case 'i': 638 show_mem(); 639 break; 640 case 'o': 641 mem_check_pagetable_vsids (); 642 break; 643 case 'q': 644 mem_map_lock_pages() ; 645 break; 646 default: 647 termch = cmd; 648 memex(); 649 } 650 break; 651 case 'd': 652 dump(); 653 break; 654 case 'r': 655 if (excp != NULL) 656 prregs(excp); /* print regs */ 657 break; 658 case 'e': 659 if (excp == NULL) 660 printf("No exception information\n"); 661 else 662 excprint(excp); 663 break; 664 case 'M': 665 print_sysmap(); 666 break; 667 case 'S': 668 super_regs(); 669 break; 670 case 't': 671 backtrace(excp); 672 break; 673 case 'f': 674 cacheflush(); 675 break; 676 case 'h': 677 dump_hash_table(); 678 break; 679 case 's': 680 case 'x': 681 case EOF: 682 return cmd; 683 case '?': 684 printf(help_string); 685 break; 686 case 'p': 687 show_state(); 688 break; 689 case 'b': 690 bpt_cmds(); 691 break; 692 case 'C': 693 csum(); 694 break; 695#ifdef CONFIG_SMP 696 case 'c': 697 cpu_cmd(); 698 break; 699#endif /* CONFIG_SMP */ 700 case 'T': 701 debug_trace(); 702 break; 703 default: 704 printf("Unrecognized command: "); 705 do { 706 if( ' ' < cmd && cmd <= '~' ) 707 putchar(cmd); 708 else 709 printf("\\x%x", cmd); 710 cmd = inchar(); 711 } while (cmd != '\n'); 712 printf(" (type ? for help)\n"); 713 break; 714 } 715 } 716} 717 718#ifdef CONFIG_SMP 719static void cpu_cmd(void) 720{ 721 unsigned long cpu; 722 int timeout; 723 int cmd; 724 725 cmd = inchar(); 726 if (cmd == 'i') { 727 printf("stopping all cpus\n"); 728 /* interrupt other cpu(s) */ 729 cpu = MSG_ALL_BUT_SELF; 730 smp_send_xmon_break(cpu); 731 return; 732 } 733 termch = cmd; 734 if (!scanhex(&cpu)) { 735 /* print cpus waiting or in xmon */ 736 printf("cpus stopped:"); 737 for (cpu = 0; cpu < NR_CPUS; ++cpu) { 738 if (test_bit(cpu, &cpus_in_xmon)) { 739 printf(" %d", cpu); 740 if (cpu == smp_processor_id()) 741 printf("*", cpu); 742 } 743 } 744 printf("\n"); 745 return; 746 } 747 /* try to switch to cpu specified */ 748 take_xmon = cpu; 749 timeout = 10000000; 750 while (take_xmon >= 0) { 751 if (--timeout == 0) { 752 /* yes there's a race here */ 753 take_xmon = -1; 754 printf("cpu %u didn't take control\n", cpu); 755 return; 756 } 757 } 758 /* now have to wait to be given control back */ 759 while (test_and_set_bit(0, &got_xmon)) { 760 if (take_xmon == smp_processor_id()) { 761 take_xmon = -1; 762 break; 763 } 764 } 765} 766#endif /* CONFIG_SMP */ 767 768static unsigned short fcstab[256] = { 769 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 770 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 771 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 772 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 773 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 774 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 775 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 776 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 777 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 778 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 779 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 780 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 781 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 782 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 783 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 784 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 785 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 786 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 787 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 788 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 789 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 790 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 791 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 792 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 793 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 794 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 795 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 796 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 797 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 798 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 799 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 800 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 801}; 802 803#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) 804 805static void 806csum(void) 807{ 808 unsigned int i; 809 unsigned short fcs; 810 unsigned char v; 811 812 if (!scanhex(&adrs)) 813 return; 814 if (!scanhex(&ncsum)) 815 return; 816 fcs = 0xffff; 817 for (i = 0; i < ncsum; ++i) { 818 if (mread(adrs+i, &v, 1) == 0) { 819 printf("csum stopped at %x\n", adrs+i); 820 break; 821 } 822 fcs = FCS(fcs, v); 823 } 824 printf("%x\n", fcs); 825} 826 827static char *breakpoint_help_string = 828 "Breakpoint command usage:\n" 829 "b show breakpoints\n" 830 "b <addr> [cnt] set breakpoint at given instr addr\n" 831 "bc clear all breakpoints\n" 832 "bc <n/addr> clear breakpoint number n or at addr\n" 833 "bi <addr> [cnt] set hardware instr breakpoint (broken?)\n" 834 "bd <addr> [cnt] set hardware data breakpoint (broken?)\n" 835 ""; 836 837static void 838bpt_cmds(void) 839{ 840 int cmd; 841 unsigned long a; 842 int mode, i; 843 struct bpt *bp; 844 struct tbtable tab; 845 846 cmd = inchar(); 847 switch (cmd) { 848 case 'd': /* bd - hardware data breakpoint */ 849 if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { 850 printf("Not implemented on POWER4\n"); 851 break; 852 } 853 mode = 7; 854 cmd = inchar(); 855 if (cmd == 'r') 856 mode = 5; 857 else if (cmd == 'w') 858 mode = 6; 859 else 860 termch = cmd; 861 dabr.address = 0; 862 dabr.count = 0; 863 dabr.enabled = scanhex(&dabr.address); 864 scanhex(&dabr.count); 865 if (dabr.enabled) 866 dabr.address = (dabr.address & ~7) | mode; 867 break; 868 case 'i': /* bi - hardware instr breakpoint */ 869 if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { 870 break; 871 } 872 iabr.address = 0; 873 iabr.count = 0; 874 iabr.enabled = scanhex(&iabr.address); 875 if (iabr.enabled) 876 iabr.address |= 3; 877 scanhex(&iabr.count); 878 break; 879 case 'c': 880 if (!scanhex(&a)) { 881 /* clear all breakpoints */ 882 for (i = 0; i < NBPTS; ++i) 883 bpts[i].enabled = 0; 884 iabr.enabled = 0; 885 dabr.enabled = 0; 886 printf("All breakpoints cleared\n"); 887 } else { 888 if (a <= NBPTS && a >= 1) { 889 /* assume a breakpoint number */ 890 --a; /* bp nums are 1 based */ 891 bp = &bpts[a]; 892 } else { 893 /* assume a breakpoint address */ 894 bp = at_breakpoint(a); 895 } 896 if (bp == 0) { 897 printf("No breakpoint at %x\n", a); 898 } else { 899 printf("Cleared breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname); 900 bp->enabled = 0; 901 } 902 } 903 break; 904 case '?': 905 printf(breakpoint_help_string); 906 break; 907 default: 908 termch = cmd; 909 cmd = skipbl(); 910 if (cmd == '?') { 911 printf(breakpoint_help_string); 912 break; 913 } 914 termch = cmd; 915 if (!scanhex(&a)) { 916 /* print all breakpoints */ 917 int bpnum; 918 919 printf(" type address count\n"); 920 if (dabr.enabled) { 921 printf(" data %.16lx %8x [", dabr.address & ~7, 922 dabr.count); 923 if (dabr.address & 1) 924 printf("r"); 925 if (dabr.address & 2) 926 printf("w"); 927 printf("]\n"); 928 } 929 if (iabr.enabled) 930 printf(" inst %.16lx %8x\n", iabr.address & ~3, 931 iabr.count); 932 for (bp = bpts, bpnum = 1; bp < &bpts[NBPTS]; ++bp, ++bpnum) 933 if (bp->enabled) 934 printf("%2x trap %.16lx %8x %s\n", bpnum, bp->address, bp->count, bp->funcname); 935 break; 936 } 937 bp = at_breakpoint(a); 938 if (bp == 0) { 939 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) 940 if (!bp->enabled) 941 break; 942 if (bp >= &bpts[NBPTS]) { 943 printf("Sorry, no free breakpoints. Please clear one first.\n"); 944 break; 945 } 946 } 947 bp->enabled = 1; 948 bp->address = a; 949 bp->count = 0; 950 scanhex(&bp->count); 951 /* Find the function name just once. */ 952 bp->funcname[0] = '\0'; 953 if (find_tb_table(bp->address, &tab) && tab.name[0]) { 954 /* Got a nice name for it. */ 955 int delta = bp->address - tab.funcstart; 956 sprintf(bp->funcname, "%s+0x%x", tab.name, delta); 957 } 958 printf("Set breakpoint %2x trap %.16lx %8x %s\n", (bp-bpts)+1, bp->address, bp->count, bp->funcname); 959 break; 960 } 961} 962 963/* Very cheap human name for vector lookup. */ 964static 965const char *getvecname(unsigned long vec) 966{ 967 char *ret; 968 switch (vec) { 969 case 0x100: ret = "(System Reset)"; break; 970 case 0x200: ret = "(Machine Check)"; break; 971 case 0x300: ret = "(Data Access)"; break; 972 case 0x400: ret = "(Instruction Access)"; break; 973 case 0x500: ret = "(Hardware Interrupt)"; break; 974 case 0x600: ret = "(Alignment)"; break; 975 case 0x700: ret = "(Program Check)"; break; 976 case 0x800: ret = "(FPU Unavailable)"; break; 977 case 0x900: ret = "(Decrementer)"; break; 978 case 0xc00: ret = "(System Call)"; break; 979 case 0xd00: ret = "(Single Step)"; break; 980 case 0xf00: ret = "(Performance Monitor)"; break; 981 default: ret = ""; 982 } 983 return ret; 984} 985 986static void 987backtrace(struct pt_regs *excp) 988{ 989 unsigned long sp; 990 unsigned long lr; 991 unsigned long stack[3]; 992 struct pt_regs regs; 993 struct tbtable tab; 994 int framecount; 995 char *funcname; 996 /* declare these as raw ptrs so we don't get func descriptors */ 997 extern void *ret_from_except, *ret_from_syscall_1; 998 999 if (excp != NULL) { 1000 lr = excp->link; 1001 sp = excp->gpr[1]; 1002 } else { 1003 /* Use care not to call any function before this point 1004 so the saved lr has a chance of being good. */ 1005 asm volatile ("mflr %0" : "=r" (lr) :); 1006 sp = getsp(); 1007 } 1008 scanhex(&sp); 1009 scannl(); 1010 for (framecount = 0; 1011 sp != 0 && framecount < MAXFRAMECOUNT; 1012 sp = stack[0], framecount++) { 1013 if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) 1014 break; 1015 printf("%.16lx %.16lx", sp, stack[2]); 1016 /* TAI -- for now only the ones cast to unsigned long will match. 1017 * Need to test the rest... 1018 */ 1019 if ((stack[2] == (unsigned long)ret_from_except && 1020 (funcname = "ret_from_except")) 1021 || (stack[2] == (unsigned long)ret_from_syscall_1 && 1022 (funcname = "ret_from_syscall_1")) 1023 ) { 1024 printf(" %s\n", funcname); 1025 if (mread(sp+112, ®s, sizeof(regs)) != sizeof(regs)) 1026 break; 1027 printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112); 1028 printf(" %.16lx", regs.nip); 1029 if ((regs.nip & 0xffffffff00000000UL) && 1030 find_tb_table(regs.nip, &tab)) { 1031 int delta = regs.nip-tab.funcstart; 1032 if (delta < 0) 1033 printf(" <unknown code>"); 1034 else 1035 printf(" %s+0x%x", tab.name, delta); 1036 } 1037 printf("\n"); 1038 if (regs.gpr[1] < sp) { 1039 printf("<Stack drops into 32-bit userspace %.16lx>\n", regs.gpr[1]); 1040 break; 1041 } 1042 1043 sp = regs.gpr[1]; 1044 if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) 1045 break; 1046 } else { 1047 if (stack[2] && find_tb_table(stack[2], &tab)) { 1048 int delta = stack[2]-tab.funcstart; 1049 if (delta < 0) 1050 printf(" <unknown code>"); 1051 else 1052 printf(" %s+0x%x", tab.name, delta); 1053 } 1054 printf("\n"); 1055 } 1056 if (stack[0] && stack[0] <= sp) { 1057 if ((stack[0] & 0xffffffff00000000UL) == 0) 1058 printf("<Stack drops into 32-bit userspace %.16lx>\n", stack[0]); 1059 else 1060 printf("<Corrupt stack. Next backchain is %.16lx>\n", stack[0]); 1061 break; 1062 } 1063 } 1064 if (framecount >= MAXFRAMECOUNT) 1065 printf("<Punt. Too many stack frames>\n"); 1066} 1067 1068int 1069getsp() 1070{ 1071 int x; 1072 1073 asm("mr %0,1" : "=r" (x) :); 1074 return x; 1075} 1076 1077spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED; 1078 1079void 1080excprint(struct pt_regs *fp) 1081{ 1082 struct task_struct *c; 1083 struct tbtable tab; 1084 unsigned long flags; 1085 1086 spin_lock_irqsave(&exception_print_lock, flags); 1087 1088#ifdef CONFIG_SMP 1089 printf("cpu %d: ", smp_processor_id()); 1090#endif /* CONFIG_SMP */ 1091 1092 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(fp->trap), fp); 1093 printf(" pc: %lx", fp->nip); 1094 if (find_tb_table(fp->nip, &tab) && tab.name[0]) { 1095 /* Got a nice name for it */ 1096 int delta = fp->nip - tab.funcstart; 1097 printf(" (%s+0x%x)", tab.name, delta); 1098 } 1099 printf("\n"); 1100 printf(" lr: %lx", fp->link); 1101 if (find_tb_table(fp->link, &tab) && tab.name[0]) { 1102 /* Got a nice name for it */ 1103 int delta = fp->link - tab.funcstart; 1104 printf(" (%s+0x%x)", tab.name, delta); 1105 } 1106 printf("\n"); 1107 printf(" sp: %lx\n", fp->gpr[1]); 1108 printf(" msr: %lx\n", fp->msr); 1109 1110 if (fp->trap == 0x300 || fp->trap == 0x600) { 1111 printf(" dar: %lx\n", fp->dar); 1112 printf(" dsisr: %lx\n", fp->dsisr); 1113 } 1114 1115 c = current; 1116 printf(" current = 0x%lx\n", c); 1117 printf(" paca = 0x%lx\n", get_paca()); 1118 if (c) { 1119 printf(" current = %lx, pid = %ld, comm = %s\n", 1120 c, c->pid, c->comm); 1121 } 1122 1123 spin_unlock_irqrestore(&exception_print_lock, flags); 1124} 1125 1126void 1127prregs(struct pt_regs *fp) 1128{ 1129 int n; 1130 unsigned long base; 1131 1132 if (scanhex((void *)&base)) 1133 fp = (struct pt_regs *) base; 1134 for (n = 0; n < 16; ++n) 1135 printf("R%.2ld = %.16lx R%.2ld = %.16lx\n", n, fp->gpr[n], 1136 n+16, fp->gpr[n+16]); 1137 printf("pc = %.16lx msr = %.16lx\nlr = %.16lx cr = %.16lx\n", 1138 fp->nip, fp->msr, fp->link, fp->ccr); 1139 printf("ctr = %.16lx xer = %.16lx trap = %8lx\n", 1140 fp->ctr, fp->xer, fp->trap); 1141} 1142 1143void 1144cacheflush(void) 1145{ 1146 int cmd; 1147 unsigned long nflush; 1148 1149 cmd = inchar(); 1150 if (cmd != 'i') 1151 termch = cmd; 1152 scanhex((void *)&adrs); 1153 if (termch != '\n') 1154 termch = 0; 1155 nflush = 1; 1156 scanhex(&nflush); 1157 nflush = (nflush + 31) / 32; 1158 if (cmd != 'i') { 1159 for (; nflush > 0; --nflush, adrs += 0x20) 1160 cflush((void *) adrs); 1161 } else { 1162 for (; nflush > 0; --nflush, adrs += 0x20) 1163 cinval((void *) adrs); 1164 } 1165} 1166 1167unsigned long 1168read_spr(int n) 1169{ 1170 unsigned int instrs[2]; 1171 unsigned long (*code)(void); 1172 unsigned long opd[3]; 1173 1174 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); 1175 instrs[1] = 0x4e800020; 1176 opd[0] = (unsigned long)instrs; 1177 opd[1] = 0; 1178 opd[2] = 0; 1179 store_inst(instrs); 1180 store_inst(instrs+1); 1181 code = (unsigned long (*)(void)) opd; 1182 1183 return code(); 1184} 1185 1186void 1187write_spr(int n, unsigned long val) 1188{ 1189 unsigned int instrs[2]; 1190 unsigned long (*code)(unsigned long); 1191 unsigned long opd[3]; 1192 1193 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); 1194 instrs[1] = 0x4e800020; 1195 opd[0] = (unsigned long)instrs; 1196 opd[1] = 0; 1197 opd[2] = 0; 1198 store_inst(instrs); 1199 store_inst(instrs+1); 1200 code = (unsigned long (*)(unsigned long)) opd; 1201 1202 code(val); 1203} 1204 1205static unsigned long regno; 1206extern char exc_prolog; 1207extern char dec_exc; 1208 1209void 1210print_sysmap(void) 1211{ 1212 extern char *sysmap; 1213 if ( sysmap ) 1214 printf("System.map: \n%s", sysmap); 1215} 1216 1217void 1218super_regs() 1219{ 1220 int i, cmd; 1221 unsigned long val; 1222 struct paca_struct* ptrPaca = NULL; 1223 struct ItLpPaca* ptrLpPaca = NULL; 1224 struct ItLpRegSave* ptrLpRegSave = NULL; 1225 1226 cmd = skipbl(); 1227 if (cmd == '\n') { 1228 unsigned long sp, toc; 1229 asm("mr %0,1" : "=r" (sp) :); 1230 asm("mr %0,2" : "=r" (toc) :); 1231 1232 printf("msr = %.16lx sprg0= %.16lx\n", get_msr(), get_sprg0()); 1233 printf("pvr = %.16lx sprg1= %.16lx\n", get_pvr(), get_sprg1()); 1234 printf("dec = %.16lx sprg2= %.16lx\n", get_dec(), get_sprg2()); 1235 printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3()); 1236 printf("toc = %.16lx dar = %.16lx\n", toc, get_dar()); 1237 printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1()); 1238 printf("asr = %.16lx\n", mfasr()); 1239 for (i = 0; i < 8; ++i) 1240 printf("sr%.2ld = %.16lx sr%.2ld = %.16lx\n", i, get_sr(i), i+8, get_sr(i+8)); 1241 1242 // Dump out relevant Paca data areas. 1243 printf("Paca: \n"); 1244 ptrPaca = get_paca(); 1245 1246 printf(" Local Processor Control Area (LpPaca): \n"); 1247 ptrLpPaca = ptrPaca->xLpPacaPtr; 1248 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", ptrLpPaca->xSavedSrr0, ptrLpPaca->xSavedSrr1); 1249 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", ptrLpPaca->xSavedGpr3, ptrLpPaca->xSavedGpr4); 1250 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->xSavedGpr5); 1251 1252 printf(" Local Processor Register Save Area (LpRegSave): \n"); 1253 ptrLpRegSave = ptrPaca->xLpRegSavePtr; 1254 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); 1255 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); 1256 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); 1257 1258 return; 1259 } 1260 1261 scanhex(®no); 1262 switch (cmd) { 1263 case 'w': 1264 val = read_spr(regno); 1265 scanhex(&val); 1266 write_spr(regno, val); 1267 /* fall through */ 1268 case 'r': 1269 printf("spr %lx = %lx\n", regno, read_spr(regno)); 1270 break; 1271 case 's': 1272 val = get_sr(regno); 1273 scanhex(&val); 1274 set_sr(regno, val); 1275 break; 1276 case 'm': 1277 val = get_msr(); 1278 scanhex(&val); 1279 set_msrd(val); 1280 break; 1281 } 1282 scannl(); 1283} 1284 1285 1286#ifndef CONFIG_PPC64BRIDGE 1287static void 1288dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) 1289{ 1290 extern void *Hash; 1291 extern unsigned long Hash_size; 1292 unsigned *htab = Hash; 1293 unsigned hsize = Hash_size; 1294 unsigned v, hmask, va, last_va; 1295 int found, last_found, i; 1296 unsigned *hg, w1, last_w2, last_va0; 1297 1298 last_found = 0; 1299 hmask = hsize / 64 - 1; 1300 va = start; 1301 start = (start >> 12) & 0xffff; 1302 end = (end >> 12) & 0xffff; 1303 for (v = start; v < end; ++v) { 1304 found = 0; 1305 hg = htab + (((v ^ seg) & hmask) * 16); 1306 w1 = 0x80000000 | (seg << 7) | (v >> 10); 1307 for (i = 0; i < 8; ++i, hg += 2) { 1308 if (*hg == w1) { 1309 found = 1; 1310 break; 1311 } 1312 } 1313 if (!found) { 1314 w1 ^= 0x40; 1315 hg = htab + ((~(v ^ seg) & hmask) * 16); 1316 for (i = 0; i < 8; ++i, hg += 2) { 1317 if (*hg == w1) { 1318 found = 1; 1319 break; 1320 } 1321 } 1322 } 1323 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) { 1324 if (last_found) { 1325 if (last_va != last_va0) 1326 printf(" ... %x", last_va); 1327 printf("\n"); 1328 } 1329 if (found) { 1330 printf("%x to %x", va, hg[1]); 1331 last_va0 = va; 1332 } 1333 last_found = found; 1334 } 1335 if (found) { 1336 last_w2 = hg[1] & ~0x180; 1337 last_va = va; 1338 } 1339 va += 4096; 1340 } 1341 if (last_found) 1342 printf(" ... %x\n", last_va); 1343} 1344 1345#else /* CONFIG_PPC64BRIDGE */ 1346static void 1347dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) 1348{ 1349 extern void *Hash; 1350 extern unsigned long Hash_size; 1351 unsigned *htab = Hash; 1352 unsigned hsize = Hash_size; 1353 unsigned v, hmask, va, last_va; 1354 int found, last_found, i; 1355 unsigned *hg, w1, last_w2, last_va0; 1356 1357 last_found = 0; 1358 hmask = hsize / 128 - 1; 1359 va = start; 1360 start = (start >> 12) & 0xffff; 1361 end = (end >> 12) & 0xffff; 1362 for (v = start; v < end; ++v) { 1363 found = 0; 1364 hg = htab + (((v ^ seg) & hmask) * 32); 1365 w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4); 1366 for (i = 0; i < 8; ++i, hg += 4) { 1367 if (hg[1] == w1) { 1368 found = 1; 1369 break; 1370 } 1371 } 1372 if (!found) { 1373 w1 ^= 2; 1374 hg = htab + ((~(v ^ seg) & hmask) * 32); 1375 for (i = 0; i < 8; ++i, hg += 4) { 1376 if (hg[1] == w1) { 1377 found = 1; 1378 break; 1379 } 1380 } 1381 } 1382 if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) { 1383 if (last_found) { 1384 if (last_va != last_va0) 1385 printf(" ... %x", last_va); 1386 printf("\n"); 1387 } 1388 if (found) { 1389 printf("%x to %x", va, hg[3]); 1390 last_va0 = va; 1391 } 1392 last_found = found; 1393 } 1394 if (found) { 1395 last_w2 = hg[3] & ~0x180; 1396 last_va = va; 1397 } 1398 va += 4096; 1399 } 1400 if (last_found) 1401 printf(" ... %x\n", last_va); 1402} 1403#endif /* CONFIG_PPC64BRIDGE */ 1404 1405static unsigned long hash_ctx; 1406static unsigned long hash_start; 1407static unsigned long hash_end; 1408 1409static void 1410dump_hash_table() 1411{ 1412 int seg; 1413 unsigned seg_start, seg_end; 1414 1415 hash_ctx = 0; 1416 hash_start = 0; 1417 hash_end = 0xfffff000; 1418 scanhex(&hash_ctx); 1419 scanhex(&hash_start); 1420 scanhex(&hash_end); 1421 printf("Mappings for context %x\n", hash_ctx); 1422 seg_start = hash_start; 1423 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) { 1424 seg_end = (seg << 28) | 0x0ffff000; 1425 if (seg_end > hash_end) 1426 seg_end = hash_end; 1427 dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end); 1428 seg_start = seg_end + 0x1000; 1429 } 1430} 1431 1432int 1433mread(unsigned long adrs, void *buf, int size) 1434{ 1435 volatile int n; 1436 char *p, *q; 1437 1438 n = 0; 1439 if( setjmp(bus_error_jmp) == 0 ){ 1440 debugger_fault_handler = handle_fault; 1441 sync(); 1442 p = (char *) adrs; 1443 q = (char *) buf; 1444 switch (size) { 1445 case 2: *(short *)q = *(short *)p; break; 1446 case 4: *(int *)q = *(int *)p; break; 1447 default: 1448 for( ; n < size; ++n ) { 1449 *q++ = *p++; 1450 sync(); 1451 } 1452 } 1453 sync(); 1454 /* wait a little while to see if we get a machine check */ 1455 __delay(200); 1456 n = size; 1457 } 1458 debugger_fault_handler = 0; 1459 return n; 1460} 1461 1462int 1463mwrite(unsigned long adrs, void *buf, int size) 1464{ 1465 volatile int n; 1466 char *p, *q; 1467 1468 n = 0; 1469 if( setjmp(bus_error_jmp) == 0 ){ 1470 debugger_fault_handler = handle_fault; 1471 sync(); 1472 p = (char *) adrs; 1473 q = (char *) buf; 1474 switch (size) { 1475 case 2: *(short *)p = *(short *)q; break; 1476 case 4: *(int *)p = *(int *)q; break; 1477 default: 1478 for( ; n < size; ++n ) { 1479 *p++ = *q++; 1480 sync(); 1481 } 1482 } 1483 sync(); 1484 /* wait a little while to see if we get a machine check */ 1485 __delay(200); 1486 n = size; 1487 } else { 1488 printf("*** Error writing address %x\n", adrs + n); 1489 } 1490 debugger_fault_handler = 0; 1491 return n; 1492} 1493 1494static int fault_type; 1495static char *fault_chars[] = { "--", "**", "##" }; 1496 1497static void 1498handle_fault(struct pt_regs *regs) 1499{ 1500 fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2; 1501 longjmp(bus_error_jmp, 1); 1502} 1503 1504#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t)) 1505 1506void 1507byterev(unsigned char *val, int size) 1508{ 1509 int t; 1510 1511 switch (size) { 1512 case 2: 1513 SWAP(val[0], val[1], t); 1514 break; 1515 case 4: 1516 SWAP(val[0], val[3], t); 1517 SWAP(val[1], val[2], t); 1518 break; 1519 case 8: /* is there really any use for this? */ 1520 SWAP(val[0], val[7], t); 1521 SWAP(val[1], val[6], t); 1522 SWAP(val[2], val[5], t); 1523 SWAP(val[3], val[4], t); 1524 break; 1525 } 1526} 1527 1528static int brev; 1529static int mnoread; 1530 1531static char *memex_help_string = 1532 "Memory examine command usage:\n" 1533 "m [addr] [flags] examine/change memory\n" 1534 " addr is optional. will start where left off.\n" 1535 " flags may include chars from this set:\n" 1536 " b modify by bytes (default)\n" 1537 " w modify by words (2 byte)\n" 1538 " l modify by longs (4 byte)\n" 1539 " d modify by doubleword (8 byte)\n" 1540 " r toggle reverse byte order mode\n" 1541 " n do not read memory (for i/o spaces)\n" 1542 " . ok to read (default)\n" 1543 "NOTE: flags are saved as defaults\n" 1544 ""; 1545 1546static char *memex_subcmd_help_string = 1547 "Memory examine subcommands:\n" 1548 " hexval write this val to current location\n" 1549 " 'string' write chars from string to this location\n" 1550 " ' increment address\n" 1551 " ^ decrement address\n" 1552 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n" 1553 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n" 1554 " ` clear no-read flag\n" 1555 " ; stay at this addr\n" 1556 " v change to byte mode\n" 1557 " w change to word (2 byte) mode\n" 1558 " l change to long (4 byte) mode\n" 1559 " u change to doubleword (8 byte) mode\n" 1560 " m addr change current addr\n" 1561 " n toggle no-read flag\n" 1562 " r toggle byte reverse flag\n" 1563 " < count back up count bytes\n" 1564 " > count skip forward count bytes\n" 1565 " x exit this mode\n" 1566 ""; 1567 1568void 1569memex() 1570{ 1571 int cmd, inc, i, nslash; 1572 unsigned long n; 1573 unsigned char val[16]; 1574 1575 scanhex((void *)&adrs); 1576 cmd = skipbl(); 1577 if (cmd == '?') { 1578 printf(memex_help_string); 1579 return; 1580 } else { 1581 termch = cmd; 1582 } 1583 last_cmd = "m\n"; 1584 while ((cmd = skipbl()) != '\n') { 1585 switch( cmd ){ 1586 case 'b': size = 1; break; 1587 case 'w': size = 2; break; 1588 case 'l': size = 4; break; 1589 case 'd': size = 8; break; 1590 case 'r': brev = !brev; break; 1591 case 'n': mnoread = 1; break; 1592 case '.': mnoread = 0; break; 1593 } 1594 } 1595 if( size <= 0 ) 1596 size = 1; 1597 else if( size > 8 ) 1598 size = 8; 1599 for(;;){ 1600 if (!mnoread) 1601 n = mread(adrs, val, size); 1602 printf("%.16x%c", adrs, brev? 'r': ' '); 1603 if (!mnoread) { 1604 if (brev) 1605 byterev(val, size); 1606 putchar(' '); 1607 for (i = 0; i < n; ++i) 1608 printf("%.2x", val[i]); 1609 for (; i < size; ++i) 1610 printf("%s", fault_chars[fault_type]); 1611 } 1612 putchar(' '); 1613 inc = size; 1614 nslash = 0; 1615 for(;;){ 1616 if( scanhex(&n) ){ 1617 for (i = 0; i < size; ++i) 1618 val[i] = n >> (i * 8); 1619 if (!brev) 1620 byterev(val, size); 1621 mwrite(adrs, val, size); 1622 inc = size; 1623 } 1624 cmd = skipbl(); 1625 if (cmd == '\n') 1626 break; 1627 inc = 0; 1628 switch (cmd) { 1629 case '\'': 1630 for(;;){ 1631 n = inchar(); 1632 if( n == '\\' ) 1633 n = bsesc(); 1634 else if( n == '\'' ) 1635 break; 1636 for (i = 0; i < size; ++i) 1637 val[i] = n >> (i * 8); 1638 if (!brev) 1639 byterev(val, size); 1640 mwrite(adrs, val, size); 1641 adrs += size; 1642 } 1643 adrs -= size; 1644 inc = size; 1645 break; 1646 case ',': 1647 adrs += size; 1648 break; 1649 case '.': 1650 mnoread = 0; 1651 break; 1652 case ';': 1653 break; 1654 case 'x': 1655 case EOF: 1656 scannl(); 1657 return; 1658 case 'b': 1659 case 'v': 1660 size = 1; 1661 break; 1662 case 'w': 1663 size = 2; 1664 break; 1665 case 'l': 1666 size = 4; 1667 break; 1668 case 'u': 1669 size = 8; 1670 break; 1671 case '^': 1672 adrs -= size; 1673 break; 1674 break; 1675 case '/': 1676 if (nslash > 0) 1677 adrs -= 1 << nslash; 1678 else 1679 nslash = 0; 1680 nslash += 4; 1681 adrs += 1 << nslash; 1682 break; 1683 case '\\': 1684 if (nslash < 0) 1685 adrs += 1 << -nslash; 1686 else 1687 nslash = 0; 1688 nslash -= 4; 1689 adrs -= 1 << -nslash; 1690 break; 1691 case 'm': 1692 scanhex((void *)&adrs); 1693 break; 1694 case 'n': 1695 mnoread = 1; 1696 break; 1697 case 'r': 1698 brev = !brev; 1699 break; 1700 case '<': 1701 n = size; 1702 scanhex(&n); 1703 adrs -= n; 1704 break; 1705 case '>': 1706 n = size; 1707 scanhex(&n); 1708 adrs += n; 1709 break; 1710 case '?': 1711 printf(memex_subcmd_help_string); 1712 break; 1713 } 1714 } 1715 adrs += inc; 1716 } 1717} 1718 1719int 1720bsesc() 1721{ 1722 int c; 1723 1724 c = inchar(); 1725 switch( c ){ 1726 case 'n': c = '\n'; break; 1727 case 'r': c = '\r'; break; 1728 case 'b': c = '\b'; break; 1729 case 't': c = '\t'; break; 1730 } 1731 return c; 1732} 1733 1734#define isxdigit(c) (('0' <= (c) && (c) <= '9') \ 1735 || ('a' <= (c) && (c) <= 'f') \ 1736 || ('A' <= (c) && (c) <= 'F')) 1737void 1738dump() 1739{ 1740 int c; 1741 1742 c = inchar(); 1743 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') 1744 termch = c; 1745 scanhex((void *)&adrs); 1746 if( termch != '\n') 1747 termch = 0; 1748 if( c == 'i' ){ 1749 scanhex(&nidump); 1750 if( nidump == 0 ) 1751 nidump = 16; 1752 adrs += ppc_inst_dump(adrs, nidump); 1753 last_cmd = "di\n"; 1754 } else { 1755 scanhex(&ndump); 1756 if( ndump == 0 ) 1757 ndump = 64; 1758 prdump(adrs, ndump); 1759 adrs += ndump; 1760 last_cmd = "d\n"; 1761 } 1762} 1763 1764void 1765prdump(unsigned long adrs, long ndump) 1766{ 1767 long n, m, c, r, nr; 1768 unsigned char temp[16]; 1769 1770 for( n = ndump; n > 0; ){ 1771 printf("%.16lx", adrs); 1772 putchar(' '); 1773 r = n < 16? n: 16; 1774 nr = mread(adrs, temp, r); 1775 adrs += nr; 1776 for( m = 0; m < r; ++m ){ 1777 if ((m & 7) == 0 && m > 0) 1778 putchar(' '); 1779 if( m < nr ) 1780 printf("%.2x", temp[m]); 1781 else 1782 printf("%s", fault_chars[fault_type]); 1783 } 1784 for(; m < 16; ++m ) 1785 printf(" "); 1786 printf(" |"); 1787 for( m = 0; m < r; ++m ){ 1788 if( m < nr ){ 1789 c = temp[m]; 1790 putchar(' ' <= c && c <= '~'? c: '.'); 1791 } else 1792 putchar(' '); 1793 } 1794 n -= r; 1795 for(; m < 16; ++m ) 1796 putchar(' '); 1797 printf("|\n"); 1798 if( nr < r ) 1799 break; 1800 } 1801} 1802 1803int 1804ppc_inst_dump(unsigned long adr, long count) 1805{ 1806 int nr, dotted; 1807 unsigned long first_adr; 1808 unsigned long inst, last_inst; 1809 unsigned char val[4]; 1810 1811 dotted = 0; 1812 for (first_adr = adr; count > 0; --count, adr += 4){ 1813 nr = mread(adr, val, 4); 1814 if( nr == 0 ){ 1815 const char *x = fault_chars[fault_type]; 1816 printf("%.16lx %s%s%s%s\n", adr, x, x, x, x); 1817 break; 1818 } 1819 inst = GETWORD(val); 1820 if (adr > first_adr && inst == last_inst) { 1821 if (!dotted) { 1822 printf(" ...\n"); 1823 dotted = 1; 1824 } 1825 continue; 1826 } 1827 dotted = 0; 1828 last_inst = inst; 1829 printf("%.16lx ", adr); 1830 printf("%.8x\t", inst); 1831 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */ 1832 printf("\n"); 1833 } 1834 return adr - first_adr; 1835} 1836 1837void 1838print_address(unsigned long addr) 1839{ 1840 printf("0x%lx", addr); 1841} 1842 1843/* 1844 * Memory operations - move, set, print differences 1845 */ 1846static unsigned long mdest; /* destination address */ 1847static unsigned long msrc; /* source address */ 1848static unsigned long mval; /* byte value to set memory to */ 1849static unsigned long mcount; /* # bytes to affect */ 1850static unsigned long mdiffs; /* max # differences to print */ 1851 1852void 1853memops(int cmd) 1854{ 1855 scanhex((void *)&mdest); 1856 if( termch != '\n' ) 1857 termch = 0; 1858 scanhex((void *)(cmd == 's'? &mval: &msrc)); 1859 if( termch != '\n' ) 1860 termch = 0; 1861 scanhex((void *)&mcount); 1862 switch( cmd ){ 1863 case 'm': 1864 memmove((void *)mdest, (void *)msrc, mcount); 1865 break; 1866 case 's': 1867 memset((void *)mdest, mval, mcount); 1868 break; 1869 case 'd': 1870 if( termch != '\n' ) 1871 termch = 0; 1872 scanhex((void *)&mdiffs); 1873 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs); 1874 break; 1875 } 1876} 1877 1878void 1879memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr) 1880{ 1881 unsigned n, prt; 1882 1883 prt = 0; 1884 for( n = nb; n > 0; --n ) 1885 if( *p1++ != *p2++ ) 1886 if( ++prt <= maxpr ) 1887 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1, 1888 p1[-1], p2 - 1, p2[-1]); 1889 if( prt > maxpr ) 1890 printf("Total of %d differences\n", prt); 1891} 1892 1893static unsigned mend; 1894static unsigned mask; 1895 1896void 1897memlocate() 1898{ 1899 unsigned a, n; 1900 unsigned char val[4]; 1901 1902 last_cmd = "ml"; 1903 scanhex((void *)&mdest); 1904 if (termch != '\n') { 1905 termch = 0; 1906 scanhex((void *)&mend); 1907 if (termch != '\n') { 1908 termch = 0; 1909 scanhex((void *)&mval); 1910 mask = ~0; 1911 if (termch != '\n') termch = 0; 1912 scanhex((void *)&mask); 1913 } 1914 } 1915 n = 0; 1916 for (a = mdest; a < mend; a += 4) { 1917 if (mread(a, val, 4) == 4 1918 && ((GETWORD(val) ^ mval) & mask) == 0) { 1919 printf("%.16x: %.16x\n", a, GETWORD(val)); 1920 if (++n >= 10) 1921 break; 1922 } 1923 } 1924} 1925 1926static unsigned long mskip = 0x1000; 1927static unsigned long mlim = 0xffffffff; 1928 1929void 1930memzcan() 1931{ 1932 unsigned char v; 1933 unsigned a; 1934 int ok, ook; 1935 1936 scanhex(&mdest); 1937 if (termch != '\n') termch = 0; 1938 scanhex(&mskip); 1939 if (termch != '\n') termch = 0; 1940 scanhex(&mlim); 1941 ook = 0; 1942 for (a = mdest; a < mlim; a += mskip) { 1943 ok = mread(a, &v, 1); 1944 if (ok && !ook) { 1945 printf("%.8x .. ", a); 1946 fflush(stdout); 1947 } else if (!ok && ook) 1948 printf("%.8x\n", a - mskip); 1949 ook = ok; 1950 if (a + mskip < a) 1951 break; 1952 } 1953 if (ook) 1954 printf("%.8x\n", a - mskip); 1955} 1956 1957/* Input scanning routines */ 1958int 1959skipbl() 1960{ 1961 int c; 1962 1963 if( termch != 0 ){ 1964 c = termch; 1965 termch = 0; 1966 } else 1967 c = inchar(); 1968 while( c == ' ' || c == '\t' ) 1969 c = inchar(); 1970 return c; 1971} 1972 1973int 1974scanhex(vp) 1975unsigned long *vp; 1976{ 1977 int c, d; 1978 unsigned long v; 1979 1980 c = skipbl(); 1981 d = hexdigit(c); 1982 if( d == EOF ){ 1983 termch = c; 1984 return 0; 1985 } 1986 v = 0; 1987 do { 1988 v = (v << 4) + d; 1989 c = inchar(); 1990 d = hexdigit(c); 1991 } while( d != EOF ); 1992 termch = c; 1993 *vp = v; 1994 return 1; 1995} 1996 1997void 1998scannl() 1999{ 2000 int c; 2001 2002 c = termch; 2003 termch = 0; 2004 while( c != '\n' ) 2005 c = inchar(); 2006} 2007 2008int 2009hexdigit(int c) 2010{ 2011 if( '0' <= c && c <= '9' ) 2012 return c - '0'; 2013 if( 'A' <= c && c <= 'F' ) 2014 return c - ('A' - 10); 2015 if( 'a' <= c && c <= 'f' ) 2016 return c - ('a' - 10); 2017 return EOF; 2018} 2019 2020void 2021getstring(char *s, int size) 2022{ 2023 int c; 2024 2025 c = skipbl(); 2026 do { 2027 if( size > 1 ){ 2028 *s++ = c; 2029 --size; 2030 } 2031 c = inchar(); 2032 } while( c != ' ' && c != '\t' && c != '\n' ); 2033 termch = c; 2034 *s = 0; 2035} 2036 2037static char line[256]; 2038static char *lineptr; 2039 2040void 2041flush_input() 2042{ 2043 lineptr = NULL; 2044} 2045 2046int 2047inchar() 2048{ 2049 if (lineptr == NULL || *lineptr == 0) { 2050 if (fgets(line, sizeof(line), stdin) == NULL) { 2051 lineptr = NULL; 2052 return EOF; 2053 } 2054 lineptr = line; 2055 } 2056 return *lineptr++; 2057} 2058 2059void 2060take_input(str) 2061char *str; 2062{ 2063 lineptr = str; 2064} 2065 2066 2067/* Starting at codeaddr scan forward for a tbtable and fill in the 2068 given table. Return non-zero if successful at doing something. 2069 */ 2070static int 2071find_tb_table(unsigned long codeaddr, struct tbtable *tab) 2072{ 2073 unsigned long codeaddr_max; 2074 unsigned long tbtab_start; 2075 int nr; 2076 int instr; 2077 int num_parms; 2078 2079 if (tab == NULL) 2080 return 0; 2081 memset(tab, 0, sizeof(tab)); 2082 2083 /* Scan instructions starting at codeaddr for 128k max */ 2084 for (codeaddr_max = codeaddr + 128*1024*4; 2085 codeaddr < codeaddr_max; 2086 codeaddr += 4) { 2087 nr = mread(codeaddr, &instr, 4); 2088 if (nr != 4) 2089 return 0; /* Bad read. Give up promptly. */ 2090 if (instr == 0) { 2091 /* table should follow. */ 2092 int version; 2093 unsigned long flags; 2094 tbtab_start = codeaddr; /* save it to compute func start addr */ 2095 codeaddr += 4; 2096 nr = mread(codeaddr, &flags, 8); 2097 if (nr != 8) 2098 return 0; /* Bad read or no tb table. */ 2099 tab->flags = flags; 2100 version = (flags >> 56) & 0xff; 2101 if (version != 0) 2102 continue; /* No tb table here. */ 2103 /* Now, like the version, some of the flags are values 2104 that are more conveniently extracted... */ 2105 tab->fp_saved = (flags >> 24) & 0x3f; 2106 tab->gpr_saved = (flags >> 16) & 0x3f; 2107 tab->fixedparms = (flags >> 8) & 0xff; 2108 tab->floatparms = (flags >> 1) & 0x7f; 2109 codeaddr += 8; 2110 num_parms = tab->fixedparms + tab->floatparms; 2111 if (num_parms) { 2112 unsigned int parminfo; 2113 int parm; 2114 if (num_parms > 32) 2115 return 1; /* incomplete */ 2116 nr = mread(codeaddr, &parminfo, 4); 2117 if (nr != 4) 2118 return 1; /* incomplete */ 2119 /* decode parminfo...32 bits. 2120 A zero means fixed. A one means float and the 2121 following bit determines single (0) or double (1). 2122 */ 2123 for (parm = 0; parm < num_parms; parm++) { 2124 if (parminfo & 0x80000000) { 2125 parminfo <<= 1; 2126 if (parminfo & 0x80000000) 2127 tab->parminfo[parm] = TBTAB_PARMDFLOAT; 2128 else 2129 tab->parminfo[parm] = TBTAB_PARMSFLOAT; 2130 } else { 2131 tab->parminfo[parm] = TBTAB_PARMFIXED; 2132 } 2133 parminfo <<= 1; 2134 } 2135 codeaddr += 4; 2136 } 2137 if (flags & TBTAB_FLAGSHASTBOFF) { 2138 nr = mread(codeaddr, &tab->tb_offset, 4); 2139 if (nr != 4) 2140 return 1; /* incomplete */ 2141 if (tab->tb_offset > 0) { 2142 tab->funcstart = tbtab_start - tab->tb_offset; 2143 } 2144 codeaddr += 4; 2145 } 2146 /* hand_mask appears to be always be omitted. */ 2147 if (flags & TBTAB_FLAGSHASCTL) { 2148 /* Assume this will never happen for C or asm */ 2149 return 1; /* incomplete */ 2150 } 2151 if (flags & TBTAB_FLAGSNAMEPRESENT) { 2152 short namlen; 2153 nr = mread(codeaddr, &namlen, 2); 2154 if (nr != 2) 2155 return 1; /* incomplete */ 2156 if (namlen >= sizeof(tab->name)) 2157 namlen = sizeof(tab->name)-1; 2158 codeaddr += 2; 2159 nr = mread(codeaddr, tab->name, namlen); 2160 tab->name[namlen] = '\0'; 2161 codeaddr += namlen; 2162 } 2163 return 1; 2164 } 2165 } 2166 return 0; /* hit max...sorry. */ 2167} 2168 2169void 2170mem_translate() 2171{ 2172 int c; 2173 unsigned long ea, va, vsid, vpn, page, hpteg_slot_primary, hpteg_slot_secondary, primary_hash, i, *steg, esid, stabl; 2174 HPTE * hpte; 2175 struct mm_struct * mm; 2176 pte_t *ptep = NULL; 2177 void * pgdir; 2178 2179 c = inchar(); 2180 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') 2181 termch = c; 2182 scanhex((void *)&ea); 2183 2184 if ((ea >= KRANGE_START) && (ea <= (KRANGE_START + (1UL<<60)))) { 2185 ptep = 0; 2186 vsid = get_kernel_vsid(ea); 2187 va = ( vsid << 28 ) | ( ea & 0x0fffffff ); 2188 } else { 2189 // if in vmalloc range, use the vmalloc page directory 2190 if ( ( ea >= VMALLOC_START ) && ( ea <= VMALLOC_END ) ) { 2191 mm = &init_mm; 2192 vsid = get_kernel_vsid( ea ); 2193 } 2194 // if in ioremap range, use the ioremap page directory 2195 else if ( ( ea >= IMALLOC_START ) && ( ea <= IMALLOC_END ) ) { 2196 mm = &ioremap_mm; 2197 vsid = get_kernel_vsid( ea ); 2198 } 2199 // if in user range, use the current task's page directory 2200 else if ( ( ea >= USER_START ) && ( ea <= USER_END ) ) { 2201 mm = current->mm; 2202 vsid = get_vsid(mm->context, ea ); 2203 } 2204 pgdir = mm->pgd; 2205 va = ( vsid << 28 ) | ( ea & 0x0fffffff ); 2206 ptep = find_linux_pte( pgdir, ea ); 2207 } 2208 2209 vpn = ((vsid << 28) | (((ea) & 0xFFFF000))) >> 12; 2210 page = vpn & 0xffff; 2211 esid = (ea >> 28) & 0xFFFFFFFFF; 2212 2213 // Search the primary group for an available slot 2214 primary_hash = ( vsid & 0x7fffffffff ) ^ page; 2215 hpteg_slot_primary = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP; 2216 hpteg_slot_secondary = ( ~primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP; 2217 2218 printf("ea : %.16lx\n", ea); 2219 printf("esid : %.16lx\n", esid); 2220 printf("vsid : %.16lx\n", vsid); 2221 2222 printf("\nSoftware Page Table\n-------------------\n"); 2223 printf("ptep : %.16lx\n", ((unsigned long *)ptep)); 2224 if(ptep) { 2225 printf("*ptep : %.16lx\n", *((unsigned long *)ptep)); 2226 } 2227 2228 hpte = htab_data.htab + hpteg_slot_primary; 2229 printf("\nHardware Page Table\n-------------------\n"); 2230 printf("htab base : %.16lx\n", htab_data.htab); 2231 printf("slot primary : %.16lx\n", hpteg_slot_primary); 2232 printf("slot secondary : %.16lx\n", hpteg_slot_secondary); 2233 printf("\nPrimary Group\n"); 2234 for (i=0; i<8; ++i) { 2235 if ( hpte->dw0.dw0.v != 0 ) { 2236 printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1); 2237 printf(" vsid: %.13lx api: %.2lx hash: %.1lx\n", 2238 (hpte->dw0.dw0.avpn)>>5, 2239 (hpte->dw0.dw0.avpn) & 0x1f, 2240 (hpte->dw0.dw0.h)); 2241 printf(" rpn: %.13lx \n", (hpte->dw1.dw1.rpn)); 2242 printf(" pp: %.1lx \n", 2243 ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp)); 2244 printf(" wimgn: %.2lx reference: %.1lx change: %.1lx\n", 2245 ((hpte->dw1.dw1.w)<<4)| 2246 ((hpte->dw1.dw1.i)<<3)| 2247 ((hpte->dw1.dw1.m)<<2)| 2248 ((hpte->dw1.dw1.g)<<1)| 2249 ((hpte->dw1.dw1.n)<<0), 2250 hpte->dw1.dw1.r, hpte->dw1.dw1.c); 2251 } 2252 hpte++; 2253 } 2254 2255 printf("\nSecondary Group\n"); 2256 // Search the secondary group 2257 hpte = htab_data.htab + hpteg_slot_secondary; 2258 for (i=0; i<8; ++i) { 2259 if(hpte->dw0.dw0.v) { 2260 printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1); 2261 printf(" vsid: %.13lx api: %.2lx hash: %.1lx\n", 2262 (hpte->dw0.dw0.avpn)>>5, 2263 (hpte->dw0.dw0.avpn) & 0x1f, 2264 (hpte->dw0.dw0.h)); 2265 printf(" rpn: %.13lx \n", (hpte->dw1.dw1.rpn)); 2266 printf(" pp: %.1lx \n", 2267 ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp)); 2268 printf(" wimgn: %.2lx reference: %.1lx change: %.1lx\n", 2269 ((hpte->dw1.dw1.w)<<4)| 2270 ((hpte->dw1.dw1.i)<<3)| 2271 ((hpte->dw1.dw1.m)<<2)| 2272 ((hpte->dw1.dw1.g)<<1)| 2273 ((hpte->dw1.dw1.n)<<0), 2274 hpte->dw1.dw1.r, hpte->dw1.dw1.c); 2275 } 2276 hpte++; 2277 } 2278 2279 printf("\nHardware Segment Table\n-----------------------\n"); 2280 stabl = (unsigned long)(KERNELBASE+(_ASR&0xFFFFFFFFFFFFFFFE)); 2281 steg = (unsigned long *)((stabl) | ((esid & 0x1f) << 7)); 2282 2283 printf("stab base : %.16lx\n", stabl); 2284 printf("slot : %.16lx\n", steg); 2285 2286 for (i=0; i<8; ++i) { 2287 printf("%d: (ste) %.16lx %.16lx\n", i, 2288 *((unsigned long *)(steg+i*2)),*((unsigned long *)(steg+i*2+1)) ); 2289 } 2290} 2291 2292void mem_check() 2293{ 2294 unsigned long htab_size_bytes; 2295 unsigned long htab_end; 2296 unsigned long last_rpn; 2297 HPTE *hpte1, *hpte2; 2298 2299 htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG 2300 htab_end = (unsigned long)htab_data.htab + htab_size_bytes; 2301 // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; 2302 last_rpn = 0xfffff; 2303 2304 printf("\nHardware Page Table Check\n-------------------\n"); 2305 printf("htab base : %.16lx\n", htab_data.htab); 2306 printf("htab size : %.16lx\n", htab_size_bytes); 2307 2308 for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { 2309 if ( hpte1->dw0.dw0.v != 0 ) { 2310 if ( hpte1->dw1.dw1.rpn <= last_rpn ) { 2311 for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) { 2312 if ( hpte2->dw0.dw0.v != 0 ) { 2313 if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) { 2314 printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); 2315 printf(" hpte1: %16.16lx *hpte1: %16.16lx %16.16lx\n", 2316 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); 2317 printf(" hpte2: %16.16lx *hpte2: %16.16lx %16.16lx\n", 2318 hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1); 2319 } 2320 } 2321 } 2322 } else { 2323 printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); 2324 printf(" hpte: %16.16lx *hpte: %16.16lx %16.16lx\n", 2325 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); 2326 } 2327 } 2328 } 2329 printf("\nDone -------------------\n"); 2330} 2331 2332void mem_find_real() 2333{ 2334 unsigned long htab_size_bytes; 2335 unsigned long htab_end; 2336 unsigned long last_rpn; 2337 HPTE *hpte1; 2338 unsigned long pa, rpn; 2339 int c; 2340 2341 c = inchar(); 2342 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') 2343 termch = c; 2344 scanhex((void *)&pa); 2345 rpn = pa >> 12; 2346 2347 htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG 2348 htab_end = (unsigned long)htab_data.htab + htab_size_bytes; 2349 // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; 2350 last_rpn = 0xfffff; 2351 2352 printf("\nMem Find RPN\n-------------------\n"); 2353 printf("htab base : %.16lx\n", htab_data.htab); 2354 printf("htab size : %.16lx\n", htab_size_bytes); 2355 2356 for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { 2357 if ( hpte1->dw0.dw0.v != 0 ) { 2358 if ( hpte1->dw1.dw1.rpn == rpn ) { 2359 printf(" Found rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); 2360 printf(" hpte: %16.16lx *hpte1: %16.16lx %16.16lx\n", 2361 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); 2362 } 2363 } 2364 } 2365 printf("\nDone -------------------\n"); 2366} 2367 2368void mem_find_vsid() 2369{ 2370 unsigned long htab_size_bytes; 2371 unsigned long htab_end; 2372 HPTE *hpte1; 2373 unsigned long vsid; 2374 int c; 2375 2376 c = inchar(); 2377 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') 2378 termch = c; 2379 scanhex((void *)&vsid); 2380 2381 htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG 2382 htab_end = (unsigned long)htab_data.htab + htab_size_bytes; 2383 2384 printf("\nMem Find VSID\n-------------------\n"); 2385 printf("htab base : %.16lx\n", htab_data.htab); 2386 printf("htab size : %.16lx\n", htab_size_bytes); 2387 2388 for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { 2389 if ( hpte1->dw0.dw0.v != 0 ) { 2390 if ( ((hpte1->dw0.dw0.avpn)>>5) == vsid ) { 2391 printf(" Found vsid: %.16lx \n", ((hpte1->dw0.dw0.avpn) >> 5)); 2392 printf(" hpte: %16.16lx *hpte1: %16.16lx %16.16lx\n", 2393 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); 2394 } 2395 } 2396 } 2397 printf("\nDone -------------------\n"); 2398} 2399 2400void mem_map_check_slab() 2401{ 2402 int i, slab_count; 2403 2404 i = max_mapnr; 2405 slab_count = 0; 2406 2407 while (i-- > 0) { 2408 if (PageSlab(mem_map+i)){ 2409 printf(" slab entry - mem_map entry =%p \n", mem_map+i); 2410 slab_count ++; 2411 } 2412 } 2413 2414 printf(" count of pages for slab = %d \n", slab_count); 2415} 2416 2417void mem_map_lock_pages() 2418{ 2419 int i, lock_count; 2420 2421 i = max_mapnr; 2422 lock_count = 0; 2423 2424 while (i-- > 0) { 2425 if (PageLocked(mem_map+i)){ 2426 printf(" locked entry - mem_map entry =%p \n", mem_map+i); 2427 lock_count ++; 2428 } 2429 } 2430 2431 printf(" count of locked pages = %d \n", lock_count); 2432} 2433 2434void mem_check_dup_rpn () 2435{ 2436 unsigned long htab_size_bytes; 2437 unsigned long htab_end; 2438 unsigned long last_rpn; 2439 HPTE *hpte1, *hpte2; 2440 int dup_count; 2441 struct task_struct *p; 2442 unsigned long kernel_vsid_c0,kernel_vsid_c1,kernel_vsid_c2,kernel_vsid_c3; 2443 unsigned long kernel_vsid_c4,kernel_vsid_c5,kernel_vsid_d,kernel_vsid_e; 2444 unsigned long kernel_vsid_f; 2445 unsigned long vsid0,vsid1,vsidB,vsid2; 2446 2447 htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG 2448 htab_end = (unsigned long)htab_data.htab + htab_size_bytes; 2449 // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; 2450 last_rpn = 0xfffff; 2451 2452 printf("\nHardware Page Table Check\n-------------------\n"); 2453 printf("htab base : %.16lx\n", htab_data.htab); 2454 printf("htab size : %.16lx\n", htab_size_bytes); 2455 2456 2457 for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { 2458 if ( hpte1->dw0.dw0.v != 0 ) { 2459 if ( hpte1->dw1.dw1.rpn <= last_rpn ) { 2460 dup_count = 0; 2461 for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) { 2462 if ( hpte2->dw0.dw0.v != 0 ) { 2463 if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) { 2464 dup_count++; 2465 } 2466 } 2467 } 2468 if(dup_count > 5) { 2469 printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); 2470 printf(" mem map array entry %p count = %d \n", 2471 (mem_map+(hpte1->dw1.dw1.rpn)), (mem_map+(hpte1->dw1.dw1.rpn))->count); 2472 for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) { 2473 if ( hpte2->dw0.dw0.v != 0 ) { 2474 if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) { 2475 printf(" hpte2: %16.16lx *hpte2: %16.16lx %16.16lx\n", 2476 hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1); 2477 } 2478 } 2479 } 2480 } 2481 } else { 2482 printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); 2483 printf(" hpte: %16.16lx *hpte: %16.16lx %16.16lx\n", 2484 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); 2485 } 2486 } 2487 if (xmon_interrupted()) 2488 return; 2489 } 2490 2491 2492 2493 // print the kernel vsids 2494 kernel_vsid_c0 = get_kernel_vsid(0xC000000000000000); 2495 kernel_vsid_c1 = get_kernel_vsid(0xC000000010000000); 2496 kernel_vsid_c2 = get_kernel_vsid(0xC000000020000000); 2497 kernel_vsid_c3 = get_kernel_vsid(0xC000000030000000); 2498 kernel_vsid_c4 = get_kernel_vsid(0xC000000040000000); 2499 kernel_vsid_c5 = get_kernel_vsid(0xC000000050000000); 2500 kernel_vsid_d = get_kernel_vsid(0xD000000000000000); 2501 kernel_vsid_e = get_kernel_vsid(0xE000000000000000); 2502 kernel_vsid_f = get_kernel_vsid(0xF000000000000000); 2503 2504 printf(" kernel vsid - seg c0 = %lx\n", kernel_vsid_c0 ); 2505 printf(" kernel vsid - seg c1 = %lx\n", kernel_vsid_c1 ); 2506 printf(" kernel vsid - seg c2 = %lx\n", kernel_vsid_c2 ); 2507 printf(" kernel vsid - seg c3 = %lx\n", kernel_vsid_c3 ); 2508 printf(" kernel vsid - seg c4 = %lx\n", kernel_vsid_c4 ); 2509 printf(" kernel vsid - seg c5 = %lx\n", kernel_vsid_c5 ); 2510 printf(" kernel vsid - seg d = %lx\n", kernel_vsid_d ); 2511 printf(" kernel vsid - seg e = %lx\n", kernel_vsid_e ); 2512 printf(" kernel vsid - seg f = %lx\n", kernel_vsid_f ); 2513 2514 2515 // print a list of valid vsids for the tasks 2516 read_lock(&tasklist_lock); 2517 for_each_task(p) 2518 if(p->mm) { 2519 struct mm_struct *mm = p->mm; 2520 printf(" task = %p mm = %lx pgd %lx\n", 2521 p, mm, mm->pgd); 2522 vsid0 = get_vsid( mm->context, 0 ); 2523 vsid1 = get_vsid( mm->context, 0x10000000 ); 2524 vsid2 = get_vsid( mm->context, 0x20000000 ); 2525 vsidB = get_vsid( mm->context, 0xB0000000 ); 2526 printf(" context = %lx vsid seg 0 = %lx\n", mm->context, vsid0 ); 2527 printf(" vsid seg 1 = %lx\n", vsid1 ); 2528 printf(" vsid seg 2 = %lx\n", vsid2 ); 2529 printf(" vsid seg 2 = %lx\n", vsidB ); 2530 2531 printf("\n"); 2532 }; 2533 read_unlock(&tasklist_lock); 2534 2535 printf("\nDone -------------------\n"); 2536} 2537 2538 2539 2540void mem_check_pagetable_vsids () 2541{ 2542 unsigned long htab_size_bytes; 2543 unsigned long htab_end; 2544 unsigned long last_rpn; 2545 struct task_struct *p; 2546 unsigned long valid_table_count,invalid_table_count,bogus_rpn_count; 2547 int found; 2548 unsigned long user_address_table_count,kernel_page_table_count; 2549 unsigned long pt_vsid; 2550 HPTE *hpte1; 2551 2552 2553 htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG 2554 htab_end = (unsigned long)htab_data.htab + htab_size_bytes; 2555 // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; 2556 last_rpn = 0xfffff; 2557 2558 printf("\nHardware Page Table Check\n-------------------\n"); 2559 printf("htab base : %.16lx\n", htab_data.htab); 2560 printf("htab size : %.16lx\n", htab_size_bytes); 2561 2562 valid_table_count = 0; 2563 invalid_table_count = 0; 2564 bogus_rpn_count = 0; 2565 user_address_table_count = 0; 2566 kernel_page_table_count = 0; 2567 for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { 2568 if ( hpte1->dw0.dw0.v != 0 ) { 2569 valid_table_count++; 2570 if ( hpte1->dw1.dw1.rpn <= last_rpn ) { 2571 pt_vsid = (hpte1->dw0.dw0.avpn) >> 5; 2572 if ((pt_vsid == get_kernel_vsid(0xC000000000000000)) | 2573 (pt_vsid == get_kernel_vsid(0xC000000010000000)) | 2574 (pt_vsid == get_kernel_vsid(0xC000000020000000)) | 2575 (pt_vsid == get_kernel_vsid(0xC000000030000000)) | 2576 (pt_vsid == get_kernel_vsid(0xC000000040000000)) | 2577 (pt_vsid == get_kernel_vsid(0xC000000050000000)) | 2578 (pt_vsid == get_kernel_vsid(0xD000000000000000)) | 2579 (pt_vsid == get_kernel_vsid(0xE000000000000000)) | 2580 (pt_vsid == get_kernel_vsid(0xF000000000000000)) ) { 2581 kernel_page_table_count ++; 2582 } else { 2583 read_lock(&tasklist_lock); 2584 found = 0; 2585 for_each_task(p) { 2586 if(p->mm && (found == 0)) { 2587 struct mm_struct *mm = p->mm; 2588 2589 if ((pt_vsid == get_vsid( mm->context, 0 )) | 2590 (pt_vsid == get_vsid( mm->context, 0x10000000 )) | 2591 (pt_vsid == get_vsid( mm->context, 0x20000000 )) | 2592 (pt_vsid == get_vsid( mm->context, 0x30000000 )) | 2593 (pt_vsid == get_vsid( mm->context, 0x40000000 )) | 2594 (pt_vsid == get_vsid( mm->context, 0x50000000 )) | 2595 (pt_vsid == get_vsid( mm->context, 0x60000000 )) | 2596 (pt_vsid == get_vsid( mm->context, 0x70000000 )) | 2597 (pt_vsid == get_vsid( mm->context, 0x80000000 )) | 2598 (pt_vsid == get_vsid( mm->context, 0x90000000 )) | 2599 (pt_vsid == get_vsid( mm->context, 0xA0000000 )) | 2600 (pt_vsid == get_vsid( mm->context, 0xB0000000 ))) { 2601 user_address_table_count ++; 2602 found = 1; 2603 } 2604 } 2605 } 2606 read_unlock(&tasklist_lock); 2607 if (found == 0) 2608 { 2609 printf(" vsid not found vsid = %lx, hpte = %p \n", 2610 pt_vsid,hpte1); 2611 printf(" rpn in entry = %lx \n", hpte1->dw1.dw1.rpn); 2612 printf(" mem map address = %lx \n", mem_map + (hpte1->dw1.dw1.rpn)); 2613 2614 } else // found 2615 { 2616 } 2617 2618 } // good rpn 2619 2620 } else { 2621 bogus_rpn_count ++; 2622 } 2623 } else { 2624 invalid_table_count++; 2625 } 2626 } 2627 2628 2629 printf(" page table valid counts - valid entries = %lx invalid entries = %lx \n", 2630 valid_table_count, invalid_table_count); 2631 2632 printf(" bogus rpn entries ( probably io) = %lx \n", bogus_rpn_count); 2633 2634 2635 2636 printf(" page table counts - kernel entries = %lx user entries = %lx \n", 2637 kernel_page_table_count, user_address_table_count); 2638 2639 printf("\nDone -------------------\n"); 2640 2641} 2642 2643static void debug_trace(void) { 2644 unsigned long val, cmd, on; 2645 2646 cmd = skipbl(); 2647 if (cmd == '\n') { 2648 /* show current state */ 2649 unsigned long i; 2650 printf("naca->debug_switch = 0x%lx\n", naca->debug_switch); 2651 for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) { 2652 on = PPCDBG_BITVAL(i) & naca->debug_switch; 2653 printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : ""); 2654 if (((i+1) % 3) == 0) 2655 printf("\n"); 2656 } 2657 printf("\n"); 2658 return; 2659 } 2660 while (cmd != '\n') { 2661 on = 1; /* default if no sign given */ 2662 while (cmd == '+' || cmd == '-') { 2663 on = (cmd == '+'); 2664 cmd = inchar(); 2665 if (cmd == ' ' || cmd == '\n') { /* Turn on or off based on + or - */ 2666 naca->debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE; 2667 printf("Setting all values to %s...\n", on ? "on" : "off"); 2668 if (cmd == '\n') return; 2669 else cmd = skipbl(); 2670 } 2671 else 2672 termch = cmd; 2673 } 2674 termch = cmd; /* not +/- ... let scanhex see it */ 2675 scanhex((void *)&val); 2676 if (val >= 64) { 2677 printf("Value %x out of range:\n", val); 2678 return; 2679 } 2680 if (on) { 2681 naca->debug_switch |= PPCDBG_BITVAL(val); 2682 printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : ""); 2683 } else { 2684 naca->debug_switch &= ~PPCDBG_BITVAL(val); 2685 printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : ""); 2686 } 2687 cmd = skipbl(); 2688 } 2689} 2690