1/* 2 * Routines providing a simple monitor for use on the PowerMac. 3 * 4 * Copyright (C) 1996 Paul Mackerras. 5 */ 6#include <linux/errno.h> 7#include <linux/sched.h> 8#include <linux/smp.h> 9#include <linux/interrupt.h> 10#include <linux/bitops.h> 11#include <linux/kallsyms.h> 12#include <asm/ptrace.h> 13#include <asm/string.h> 14#include <asm/machdep.h> 15#include <asm/xmon.h> 16#include "nonstdio.h" 17#include "privinst.h" 18 19#define scanhex xmon_scanhex 20#define skipbl xmon_skipbl 21 22#ifdef CONFIG_SMP 23static unsigned long cpus_in_xmon = 0; 24static unsigned long got_xmon = 0; 25static volatile int take_xmon = -1; 26#endif /* CONFIG_SMP */ 27 28static unsigned adrs; 29static int size = 1; 30static unsigned ndump = 64; 31static unsigned nidump = 16; 32static unsigned ncsum = 4096; 33static int termch; 34 35static u_int bus_error_jmp[100]; 36#define setjmp xmon_setjmp 37#define longjmp xmon_longjmp 38 39/* Breakpoint stuff */ 40struct bpt { 41 unsigned address; 42 unsigned instr; 43 unsigned count; 44 unsigned char enabled; 45}; 46 47#define NBPTS 16 48static struct bpt bpts[NBPTS]; 49static struct bpt dabr; 50static struct bpt iabr; 51static unsigned bpinstr = 0x7fe00008; /* trap */ 52 53/* Prototypes */ 54extern void (*debugger_fault_handler)(struct pt_regs *); 55static int cmds(struct pt_regs *); 56static int mread(unsigned, void *, int); 57static int mwrite(unsigned, void *, int); 58static void handle_fault(struct pt_regs *); 59static void byterev(unsigned char *, int); 60static void memex(void); 61static int bsesc(void); 62static void dump(void); 63static void prdump(unsigned, int); 64#ifdef __MWERKS__ 65static void prndump(unsigned, int); 66static int nvreadb(unsigned); 67#endif 68static int ppc_inst_dump(unsigned, int); 69void print_address(unsigned); 70static int getsp(void); 71static void dump_hash_table(void); 72static void backtrace(struct pt_regs *); 73static void excprint(struct pt_regs *); 74static void prregs(struct pt_regs *); 75static void memops(int); 76static void memlocate(void); 77static void memzcan(void); 78static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned); 79int skipbl(void); 80int scanhex(unsigned *valp); 81static void scannl(void); 82static int hexdigit(int); 83void getstring(char *, int); 84static void flush_input(void); 85static int inchar(void); 86static void take_input(char *); 87/* static void openforth(void); */ 88static unsigned read_spr(int); 89static void write_spr(int, unsigned); 90static void super_regs(void); 91static void symbol_lookup(void); 92static void remove_bpts(void); 93static void insert_bpts(void); 94static struct bpt *at_breakpoint(unsigned pc); 95static void bpt_cmds(void); 96void cacheflush(void); 97#ifdef CONFIG_SMP 98static void cpu_cmd(void); 99#endif /* CONFIG_SMP */ 100static void csum(void); 101static void bootcmds(void); 102static void proccall(void); 103static void printtime(void); 104 105extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned); 106extern void printf(const char *fmt, ...); 107extern int putchar(int ch); 108extern int setjmp(u_int *); 109extern void longjmp(u_int *, int); 110 111extern void xmon_enter(void); 112extern void xmon_leave(void); 113 114static unsigned start_tb[NR_CPUS][2]; 115static unsigned stop_tb[NR_CPUS][2]; 116 117#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3]) 118 119#define isxdigit(c) (('0' <= (c) && (c) <= '9') \ 120 || ('a' <= (c) && (c) <= 'f') \ 121 || ('A' <= (c) && (c) <= 'F')) 122#define isalnum(c) (('0' <= (c) && (c) <= '9') \ 123 || ('a' <= (c) && (c) <= 'z') \ 124 || ('A' <= (c) && (c) <= 'Z')) 125#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0) 126 127static char *help_string = "\ 128Commands:\n\ 129 d dump bytes\n\ 130 di dump instructions\n\ 131 df dump float values\n\ 132 dd dump double values\n\ 133 e print exception information\n\ 134 h dump hash table\n\ 135 m examine/change memory\n\ 136 mm move a block of memory\n\ 137 ms set a block of memory\n\ 138 md compare two blocks of memory\n\ 139 r print registers\n\ 140 S print special registers\n\ 141 t print backtrace\n\ 142 la lookup address\n\ 143 ls lookup symbol\n\ 144 C checksum\n\ 145 p call function with arguments\n\ 146 T print time\n\ 147 x exit monitor\n\ 148 zr reboot\n\ 149 zh halt\n\ 150"; 151 152static int xmon_trace[NR_CPUS]; 153#define SSTEP 1 /* stepping because of 's' command */ 154#define BRSTEP 2 /* stepping over breakpoint */ 155 156#ifdef CONFIG_4xx 157#define MSR_SSTEP_ENABLE 0x200 158#else 159#define MSR_SSTEP_ENABLE 0x400 160#endif 161 162static struct pt_regs *xmon_regs[NR_CPUS]; 163 164extern inline void sync(void) 165{ 166 asm volatile("sync; isync"); 167} 168 169extern inline void __delay(unsigned int loops) 170{ 171 if (loops != 0) 172 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : : 173 "r" (loops) : "ctr"); 174} 175 176/* Print an address in numeric and symbolic form (if possible) */ 177static void xmon_print_symbol(unsigned long address, const char *mid, 178 const char *after) 179{ 180 char *modname; 181 const char *name = NULL; 182 unsigned long offset, size; 183 static char tmpstr[128]; 184 185 printf("%.8lx", address); 186 if (setjmp(bus_error_jmp) == 0) { 187 debugger_fault_handler = handle_fault; 188 sync(); 189 name = kallsyms_lookup(address, &size, &offset, &modname, 190 tmpstr); 191 sync(); 192 /* wait a little while to see if we get a machine check */ 193 __delay(200); 194 } 195 debugger_fault_handler = NULL; 196 197 if (name) { 198 printf("%s%s+%#lx/%#lx", mid, name, offset, size); 199 if (modname) 200 printf(" [%s]", modname); 201 } 202 printf("%s", after); 203} 204 205static void get_tb(unsigned *p) 206{ 207 unsigned hi, lo, hiagain; 208 209 if ((get_pvr() >> 16) == 1) 210 return; 211 212 do { 213 asm volatile("mftbu %0; mftb %1; mftbu %2" 214 : "=r" (hi), "=r" (lo), "=r" (hiagain)); 215 } while (hi != hiagain); 216 p[0] = hi; 217 p[1] = lo; 218} 219 220static inline void xmon_enable_sstep(struct pt_regs *regs) 221{ 222 regs->msr |= MSR_SSTEP_ENABLE; 223#ifdef CONFIG_4xx 224 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); 225#endif 226} 227 228int xmon(struct pt_regs *excp) 229{ 230 struct pt_regs regs; 231 int msr, cmd; 232 233 get_tb(stop_tb[smp_processor_id()]); 234 if (excp == NULL) { 235 asm volatile ("stw 0,0(%0)\n\ 236 lwz 0,0(1)\n\ 237 stw 0,4(%0)\n\ 238 stmw 2,8(%0)" : : "b" (®s)); 239 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1]; 240 regs.msr = get_msr(); 241 regs.ctr = get_ctr(); 242 regs.xer = get_xer(); 243 regs.ccr = get_cr(); 244 regs.trap = 0; 245 excp = ®s; 246 } 247 248 msr = get_msr(); 249 set_msr(msr & ~0x8000); /* disable interrupts */ 250 xmon_regs[smp_processor_id()] = excp; 251 xmon_enter(); 252 excprint(excp); 253#ifdef CONFIG_SMP 254 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) 255 for (;;) 256 ; 257 while (test_and_set_bit(0, &got_xmon)) { 258 if (take_xmon == smp_processor_id()) { 259 take_xmon = -1; 260 break; 261 } 262 } 263#endif /* CONFIG_SMP */ 264 remove_bpts(); 265 cmd = cmds(excp); 266 if (cmd == 's') { 267 xmon_trace[smp_processor_id()] = SSTEP; 268 xmon_enable_sstep(excp); 269 } else if (at_breakpoint(excp->nip)) { 270 xmon_trace[smp_processor_id()] = BRSTEP; 271 xmon_enable_sstep(excp); 272 } else { 273 xmon_trace[smp_processor_id()] = 0; 274 insert_bpts(); 275 } 276 xmon_leave(); 277 xmon_regs[smp_processor_id()] = NULL; 278#ifdef CONFIG_SMP 279 clear_bit(0, &got_xmon); 280 clear_bit(smp_processor_id(), &cpus_in_xmon); 281#endif /* CONFIG_SMP */ 282 set_msr(msr); /* restore interrupt enable */ 283 get_tb(start_tb[smp_processor_id()]); 284 285 return cmd != 'X'; 286} 287 288irqreturn_t 289xmon_irq(int irq, void *d, struct pt_regs *regs) 290{ 291 unsigned long flags; 292 local_irq_save(flags); 293 printf("Keyboard interrupt\n"); 294 xmon(regs); 295 local_irq_restore(flags); 296 return IRQ_HANDLED; 297} 298 299int 300xmon_bpt(struct pt_regs *regs) 301{ 302 struct bpt *bp; 303 304 bp = at_breakpoint(regs->nip); 305 if (!bp) 306 return 0; 307 if (bp->count) { 308 --bp->count; 309 remove_bpts(); 310 excprint(regs); 311 xmon_trace[smp_processor_id()] = BRSTEP; 312 xmon_enable_sstep(regs); 313 } else { 314 xmon(regs); 315 } 316 return 1; 317} 318 319int 320xmon_sstep(struct pt_regs *regs) 321{ 322 if (!xmon_trace[smp_processor_id()]) 323 return 0; 324 if (xmon_trace[smp_processor_id()] == BRSTEP) { 325 xmon_trace[smp_processor_id()] = 0; 326 insert_bpts(); 327 } else { 328 xmon(regs); 329 } 330 return 1; 331} 332 333int 334xmon_dabr_match(struct pt_regs *regs) 335{ 336 if (dabr.enabled && dabr.count) { 337 --dabr.count; 338 remove_bpts(); 339 excprint(regs); 340 xmon_trace[smp_processor_id()] = BRSTEP; 341 regs->msr |= 0x400; 342 } else { 343 dabr.instr = regs->nip; 344 xmon(regs); 345 } 346 return 1; 347} 348 349int 350xmon_iabr_match(struct pt_regs *regs) 351{ 352 if (iabr.enabled && iabr.count) { 353 --iabr.count; 354 remove_bpts(); 355 excprint(regs); 356 xmon_trace[smp_processor_id()] = BRSTEP; 357 regs->msr |= 0x400; 358 } else { 359 xmon(regs); 360 } 361 return 1; 362} 363 364static struct bpt * 365at_breakpoint(unsigned pc) 366{ 367 int i; 368 struct bpt *bp; 369 370 if (dabr.enabled && pc == dabr.instr) 371 return &dabr; 372 if (iabr.enabled && pc == iabr.address) 373 return &iabr; 374 bp = bpts; 375 for (i = 0; i < NBPTS; ++i, ++bp) 376 if (bp->enabled && pc == bp->address) 377 return bp; 378 return NULL; 379} 380 381static void 382insert_bpts(void) 383{ 384 int i; 385 struct bpt *bp; 386 387 bp = bpts; 388 for (i = 0; i < NBPTS; ++i, ++bp) { 389 if (!bp->enabled) 390 continue; 391 if (mread(bp->address, &bp->instr, 4) != 4 392 || mwrite(bp->address, &bpinstr, 4) != 4) { 393 printf("Couldn't insert breakpoint at %x, disabling\n", 394 bp->address); 395 bp->enabled = 0; 396 } 397 store_inst((void *) bp->address); 398 } 399#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx)) 400 if (dabr.enabled) 401 set_dabr(dabr.address); 402 if (iabr.enabled) 403 set_iabr(iabr.address); 404#endif 405} 406 407static void 408remove_bpts(void) 409{ 410 int i; 411 struct bpt *bp; 412 unsigned instr; 413 414#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx)) 415 set_dabr(0); 416 set_iabr(0); 417#endif 418 bp = bpts; 419 for (i = 0; i < NBPTS; ++i, ++bp) { 420 if (!bp->enabled) 421 continue; 422 if (mread(bp->address, &instr, 4) == 4 423 && instr == bpinstr 424 && mwrite(bp->address, &bp->instr, 4) != 4) 425 printf("Couldn't remove breakpoint at %x\n", 426 bp->address); 427 store_inst((void *) bp->address); 428 } 429} 430 431static char *last_cmd; 432 433/* Command interpreting routine */ 434static int 435cmds(struct pt_regs *excp) 436{ 437 int cmd; 438 439 last_cmd = NULL; 440 for(;;) { 441#ifdef CONFIG_SMP 442 printf("%d:", smp_processor_id()); 443#endif /* CONFIG_SMP */ 444 printf("mon> "); 445 fflush(stdout); 446 flush_input(); 447 termch = 0; 448 cmd = skipbl(); 449 if( cmd == '\n' ) { 450 if (last_cmd == NULL) 451 continue; 452 take_input(last_cmd); 453 last_cmd = NULL; 454 cmd = inchar(); 455 } 456 switch (cmd) { 457 case 'm': 458 cmd = inchar(); 459 switch (cmd) { 460 case 'm': 461 case 's': 462 case 'd': 463 memops(cmd); 464 break; 465 case 'l': 466 memlocate(); 467 break; 468 case 'z': 469 memzcan(); 470 break; 471 default: 472 termch = cmd; 473 memex(); 474 } 475 break; 476 case 'd': 477 dump(); 478 break; 479 case 'l': 480 symbol_lookup(); 481 break; 482 case 'r': 483 if (excp != NULL) 484 prregs(excp); /* print regs */ 485 break; 486 case 'e': 487 if (excp == NULL) 488 printf("No exception information\n"); 489 else 490 excprint(excp); 491 break; 492 case 'S': 493 super_regs(); 494 break; 495 case 't': 496 backtrace(excp); 497 break; 498 case 'f': 499 cacheflush(); 500 break; 501 case 'h': 502 dump_hash_table(); 503 break; 504 case 's': 505 case 'x': 506 case EOF: 507 return cmd; 508 case '?': 509 printf(help_string); 510 break; 511 default: 512 printf("Unrecognized command: "); 513 if( ' ' < cmd && cmd <= '~' ) 514 putchar(cmd); 515 else 516 printf("\\x%x", cmd); 517 printf(" (type ? for help)\n"); 518 break; 519 case 'b': 520 bpt_cmds(); 521 break; 522 case 'C': 523 csum(); 524 break; 525#ifdef CONFIG_SMP 526 case 'c': 527 cpu_cmd(); 528 break; 529#endif /* CONFIG_SMP */ 530 case 'z': 531 bootcmds(); 532 break; 533 case 'p': 534 proccall(); 535 break; 536 case 'T': 537 printtime(); 538 break; 539 } 540 } 541} 542 543extern unsigned tb_to_us; 544 545#define mulhwu(x,y) \ 546({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) 547 548static void printtime(void) 549{ 550 unsigned int delta; 551 552 delta = stop_tb[smp_processor_id()][1] 553 - start_tb[smp_processor_id()][1]; 554 delta = mulhwu(tb_to_us, delta); 555 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000); 556} 557 558static void bootcmds(void) 559{ 560 int cmd; 561 562 cmd = inchar(); 563 if (cmd == 'r') 564 ppc_md.restart(NULL); 565 else if (cmd == 'h') 566 ppc_md.halt(); 567 else if (cmd == 'p') 568 ppc_md.power_off(); 569} 570 571#ifdef CONFIG_SMP 572static void cpu_cmd(void) 573{ 574 unsigned cpu; 575 int timeout; 576 int cmd; 577 578 cmd = inchar(); 579 if (cmd == 'i') { 580 /* interrupt other cpu(s) */ 581 cpu = MSG_ALL_BUT_SELF; 582 if (scanhex(&cpu)) 583 smp_send_xmon_break(cpu); 584 return; 585 } 586 termch = cmd; 587 if (!scanhex(&cpu)) { 588 /* print cpus waiting or in xmon */ 589 printf("cpus stopped:"); 590 for (cpu = 0; cpu < NR_CPUS; ++cpu) { 591 if (test_bit(cpu, &cpus_in_xmon)) { 592 printf(" %d", cpu); 593 if (cpu == smp_processor_id()) 594 printf("*", cpu); 595 } 596 } 597 printf("\n"); 598 return; 599 } 600 /* try to switch to cpu specified */ 601 take_xmon = cpu; 602 timeout = 10000000; 603 while (take_xmon >= 0) { 604 if (--timeout == 0) { 605 /* yes there's a race here */ 606 take_xmon = -1; 607 printf("cpu %u didn't take control\n", cpu); 608 return; 609 } 610 } 611 /* now have to wait to be given control back */ 612 while (test_and_set_bit(0, &got_xmon)) { 613 if (take_xmon == smp_processor_id()) { 614 take_xmon = -1; 615 break; 616 } 617 } 618} 619#endif /* CONFIG_SMP */ 620 621 622static unsigned short fcstab[256] = { 623 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 624 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 625 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 626 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 627 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 628 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 629 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 630 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 631 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 632 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 633 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 634 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 635 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 636 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 637 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 638 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 639 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 640 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 641 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 642 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 643 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 644 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 645 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 646 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 647 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 648 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 649 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 650 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 651 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 652 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 653 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 654 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 655}; 656 657#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) 658 659static void 660csum(void) 661{ 662 unsigned int i; 663 unsigned short fcs; 664 unsigned char v; 665 666 if (!scanhex(&adrs)) 667 return; 668 if (!scanhex(&ncsum)) 669 return; 670 fcs = 0xffff; 671 for (i = 0; i < ncsum; ++i) { 672 if (mread(adrs+i, &v, 1) == 0) { 673 printf("csum stopped at %x\n", adrs+i); 674 break; 675 } 676 fcs = FCS(fcs, v); 677 } 678 printf("%x\n", fcs); 679} 680 681static void 682bpt_cmds(void) 683{ 684 int cmd; 685 unsigned a; 686 int mode, i; 687 struct bpt *bp; 688 689 cmd = inchar(); 690 switch (cmd) { 691#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx)) 692 case 'd': 693 mode = 7; 694 cmd = inchar(); 695 if (cmd == 'r') 696 mode = 5; 697 else if (cmd == 'w') 698 mode = 6; 699 else 700 termch = cmd; 701 cmd = inchar(); 702 if (cmd == 'p') 703 mode &= ~4; 704 else 705 termch = cmd; 706 dabr.address = 0; 707 dabr.count = 0; 708 dabr.enabled = scanhex(&dabr.address); 709 scanhex(&dabr.count); 710 if (dabr.enabled) 711 dabr.address = (dabr.address & ~7) | mode; 712 break; 713 case 'i': 714 cmd = inchar(); 715 if (cmd == 'p') 716 mode = 2; 717 else 718 mode = 3; 719 iabr.address = 0; 720 iabr.count = 0; 721 iabr.enabled = scanhex(&iabr.address); 722 if (iabr.enabled) 723 iabr.address |= mode; 724 scanhex(&iabr.count); 725 break; 726#endif 727 case 'c': 728 if (!scanhex(&a)) { 729 /* clear all breakpoints */ 730 for (i = 0; i < NBPTS; ++i) 731 bpts[i].enabled = 0; 732 iabr.enabled = 0; 733 dabr.enabled = 0; 734 printf("All breakpoints cleared\n"); 735 } else { 736 bp = at_breakpoint(a); 737 if (bp == 0) { 738 printf("No breakpoint at %x\n", a); 739 } else { 740 bp->enabled = 0; 741 } 742 } 743 break; 744 default: 745 termch = cmd; 746 if (!scanhex(&a)) { 747 /* print all breakpoints */ 748 printf("type address count\n"); 749 if (dabr.enabled) { 750 printf("data %.8x %8x [", dabr.address & ~7, 751 dabr.count); 752 if (dabr.address & 1) 753 printf("r"); 754 if (dabr.address & 2) 755 printf("w"); 756 if (!(dabr.address & 4)) 757 printf("p"); 758 printf("]\n"); 759 } 760 if (iabr.enabled) 761 printf("inst %.8x %8x\n", iabr.address & ~3, 762 iabr.count); 763 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) 764 if (bp->enabled) 765 printf("trap %.8x %8x\n", bp->address, 766 bp->count); 767 break; 768 } 769 bp = at_breakpoint(a); 770 if (bp == 0) { 771 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) 772 if (!bp->enabled) 773 break; 774 if (bp >= &bpts[NBPTS]) { 775 printf("Sorry, no free breakpoints\n"); 776 break; 777 } 778 } 779 bp->enabled = 1; 780 bp->address = a; 781 bp->count = 0; 782 scanhex(&bp->count); 783 break; 784 } 785} 786 787static void 788backtrace(struct pt_regs *excp) 789{ 790 unsigned sp; 791 unsigned stack[2]; 792 struct pt_regs regs; 793 extern char ret_from_except, ret_from_except_full, ret_from_syscall; 794 795 printf("backtrace:\n"); 796 797 if (excp != NULL) 798 sp = excp->gpr[1]; 799 else 800 sp = getsp(); 801 scanhex(&sp); 802 scannl(); 803 for (; sp != 0; sp = stack[0]) { 804 if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) 805 break; 806 printf("[%.8lx] ", stack[0]); 807 xmon_print_symbol(stack[1], " ", "\n"); 808 if (stack[1] == (unsigned) &ret_from_except 809 || stack[1] == (unsigned) &ret_from_except_full 810 || stack[1] == (unsigned) &ret_from_syscall) { 811 if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs)) 812 break; 813 printf("exception:%x [%x] %x\n", regs.trap, sp+16, 814 regs.nip); 815 sp = regs.gpr[1]; 816 if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) 817 break; 818 } 819 } 820} 821 822int 823getsp(void) 824{ 825 int x; 826 827 asm("mr %0,1" : "=r" (x) :); 828 return x; 829} 830 831void 832excprint(struct pt_regs *fp) 833{ 834 int trap; 835 836#ifdef CONFIG_SMP 837 printf("cpu %d: ", smp_processor_id()); 838#endif /* CONFIG_SMP */ 839 printf("vector: %x at pc=", fp->trap); 840 xmon_print_symbol(fp->nip, ": ", ", lr="); 841 xmon_print_symbol(fp->link, ": ", "\n"); 842 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp); 843 trap = TRAP(fp); 844 if (trap == 0x300 || trap == 0x600) 845 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr); 846 if (current) 847 printf("current = %x, pid = %d, comm = %s\n", 848 current, current->pid, current->comm); 849} 850 851void 852prregs(struct pt_regs *fp) 853{ 854 int n; 855 unsigned base; 856 857 if (scanhex(&base)) 858 fp = (struct pt_regs *) base; 859 for (n = 0; n < 32; ++n) { 860 printf("R%.2d = %.8x%s", n, fp->gpr[n], 861 (n & 3) == 3? "\n": " "); 862 if (n == 12 && !FULL_REGS(fp)) { 863 printf("\n"); 864 break; 865 } 866 } 867 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n", 868 fp->nip, fp->msr, fp->link, fp->ccr); 869 printf("ctr = %.8x xer = %.8x trap = %4x\n", 870 fp->ctr, fp->xer, fp->trap); 871} 872 873void 874cacheflush(void) 875{ 876 int cmd; 877 unsigned nflush; 878 879 cmd = inchar(); 880 if (cmd != 'i') 881 termch = cmd; 882 scanhex(&adrs); 883 if (termch != '\n') 884 termch = 0; 885 nflush = 1; 886 scanhex(&nflush); 887 nflush = (nflush + 31) / 32; 888 if (cmd != 'i') { 889 for (; nflush > 0; --nflush, adrs += 0x20) 890 cflush((void *) adrs); 891 } else { 892 for (; nflush > 0; --nflush, adrs += 0x20) 893 cinval((void *) adrs); 894 } 895} 896 897unsigned int 898read_spr(int n) 899{ 900 unsigned int instrs[2]; 901 int (*code)(void); 902 903 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); 904 instrs[1] = 0x4e800020; 905 store_inst(instrs); 906 store_inst(instrs+1); 907 code = (int (*)(void)) instrs; 908 return code(); 909} 910 911void 912write_spr(int n, unsigned int val) 913{ 914 unsigned int instrs[2]; 915 int (*code)(unsigned int); 916 917 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); 918 instrs[1] = 0x4e800020; 919 store_inst(instrs); 920 store_inst(instrs+1); 921 code = (int (*)(unsigned int)) instrs; 922 code(val); 923} 924 925static unsigned int regno; 926extern char exc_prolog; 927extern char dec_exc; 928 929void 930super_regs(void) 931{ 932 int i, cmd; 933 unsigned val; 934 935 cmd = skipbl(); 936 if (cmd == '\n') { 937 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr()); 938 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(), 939 get_sprg2(), get_sprg3()); 940 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1()); 941#ifdef CONFIG_PPC_STD_MMU 942 printf("sr0-15 ="); 943 for (i = 0; i < 16; ++i) 944 printf(" %x", get_sr(i)); 945 printf("\n"); 946#endif 947 asm("mr %0,1" : "=r" (i) :); 948 printf("sp = %x ", i); 949 asm("mr %0,2" : "=r" (i) :); 950 printf("toc = %x\n", i); 951 return; 952 } 953 954 scanhex(®no); 955 switch (cmd) { 956 case 'w': 957 val = read_spr(regno); 958 scanhex(&val); 959 write_spr(regno, val); 960 /* fall through */ 961 case 'r': 962 printf("spr %x = %x\n", regno, read_spr(regno)); 963 break; 964 case 's': 965 val = get_sr(regno); 966 scanhex(&val); 967 set_sr(regno, val); 968 break; 969 case 'm': 970 val = get_msr(); 971 scanhex(&val); 972 set_msr(val); 973 break; 974 } 975 scannl(); 976} 977 978#ifndef CONFIG_PPC_STD_MMU 979static void 980dump_hash_table(void) 981{ 982 printf("This CPU doesn't have a hash table.\n"); 983} 984#else 985 986static void 987dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) 988{ 989 extern void *Hash; 990 extern unsigned long Hash_size; 991 unsigned *htab = Hash; 992 unsigned hsize = Hash_size; 993 unsigned v, hmask, va, last_va = 0; 994 int found, last_found, i; 995 unsigned *hg, w1, last_w2 = 0, last_va0 = 0; 996 997 last_found = 0; 998 hmask = hsize / 64 - 1; 999 va = start; 1000 start = (start >> 12) & 0xffff; 1001 end = (end >> 12) & 0xffff; 1002 for (v = start; v < end; ++v) { 1003 found = 0; 1004 hg = htab + (((v ^ seg) & hmask) * 16); 1005 w1 = 0x80000000 | (seg << 7) | (v >> 10); 1006 for (i = 0; i < 8; ++i, hg += 2) { 1007 if (*hg == w1) { 1008 found = 1; 1009 break; 1010 } 1011 } 1012 if (!found) { 1013 w1 ^= 0x40; 1014 hg = htab + ((~(v ^ seg) & hmask) * 16); 1015 for (i = 0; i < 8; ++i, hg += 2) { 1016 if (*hg == w1) { 1017 found = 1; 1018 break; 1019 } 1020 } 1021 } 1022 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) { 1023 if (last_found) { 1024 if (last_va != last_va0) 1025 printf(" ... %x", last_va); 1026 printf("\n"); 1027 } 1028 if (found) { 1029 printf("%x to %x", va, hg[1]); 1030 last_va0 = va; 1031 } 1032 last_found = found; 1033 } 1034 if (found) { 1035 last_w2 = hg[1] & ~0x180; 1036 last_va = va; 1037 } 1038 va += 4096; 1039 } 1040 if (last_found) 1041 printf(" ... %x\n", last_va); 1042} 1043 1044static unsigned hash_ctx; 1045static unsigned hash_start; 1046static unsigned hash_end; 1047 1048static void 1049dump_hash_table(void) 1050{ 1051 int seg; 1052 unsigned seg_start, seg_end; 1053 1054 hash_ctx = 0; 1055 hash_start = 0; 1056 hash_end = 0xfffff000; 1057 scanhex(&hash_ctx); 1058 scanhex(&hash_start); 1059 scanhex(&hash_end); 1060 printf("Mappings for context %x\n", hash_ctx); 1061 seg_start = hash_start; 1062 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) { 1063 seg_end = (seg << 28) | 0x0ffff000; 1064 if (seg_end > hash_end) 1065 seg_end = hash_end; 1066 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111), 1067 seg_start, seg_end); 1068 seg_start = seg_end + 0x1000; 1069 } 1070} 1071#endif /* CONFIG_PPC_STD_MMU */ 1072 1073/* 1074 * Stuff for reading and writing memory safely 1075 */ 1076 1077int 1078mread(unsigned adrs, void *buf, int size) 1079{ 1080 volatile int n; 1081 char *p, *q; 1082 1083 n = 0; 1084 if( setjmp(bus_error_jmp) == 0 ){ 1085 debugger_fault_handler = handle_fault; 1086 sync(); 1087 p = (char *) adrs; 1088 q = (char *) buf; 1089 switch (size) { 1090 case 2: *(short *)q = *(short *)p; break; 1091 case 4: *(int *)q = *(int *)p; break; 1092 default: 1093 for( ; n < size; ++n ) { 1094 *q++ = *p++; 1095 sync(); 1096 } 1097 } 1098 sync(); 1099 /* wait a little while to see if we get a machine check */ 1100 __delay(200); 1101 n = size; 1102 } 1103 debugger_fault_handler = NULL; 1104 return n; 1105} 1106 1107int 1108mwrite(unsigned adrs, void *buf, int size) 1109{ 1110 volatile int n; 1111 char *p, *q; 1112 1113 n = 0; 1114 if( setjmp(bus_error_jmp) == 0 ){ 1115 debugger_fault_handler = handle_fault; 1116 sync(); 1117 p = (char *) adrs; 1118 q = (char *) buf; 1119 switch (size) { 1120 case 2: *(short *)p = *(short *)q; break; 1121 case 4: *(int *)p = *(int *)q; break; 1122 default: 1123 for( ; n < size; ++n ) { 1124 *p++ = *q++; 1125 sync(); 1126 } 1127 } 1128 sync(); 1129 n = size; 1130 } else { 1131 printf("*** Error writing address %x\n", adrs + n); 1132 } 1133 debugger_fault_handler = NULL; 1134 return n; 1135} 1136 1137static int fault_type; 1138static int fault_except; 1139static char *fault_chars[] = { "--", "**", "##" }; 1140 1141static void 1142handle_fault(struct pt_regs *regs) 1143{ 1144 fault_except = TRAP(regs); 1145 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2; 1146 longjmp(bus_error_jmp, 1); 1147} 1148 1149#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t)) 1150 1151void 1152byterev(unsigned char *val, int size) 1153{ 1154 int t; 1155 1156 switch (size) { 1157 case 2: 1158 SWAP(val[0], val[1], t); 1159 break; 1160 case 4: 1161 SWAP(val[0], val[3], t); 1162 SWAP(val[1], val[2], t); 1163 break; 1164 } 1165} 1166 1167static int brev; 1168static int mnoread; 1169 1170void 1171memex(void) 1172{ 1173 int cmd, inc, i, nslash; 1174 unsigned n; 1175 unsigned char val[4]; 1176 1177 last_cmd = "m\n"; 1178 scanhex(&adrs); 1179 while ((cmd = skipbl()) != '\n') { 1180 switch( cmd ){ 1181 case 'b': size = 1; break; 1182 case 'w': size = 2; break; 1183 case 'l': size = 4; break; 1184 case 'r': brev = !brev; break; 1185 case 'n': mnoread = 1; break; 1186 case '.': mnoread = 0; break; 1187 } 1188 } 1189 if( size <= 0 ) 1190 size = 1; 1191 else if( size > 4 ) 1192 size = 4; 1193 for(;;){ 1194 if (!mnoread) 1195 n = mread(adrs, val, size); 1196 printf("%.8x%c", adrs, brev? 'r': ' '); 1197 if (!mnoread) { 1198 if (brev) 1199 byterev(val, size); 1200 putchar(' '); 1201 for (i = 0; i < n; ++i) 1202 printf("%.2x", val[i]); 1203 for (; i < size; ++i) 1204 printf("%s", fault_chars[fault_type]); 1205 } 1206 putchar(' '); 1207 inc = size; 1208 nslash = 0; 1209 for(;;){ 1210 if( scanhex(&n) ){ 1211 for (i = 0; i < size; ++i) 1212 val[i] = n >> (i * 8); 1213 if (!brev) 1214 byterev(val, size); 1215 mwrite(adrs, val, size); 1216 inc = size; 1217 } 1218 cmd = skipbl(); 1219 if (cmd == '\n') 1220 break; 1221 inc = 0; 1222 switch (cmd) { 1223 case '\'': 1224 for(;;){ 1225 n = inchar(); 1226 if( n == '\\' ) 1227 n = bsesc(); 1228 else if( n == '\'' ) 1229 break; 1230 for (i = 0; i < size; ++i) 1231 val[i] = n >> (i * 8); 1232 if (!brev) 1233 byterev(val, size); 1234 mwrite(adrs, val, size); 1235 adrs += size; 1236 } 1237 adrs -= size; 1238 inc = size; 1239 break; 1240 case ',': 1241 adrs += size; 1242 break; 1243 case '.': 1244 mnoread = 0; 1245 break; 1246 case ';': 1247 break; 1248 case 'x': 1249 case EOF: 1250 scannl(); 1251 return; 1252 case 'b': 1253 case 'v': 1254 size = 1; 1255 break; 1256 case 'w': 1257 size = 2; 1258 break; 1259 case 'l': 1260 size = 4; 1261 break; 1262 case '^': 1263 adrs -= size; 1264 break; 1265 break; 1266 case '/': 1267 if (nslash > 0) 1268 adrs -= 1 << nslash; 1269 else 1270 nslash = 0; 1271 nslash += 4; 1272 adrs += 1 << nslash; 1273 break; 1274 case '\\': 1275 if (nslash < 0) 1276 adrs += 1 << -nslash; 1277 else 1278 nslash = 0; 1279 nslash -= 4; 1280 adrs -= 1 << -nslash; 1281 break; 1282 case 'm': 1283 scanhex(&adrs); 1284 break; 1285 case 'n': 1286 mnoread = 1; 1287 break; 1288 case 'r': 1289 brev = !brev; 1290 break; 1291 case '<': 1292 n = size; 1293 scanhex(&n); 1294 adrs -= n; 1295 break; 1296 case '>': 1297 n = size; 1298 scanhex(&n); 1299 adrs += n; 1300 break; 1301 } 1302 } 1303 adrs += inc; 1304 } 1305} 1306 1307int 1308bsesc(void) 1309{ 1310 int c; 1311 1312 c = inchar(); 1313 switch( c ){ 1314 case 'n': c = '\n'; break; 1315 case 'r': c = '\r'; break; 1316 case 'b': c = '\b'; break; 1317 case 't': c = '\t'; break; 1318 } 1319 return c; 1320} 1321 1322void 1323dump(void) 1324{ 1325 int c; 1326 1327 c = inchar(); 1328 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') 1329 termch = c; 1330 scanhex(&adrs); 1331 if( termch != '\n') 1332 termch = 0; 1333 if( c == 'i' ){ 1334 scanhex(&nidump); 1335 if( nidump == 0 ) 1336 nidump = 16; 1337 adrs += ppc_inst_dump(adrs, nidump); 1338 last_cmd = "di\n"; 1339 } else { 1340 scanhex(&ndump); 1341 if( ndump == 0 ) 1342 ndump = 64; 1343 prdump(adrs, ndump); 1344 adrs += ndump; 1345 last_cmd = "d\n"; 1346 } 1347} 1348 1349void 1350prdump(unsigned adrs, int ndump) 1351{ 1352 register int n, m, c, r, nr; 1353 unsigned char temp[16]; 1354 1355 for( n = ndump; n > 0; ){ 1356 printf("%.8x", adrs); 1357 putchar(' '); 1358 r = n < 16? n: 16; 1359 nr = mread(adrs, temp, r); 1360 adrs += nr; 1361 for( m = 0; m < r; ++m ){ 1362 putchar((m & 3) == 0 && m > 0? '.': ' '); 1363 if( m < nr ) 1364 printf("%.2x", temp[m]); 1365 else 1366 printf("%s", fault_chars[fault_type]); 1367 } 1368 for(; m < 16; ++m ) 1369 printf(" "); 1370 printf(" |"); 1371 for( m = 0; m < r; ++m ){ 1372 if( m < nr ){ 1373 c = temp[m]; 1374 putchar(' ' <= c && c <= '~'? c: '.'); 1375 } else 1376 putchar(' '); 1377 } 1378 n -= r; 1379 for(; m < 16; ++m ) 1380 putchar(' '); 1381 printf("|\n"); 1382 if( nr < r ) 1383 break; 1384 } 1385} 1386 1387int 1388ppc_inst_dump(unsigned adr, int count) 1389{ 1390 int nr, dotted; 1391 unsigned first_adr; 1392 unsigned long inst, last_inst = 0; 1393 unsigned char val[4]; 1394 1395 dotted = 0; 1396 for (first_adr = adr; count > 0; --count, adr += 4){ 1397 nr = mread(adr, val, 4); 1398 if( nr == 0 ){ 1399 const char *x = fault_chars[fault_type]; 1400 printf("%.8x %s%s%s%s\n", adr, x, x, x, x); 1401 break; 1402 } 1403 inst = GETWORD(val); 1404 if (adr > first_adr && inst == last_inst) { 1405 if (!dotted) { 1406 printf(" ...\n"); 1407 dotted = 1; 1408 } 1409 continue; 1410 } 1411 dotted = 0; 1412 last_inst = inst; 1413 printf("%.8x ", adr); 1414 printf("%.8x\t", inst); 1415 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */ 1416 printf("\n"); 1417 } 1418 return adr - first_adr; 1419} 1420 1421void 1422print_address(unsigned addr) 1423{ 1424 printf("0x%x", addr); 1425} 1426 1427/* 1428 * Memory operations - move, set, print differences 1429 */ 1430static unsigned mdest; /* destination address */ 1431static unsigned msrc; /* source address */ 1432static unsigned mval; /* byte value to set memory to */ 1433static unsigned mcount; /* # bytes to affect */ 1434static unsigned mdiffs; /* max # differences to print */ 1435 1436void 1437memops(int cmd) 1438{ 1439 scanhex(&mdest); 1440 if( termch != '\n' ) 1441 termch = 0; 1442 scanhex(cmd == 's'? &mval: &msrc); 1443 if( termch != '\n' ) 1444 termch = 0; 1445 scanhex(&mcount); 1446 switch( cmd ){ 1447 case 'm': 1448 memmove((void *)mdest, (void *)msrc, mcount); 1449 break; 1450 case 's': 1451 memset((void *)mdest, mval, mcount); 1452 break; 1453 case 'd': 1454 if( termch != '\n' ) 1455 termch = 0; 1456 scanhex(&mdiffs); 1457 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs); 1458 break; 1459 } 1460} 1461 1462void 1463memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr) 1464{ 1465 unsigned n, prt; 1466 1467 prt = 0; 1468 for( n = nb; n > 0; --n ) 1469 if( *p1++ != *p2++ ) 1470 if( ++prt <= maxpr ) 1471 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1, 1472 p1[-1], (unsigned)p2 - 1, p2[-1]); 1473 if( prt > maxpr ) 1474 printf("Total of %d differences\n", prt); 1475} 1476 1477static unsigned mend; 1478static unsigned mask; 1479 1480void 1481memlocate(void) 1482{ 1483 unsigned a, n; 1484 unsigned char val[4]; 1485 1486 last_cmd = "ml"; 1487 scanhex(&mdest); 1488 if (termch != '\n') { 1489 termch = 0; 1490 scanhex(&mend); 1491 if (termch != '\n') { 1492 termch = 0; 1493 scanhex(&mval); 1494 mask = ~0; 1495 if (termch != '\n') termch = 0; 1496 scanhex(&mask); 1497 } 1498 } 1499 n = 0; 1500 for (a = mdest; a < mend; a += 4) { 1501 if (mread(a, val, 4) == 4 1502 && ((GETWORD(val) ^ mval) & mask) == 0) { 1503 printf("%.8x: %.8x\n", a, GETWORD(val)); 1504 if (++n >= 10) 1505 break; 1506 } 1507 } 1508} 1509 1510static unsigned mskip = 0x1000; 1511static unsigned mlim = 0xffffffff; 1512 1513void 1514memzcan(void) 1515{ 1516 unsigned char v; 1517 unsigned a; 1518 int ok, ook; 1519 1520 scanhex(&mdest); 1521 if (termch != '\n') termch = 0; 1522 scanhex(&mskip); 1523 if (termch != '\n') termch = 0; 1524 scanhex(&mlim); 1525 ook = 0; 1526 for (a = mdest; a < mlim; a += mskip) { 1527 ok = mread(a, &v, 1); 1528 if (ok && !ook) { 1529 printf("%.8x .. ", a); 1530 fflush(stdout); 1531 } else if (!ok && ook) 1532 printf("%.8x\n", a - mskip); 1533 ook = ok; 1534 if (a + mskip < a) 1535 break; 1536 } 1537 if (ook) 1538 printf("%.8x\n", a - mskip); 1539} 1540 1541void proccall(void) 1542{ 1543 unsigned int args[8]; 1544 unsigned int ret; 1545 int i; 1546 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int, 1547 unsigned int, unsigned int, unsigned int, 1548 unsigned int, unsigned int, unsigned int); 1549 callfunc_t func; 1550 1551 scanhex(&adrs); 1552 if (termch != '\n') 1553 termch = 0; 1554 for (i = 0; i < 8; ++i) 1555 args[i] = 0; 1556 for (i = 0; i < 8; ++i) { 1557 if (!scanhex(&args[i]) || termch == '\n') 1558 break; 1559 termch = 0; 1560 } 1561 func = (callfunc_t) adrs; 1562 ret = 0; 1563 if (setjmp(bus_error_jmp) == 0) { 1564 debugger_fault_handler = handle_fault; 1565 sync(); 1566 ret = func(args[0], args[1], args[2], args[3], 1567 args[4], args[5], args[6], args[7]); 1568 sync(); 1569 printf("return value is %x\n", ret); 1570 } else { 1571 printf("*** %x exception occurred\n", fault_except); 1572 } 1573 debugger_fault_handler = NULL; 1574} 1575 1576/* Input scanning routines */ 1577int 1578skipbl(void) 1579{ 1580 int c; 1581 1582 if( termch != 0 ){ 1583 c = termch; 1584 termch = 0; 1585 } else 1586 c = inchar(); 1587 while( c == ' ' || c == '\t' ) 1588 c = inchar(); 1589 return c; 1590} 1591 1592#define N_PTREGS 44 1593static char *regnames[N_PTREGS] = { 1594 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 1595 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 1596 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 1597 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 1598 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq", 1599 "trap", "dar", "dsisr", "res" 1600}; 1601 1602int 1603scanhex(unsigned *vp) 1604{ 1605 int c, d; 1606 unsigned v; 1607 1608 c = skipbl(); 1609 if (c == '%') { 1610 /* parse register name */ 1611 char regname[8]; 1612 int i; 1613 1614 for (i = 0; i < sizeof(regname) - 1; ++i) { 1615 c = inchar(); 1616 if (!isalnum(c)) { 1617 termch = c; 1618 break; 1619 } 1620 regname[i] = c; 1621 } 1622 regname[i] = 0; 1623 for (i = 0; i < N_PTREGS; ++i) { 1624 if (strcmp(regnames[i], regname) == 0) { 1625 unsigned *rp = (unsigned *) 1626 xmon_regs[smp_processor_id()]; 1627 if (rp == NULL) { 1628 printf("regs not available\n"); 1629 return 0; 1630 } 1631 *vp = rp[i]; 1632 return 1; 1633 } 1634 } 1635 printf("invalid register name '%%%s'\n", regname); 1636 return 0; 1637 } else if (c == '$') { 1638 static char symname[128]; 1639 int i; 1640 for (i=0; i<63; i++) { 1641 c = inchar(); 1642 if (isspace(c)) { 1643 termch = c; 1644 break; 1645 } 1646 symname[i] = c; 1647 } 1648 symname[i++] = 0; 1649 *vp = 0; 1650 if (setjmp(bus_error_jmp) == 0) { 1651 debugger_fault_handler = handle_fault; 1652 sync(); 1653 *vp = kallsyms_lookup_name(symname); 1654 sync(); 1655 } 1656 debugger_fault_handler = NULL; 1657 if (!(*vp)) { 1658 printf("unknown symbol\n"); 1659 return 0; 1660 } 1661 return 1; 1662 } 1663 1664 d = hexdigit(c); 1665 if( d == EOF ){ 1666 termch = c; 1667 return 0; 1668 } 1669 v = 0; 1670 do { 1671 v = (v << 4) + d; 1672 c = inchar(); 1673 d = hexdigit(c); 1674 } while( d != EOF ); 1675 termch = c; 1676 *vp = v; 1677 return 1; 1678} 1679 1680void 1681scannl(void) 1682{ 1683 int c; 1684 1685 c = termch; 1686 termch = 0; 1687 while( c != '\n' ) 1688 c = inchar(); 1689} 1690 1691int hexdigit(int c) 1692{ 1693 if( '0' <= c && c <= '9' ) 1694 return c - '0'; 1695 if( 'A' <= c && c <= 'F' ) 1696 return c - ('A' - 10); 1697 if( 'a' <= c && c <= 'f' ) 1698 return c - ('a' - 10); 1699 return EOF; 1700} 1701 1702void 1703getstring(char *s, int size) 1704{ 1705 int c; 1706 1707 c = skipbl(); 1708 do { 1709 if( size > 1 ){ 1710 *s++ = c; 1711 --size; 1712 } 1713 c = inchar(); 1714 } while( c != ' ' && c != '\t' && c != '\n' ); 1715 termch = c; 1716 *s = 0; 1717} 1718 1719static char line[256]; 1720static char *lineptr; 1721 1722void 1723flush_input(void) 1724{ 1725 lineptr = NULL; 1726} 1727 1728int 1729inchar(void) 1730{ 1731 if (lineptr == NULL || *lineptr == 0) { 1732 if (fgets(line, sizeof(line), stdin) == NULL) { 1733 lineptr = NULL; 1734 return EOF; 1735 } 1736 lineptr = line; 1737 } 1738 return *lineptr++; 1739} 1740 1741void 1742take_input(char *str) 1743{ 1744 lineptr = str; 1745} 1746 1747static void 1748symbol_lookup(void) 1749{ 1750 int type = inchar(); 1751 unsigned addr; 1752 static char tmp[128]; 1753 1754 switch (type) { 1755 case 'a': 1756 if (scanhex(&addr)) 1757 xmon_print_symbol(addr, ": ", "\n"); 1758 termch = 0; 1759 break; 1760 case 's': 1761 getstring(tmp, 64); 1762 if (setjmp(bus_error_jmp) == 0) { 1763 debugger_fault_handler = handle_fault; 1764 sync(); 1765 addr = kallsyms_lookup_name(tmp); 1766 if (addr) 1767 printf("%s: %lx\n", tmp, addr); 1768 else 1769 printf("Symbol '%s' not found.\n", tmp); 1770 sync(); 1771 } 1772 debugger_fault_handler = NULL; 1773 termch = 0; 1774 break; 1775 } 1776} 1777