Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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