1 /* 2 * Routines providing a simple monitor for use on the PowerMac. 3 * 4 * Copyright (C) 1996-2005 Paul Mackerras. 5 * Copyright (C) 2001 PPC64 Team, IBM Corp 6 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 11 * 2 of the License, or (at your option) any later version. 12 */ 13 #include <linux/errno.h> 14 #include <linux/sched.h> 15 #include <linux/smp.h> 16 #include <linux/mm.h> 17 #include <linux/reboot.h> 18 #include <linux/delay.h> 19 #include <linux/kallsyms.h> 20 #include <linux/cpumask.h> 21 #include <linux/module.h> 22 #include <linux/sysrq.h> 23 #include <linux/interrupt.h> 24 #include <linux/irq.h> 25 #include <linux/bug.h> 26 27 #include <asm/ptrace.h> 28 #include <asm/string.h> 29 #include <asm/prom.h> 30 #include <asm/machdep.h> 31 #include <asm/xmon.h> 32 #include <asm/processor.h> 33 #include <asm/pgtable.h> 34 #include <asm/mmu.h> 35 #include <asm/mmu_context.h> 36 #include <asm/cputable.h> 37 #include <asm/rtas.h> 38 #include <asm/sstep.h> 39 #include <asm/irq_regs.h> 40 #include <asm/spu.h> 41 #include <asm/spu_priv1.h> 42 #include <asm/firmware.h> 43 #include <asm/setjmp.h> 44 #include <asm/reg.h> 45 46 #ifdef CONFIG_PPC64 47 #include <asm/hvcall.h> 48 #include <asm/paca.h> 49 #endif 50 51 #include "nonstdio.h" 52 #include "dis-asm.h" 53 54 #define scanhex xmon_scanhex 55 #define skipbl xmon_skipbl 56 57 #ifdef CONFIG_SMP 58 static cpumask_t cpus_in_xmon = CPU_MASK_NONE; 59 static unsigned long xmon_taken = 1; 60 static int xmon_owner; 61 static int xmon_gate; 62 #endif /* CONFIG_SMP */ 63 64 static unsigned long in_xmon = 0; 65 66 static unsigned long adrs; 67 static int size = 1; 68 #define MAX_DUMP (128 * 1024) 69 static unsigned long ndump = 64; 70 static unsigned long nidump = 16; 71 static unsigned long ncsum = 4096; 72 static int termch; 73 static char tmpstr[128]; 74 75 static long bus_error_jmp[JMP_BUF_LEN]; 76 static int catch_memory_errors; 77 static long *xmon_fault_jmp[NR_CPUS]; 78 79 /* Breakpoint stuff */ 80 struct bpt { 81 unsigned long address; 82 unsigned int instr[2]; 83 atomic_t ref_count; 84 int enabled; 85 unsigned long pad; 86 }; 87 88 /* Bits in bpt.enabled */ 89 #define BP_IABR_TE 1 /* IABR translation enabled */ 90 #define BP_IABR 2 91 #define BP_TRAP 8 92 #define BP_DABR 0x10 93 94 #define NBPTS 256 95 static struct bpt bpts[NBPTS]; 96 static struct bpt dabr; 97 static struct bpt *iabr; 98 static unsigned bpinstr = 0x7fe00008; /* trap */ 99 100 #define BP_NUM(bp) ((bp) - bpts + 1) 101 102 /* Prototypes */ 103 static int cmds(struct pt_regs *); 104 static int mread(unsigned long, void *, int); 105 static int mwrite(unsigned long, void *, int); 106 static int handle_fault(struct pt_regs *); 107 static void byterev(unsigned char *, int); 108 static void memex(void); 109 static int bsesc(void); 110 static void dump(void); 111 static void prdump(unsigned long, long); 112 static int ppc_inst_dump(unsigned long, long, int); 113 static void dump_log_buf(void); 114 static void backtrace(struct pt_regs *); 115 static void excprint(struct pt_regs *); 116 static void prregs(struct pt_regs *); 117 static void memops(int); 118 static void memlocate(void); 119 static void memzcan(void); 120 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned); 121 int skipbl(void); 122 int scanhex(unsigned long *valp); 123 static void scannl(void); 124 static int hexdigit(int); 125 void getstring(char *, int); 126 static void flush_input(void); 127 static int inchar(void); 128 static void take_input(char *); 129 static unsigned long read_spr(int); 130 static void write_spr(int, unsigned long); 131 static void super_regs(void); 132 static void remove_bpts(void); 133 static void insert_bpts(void); 134 static void remove_cpu_bpts(void); 135 static void insert_cpu_bpts(void); 136 static struct bpt *at_breakpoint(unsigned long pc); 137 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp); 138 static int do_step(struct pt_regs *); 139 static void bpt_cmds(void); 140 static void cacheflush(void); 141 static int cpu_cmd(void); 142 static void csum(void); 143 static void bootcmds(void); 144 static void proccall(void); 145 void dump_segments(void); 146 static void symbol_lookup(void); 147 static void xmon_show_stack(unsigned long sp, unsigned long lr, 148 unsigned long pc); 149 static void xmon_print_symbol(unsigned long address, const char *mid, 150 const char *after); 151 static const char *getvecname(unsigned long vec); 152 153 static int do_spu_cmd(void); 154 155 #ifdef CONFIG_44x 156 static void dump_tlb_44x(void); 157 #endif 158 159 static int xmon_no_auto_backtrace; 160 161 extern void xmon_enter(void); 162 extern void xmon_leave(void); 163 164 #ifdef CONFIG_PPC64 165 #define REG "%.16lx" 166 #define REGS_PER_LINE 4 167 #define LAST_VOLATILE 13 168 #else 169 #define REG "%.8lx" 170 #define REGS_PER_LINE 8 171 #define LAST_VOLATILE 12 172 #endif 173 174 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3]) 175 176 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ 177 || ('a' <= (c) && (c) <= 'f') \ 178 || ('A' <= (c) && (c) <= 'F')) 179 #define isalnum(c) (('0' <= (c) && (c) <= '9') \ 180 || ('a' <= (c) && (c) <= 'z') \ 181 || ('A' <= (c) && (c) <= 'Z')) 182 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0) 183 184 static char *help_string = "\ 185 Commands:\n\ 186 b show breakpoints\n\ 187 bd set data breakpoint\n\ 188 bi set instruction breakpoint\n\ 189 bc clear breakpoint\n" 190 #ifdef CONFIG_SMP 191 "\ 192 c print cpus stopped in xmon\n\ 193 c# try to switch to cpu number h (in hex)\n" 194 #endif 195 "\ 196 C checksum\n\ 197 d dump bytes\n\ 198 di dump instructions\n\ 199 df dump float values\n\ 200 dd dump double values\n\ 201 dl dump the kernel log buffer\n\ 202 dr dump stream of raw bytes\n\ 203 e print exception information\n\ 204 f flush cache\n\ 205 la lookup symbol+offset of specified address\n\ 206 ls lookup address of specified symbol\n\ 207 m examine/change memory\n\ 208 mm move a block of memory\n\ 209 ms set a block of memory\n\ 210 md compare two blocks of memory\n\ 211 ml locate a block of memory\n\ 212 mz zero a block of memory\n\ 213 mi show information about memory allocation\n\ 214 p call a procedure\n\ 215 r print registers\n\ 216 s single step\n" 217 #ifdef CONFIG_SPU_BASE 218 " ss stop execution on all spus\n\ 219 sr restore execution on stopped spus\n\ 220 sf # dump spu fields for spu # (in hex)\n\ 221 sd # dump spu local store for spu # (in hex)\n\ 222 sdi # disassemble spu local store for spu # (in hex)\n" 223 #endif 224 " S print special registers\n\ 225 t print backtrace\n\ 226 x exit monitor and recover\n\ 227 X exit monitor and dont recover\n" 228 #ifdef CONFIG_PPC64 229 " u dump segment table or SLB\n" 230 #endif 231 #ifdef CONFIG_PPC_STD_MMU_32 232 " u dump segment registers\n" 233 #endif 234 #ifdef CONFIG_44x 235 " u dump TLB\n" 236 #endif 237 " ? help\n" 238 " zr reboot\n\ 239 zh halt\n" 240 ; 241 242 static struct pt_regs *xmon_regs; 243 244 static inline void sync(void) 245 { 246 asm volatile("sync; isync"); 247 } 248 249 static inline void store_inst(void *p) 250 { 251 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p)); 252 } 253 254 static inline void cflush(void *p) 255 { 256 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p)); 257 } 258 259 static inline void cinval(void *p) 260 { 261 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); 262 } 263 264 /* 265 * Disable surveillance (the service processor watchdog function) 266 * while we are in xmon. 267 * XXX we should re-enable it when we leave. :) 268 */ 269 #define SURVEILLANCE_TOKEN 9000 270 271 static inline void disable_surveillance(void) 272 { 273 #ifdef CONFIG_PPC_PSERIES 274 /* Since this can't be a module, args should end up below 4GB. */ 275 static struct rtas_args args; 276 277 /* 278 * At this point we have got all the cpus we can into 279 * xmon, so there is hopefully no other cpu calling RTAS 280 * at the moment, even though we don't take rtas.lock. 281 * If we did try to take rtas.lock there would be a 282 * real possibility of deadlock. 283 */ 284 args.token = rtas_token("set-indicator"); 285 if (args.token == RTAS_UNKNOWN_SERVICE) 286 return; 287 args.nargs = 3; 288 args.nret = 1; 289 args.rets = &args.args[3]; 290 args.args[0] = SURVEILLANCE_TOKEN; 291 args.args[1] = 0; 292 args.args[2] = 0; 293 enter_rtas(__pa(&args)); 294 #endif /* CONFIG_PPC_PSERIES */ 295 } 296 297 #ifdef CONFIG_SMP 298 static int xmon_speaker; 299 300 static void get_output_lock(void) 301 { 302 int me = smp_processor_id() + 0x100; 303 int last_speaker = 0, prev; 304 long timeout; 305 306 if (xmon_speaker == me) 307 return; 308 for (;;) { 309 if (xmon_speaker == 0) { 310 last_speaker = cmpxchg(&xmon_speaker, 0, me); 311 if (last_speaker == 0) 312 return; 313 } 314 timeout = 10000000; 315 while (xmon_speaker == last_speaker) { 316 if (--timeout > 0) 317 continue; 318 /* hostile takeover */ 319 prev = cmpxchg(&xmon_speaker, last_speaker, me); 320 if (prev == last_speaker) 321 return; 322 break; 323 } 324 } 325 } 326 327 static void release_output_lock(void) 328 { 329 xmon_speaker = 0; 330 } 331 332 int cpus_are_in_xmon(void) 333 { 334 return !cpus_empty(cpus_in_xmon); 335 } 336 #endif 337 338 static int xmon_core(struct pt_regs *regs, int fromipi) 339 { 340 int cmd = 0; 341 struct bpt *bp; 342 long recurse_jmp[JMP_BUF_LEN]; 343 unsigned long offset; 344 unsigned long flags; 345 #ifdef CONFIG_SMP 346 int cpu; 347 int secondary; 348 unsigned long timeout; 349 #endif 350 351 local_irq_save(flags); 352 353 bp = in_breakpoint_table(regs->nip, &offset); 354 if (bp != NULL) { 355 regs->nip = bp->address + offset; 356 atomic_dec(&bp->ref_count); 357 } 358 359 remove_cpu_bpts(); 360 361 #ifdef CONFIG_SMP 362 cpu = smp_processor_id(); 363 if (cpu_isset(cpu, cpus_in_xmon)) { 364 get_output_lock(); 365 excprint(regs); 366 printf("cpu 0x%x: Exception %lx %s in xmon, " 367 "returning to main loop\n", 368 cpu, regs->trap, getvecname(TRAP(regs))); 369 release_output_lock(); 370 longjmp(xmon_fault_jmp[cpu], 1); 371 } 372 373 if (setjmp(recurse_jmp) != 0) { 374 if (!in_xmon || !xmon_gate) { 375 get_output_lock(); 376 printf("xmon: WARNING: bad recursive fault " 377 "on cpu 0x%x\n", cpu); 378 release_output_lock(); 379 goto waiting; 380 } 381 secondary = !(xmon_taken && cpu == xmon_owner); 382 goto cmdloop; 383 } 384 385 xmon_fault_jmp[cpu] = recurse_jmp; 386 cpu_set(cpu, cpus_in_xmon); 387 388 bp = NULL; 389 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) 390 bp = at_breakpoint(regs->nip); 391 if (bp || (regs->msr & MSR_RI) == 0) 392 fromipi = 0; 393 394 if (!fromipi) { 395 get_output_lock(); 396 excprint(regs); 397 if (bp) { 398 printf("cpu 0x%x stopped at breakpoint 0x%x (", 399 cpu, BP_NUM(bp)); 400 xmon_print_symbol(regs->nip, " ", ")\n"); 401 } 402 if ((regs->msr & MSR_RI) == 0) 403 printf("WARNING: exception is not recoverable, " 404 "can't continue\n"); 405 release_output_lock(); 406 } 407 408 waiting: 409 secondary = 1; 410 while (secondary && !xmon_gate) { 411 if (in_xmon == 0) { 412 if (fromipi) 413 goto leave; 414 secondary = test_and_set_bit(0, &in_xmon); 415 } 416 barrier(); 417 } 418 419 if (!secondary && !xmon_gate) { 420 /* we are the first cpu to come in */ 421 /* interrupt other cpu(s) */ 422 int ncpus = num_online_cpus(); 423 424 xmon_owner = cpu; 425 mb(); 426 if (ncpus > 1) { 427 smp_send_debugger_break(MSG_ALL_BUT_SELF); 428 /* wait for other cpus to come in */ 429 for (timeout = 100000000; timeout != 0; --timeout) { 430 if (cpus_weight(cpus_in_xmon) >= ncpus) 431 break; 432 barrier(); 433 } 434 } 435 remove_bpts(); 436 disable_surveillance(); 437 /* for breakpoint or single step, print the current instr. */ 438 if (bp || TRAP(regs) == 0xd00) 439 ppc_inst_dump(regs->nip, 1, 0); 440 printf("enter ? for help\n"); 441 mb(); 442 xmon_gate = 1; 443 barrier(); 444 } 445 446 cmdloop: 447 while (in_xmon) { 448 if (secondary) { 449 if (cpu == xmon_owner) { 450 if (!test_and_set_bit(0, &xmon_taken)) { 451 secondary = 0; 452 continue; 453 } 454 /* missed it */ 455 while (cpu == xmon_owner) 456 barrier(); 457 } 458 barrier(); 459 } else { 460 cmd = cmds(regs); 461 if (cmd != 0) { 462 /* exiting xmon */ 463 insert_bpts(); 464 xmon_gate = 0; 465 wmb(); 466 in_xmon = 0; 467 break; 468 } 469 /* have switched to some other cpu */ 470 secondary = 1; 471 } 472 } 473 leave: 474 cpu_clear(cpu, cpus_in_xmon); 475 xmon_fault_jmp[cpu] = NULL; 476 #else 477 /* UP is simple... */ 478 if (in_xmon) { 479 printf("Exception %lx %s in xmon, returning to main loop\n", 480 regs->trap, getvecname(TRAP(regs))); 481 longjmp(xmon_fault_jmp[0], 1); 482 } 483 if (setjmp(recurse_jmp) == 0) { 484 xmon_fault_jmp[0] = recurse_jmp; 485 in_xmon = 1; 486 487 excprint(regs); 488 bp = at_breakpoint(regs->nip); 489 if (bp) { 490 printf("Stopped at breakpoint %x (", BP_NUM(bp)); 491 xmon_print_symbol(regs->nip, " ", ")\n"); 492 } 493 if ((regs->msr & MSR_RI) == 0) 494 printf("WARNING: exception is not recoverable, " 495 "can't continue\n"); 496 remove_bpts(); 497 disable_surveillance(); 498 /* for breakpoint or single step, print the current instr. */ 499 if (bp || TRAP(regs) == 0xd00) 500 ppc_inst_dump(regs->nip, 1, 0); 501 printf("enter ? for help\n"); 502 } 503 504 cmd = cmds(regs); 505 506 insert_bpts(); 507 in_xmon = 0; 508 #endif 509 510 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) { 511 bp = at_breakpoint(regs->nip); 512 if (bp != NULL) { 513 int stepped = emulate_step(regs, bp->instr[0]); 514 if (stepped == 0) { 515 regs->nip = (unsigned long) &bp->instr[0]; 516 atomic_inc(&bp->ref_count); 517 } else if (stepped < 0) { 518 printf("Couldn't single-step %s instruction\n", 519 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd")); 520 } 521 } 522 } 523 524 insert_cpu_bpts(); 525 526 local_irq_restore(flags); 527 528 return cmd != 'X' && cmd != EOF; 529 } 530 531 int xmon(struct pt_regs *excp) 532 { 533 struct pt_regs regs; 534 535 if (excp == NULL) { 536 ppc_save_regs(®s); 537 excp = ®s; 538 } 539 540 return xmon_core(excp, 0); 541 } 542 EXPORT_SYMBOL(xmon); 543 544 irqreturn_t xmon_irq(int irq, void *d) 545 { 546 unsigned long flags; 547 local_irq_save(flags); 548 printf("Keyboard interrupt\n"); 549 xmon(get_irq_regs()); 550 local_irq_restore(flags); 551 return IRQ_HANDLED; 552 } 553 554 static int xmon_bpt(struct pt_regs *regs) 555 { 556 struct bpt *bp; 557 unsigned long offset; 558 559 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) 560 return 0; 561 562 /* Are we at the trap at bp->instr[1] for some bp? */ 563 bp = in_breakpoint_table(regs->nip, &offset); 564 if (bp != NULL && offset == 4) { 565 regs->nip = bp->address + 4; 566 atomic_dec(&bp->ref_count); 567 return 1; 568 } 569 570 /* Are we at a breakpoint? */ 571 bp = at_breakpoint(regs->nip); 572 if (!bp) 573 return 0; 574 575 xmon_core(regs, 0); 576 577 return 1; 578 } 579 580 static int xmon_sstep(struct pt_regs *regs) 581 { 582 if (user_mode(regs)) 583 return 0; 584 xmon_core(regs, 0); 585 return 1; 586 } 587 588 static int xmon_dabr_match(struct pt_regs *regs) 589 { 590 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) 591 return 0; 592 if (dabr.enabled == 0) 593 return 0; 594 xmon_core(regs, 0); 595 return 1; 596 } 597 598 static int xmon_iabr_match(struct pt_regs *regs) 599 { 600 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) 601 return 0; 602 if (iabr == NULL) 603 return 0; 604 xmon_core(regs, 0); 605 return 1; 606 } 607 608 static int xmon_ipi(struct pt_regs *regs) 609 { 610 #ifdef CONFIG_SMP 611 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon)) 612 xmon_core(regs, 1); 613 #endif 614 return 0; 615 } 616 617 static int xmon_fault_handler(struct pt_regs *regs) 618 { 619 struct bpt *bp; 620 unsigned long offset; 621 622 if (in_xmon && catch_memory_errors) 623 handle_fault(regs); /* doesn't return */ 624 625 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) { 626 bp = in_breakpoint_table(regs->nip, &offset); 627 if (bp != NULL) { 628 regs->nip = bp->address + offset; 629 atomic_dec(&bp->ref_count); 630 } 631 } 632 633 return 0; 634 } 635 636 static struct bpt *at_breakpoint(unsigned long pc) 637 { 638 int i; 639 struct bpt *bp; 640 641 bp = bpts; 642 for (i = 0; i < NBPTS; ++i, ++bp) 643 if (bp->enabled && pc == bp->address) 644 return bp; 645 return NULL; 646 } 647 648 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp) 649 { 650 unsigned long off; 651 652 off = nip - (unsigned long) bpts; 653 if (off >= sizeof(bpts)) 654 return NULL; 655 off %= sizeof(struct bpt); 656 if (off != offsetof(struct bpt, instr[0]) 657 && off != offsetof(struct bpt, instr[1])) 658 return NULL; 659 *offp = off - offsetof(struct bpt, instr[0]); 660 return (struct bpt *) (nip - off); 661 } 662 663 static struct bpt *new_breakpoint(unsigned long a) 664 { 665 struct bpt *bp; 666 667 a &= ~3UL; 668 bp = at_breakpoint(a); 669 if (bp) 670 return bp; 671 672 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) { 673 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) { 674 bp->address = a; 675 bp->instr[1] = bpinstr; 676 store_inst(&bp->instr[1]); 677 return bp; 678 } 679 } 680 681 printf("Sorry, no free breakpoints. Please clear one first.\n"); 682 return NULL; 683 } 684 685 static void insert_bpts(void) 686 { 687 int i; 688 struct bpt *bp; 689 690 bp = bpts; 691 for (i = 0; i < NBPTS; ++i, ++bp) { 692 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0) 693 continue; 694 if (mread(bp->address, &bp->instr[0], 4) != 4) { 695 printf("Couldn't read instruction at %lx, " 696 "disabling breakpoint there\n", bp->address); 697 bp->enabled = 0; 698 continue; 699 } 700 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) { 701 printf("Breakpoint at %lx is on an mtmsrd or rfid " 702 "instruction, disabling it\n", bp->address); 703 bp->enabled = 0; 704 continue; 705 } 706 store_inst(&bp->instr[0]); 707 if (bp->enabled & BP_IABR) 708 continue; 709 if (mwrite(bp->address, &bpinstr, 4) != 4) { 710 printf("Couldn't write instruction at %lx, " 711 "disabling breakpoint there\n", bp->address); 712 bp->enabled &= ~BP_TRAP; 713 continue; 714 } 715 store_inst((void *)bp->address); 716 } 717 } 718 719 static void insert_cpu_bpts(void) 720 { 721 if (dabr.enabled) 722 set_dabr(dabr.address | (dabr.enabled & 7)); 723 if (iabr && cpu_has_feature(CPU_FTR_IABR)) 724 mtspr(SPRN_IABR, iabr->address 725 | (iabr->enabled & (BP_IABR|BP_IABR_TE))); 726 } 727 728 static void remove_bpts(void) 729 { 730 int i; 731 struct bpt *bp; 732 unsigned instr; 733 734 bp = bpts; 735 for (i = 0; i < NBPTS; ++i, ++bp) { 736 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP) 737 continue; 738 if (mread(bp->address, &instr, 4) == 4 739 && instr == bpinstr 740 && mwrite(bp->address, &bp->instr, 4) != 4) 741 printf("Couldn't remove breakpoint at %lx\n", 742 bp->address); 743 else 744 store_inst((void *)bp->address); 745 } 746 } 747 748 static void remove_cpu_bpts(void) 749 { 750 set_dabr(0); 751 if (cpu_has_feature(CPU_FTR_IABR)) 752 mtspr(SPRN_IABR, 0); 753 } 754 755 /* Command interpreting routine */ 756 static char *last_cmd; 757 758 static int 759 cmds(struct pt_regs *excp) 760 { 761 int cmd = 0; 762 763 last_cmd = NULL; 764 xmon_regs = excp; 765 766 if (!xmon_no_auto_backtrace) { 767 xmon_no_auto_backtrace = 1; 768 xmon_show_stack(excp->gpr[1], excp->link, excp->nip); 769 } 770 771 for(;;) { 772 #ifdef CONFIG_SMP 773 printf("%x:", smp_processor_id()); 774 #endif /* CONFIG_SMP */ 775 printf("mon> "); 776 flush_input(); 777 termch = 0; 778 cmd = skipbl(); 779 if( cmd == '\n' ) { 780 if (last_cmd == NULL) 781 continue; 782 take_input(last_cmd); 783 last_cmd = NULL; 784 cmd = inchar(); 785 } 786 switch (cmd) { 787 case 'm': 788 cmd = inchar(); 789 switch (cmd) { 790 case 'm': 791 case 's': 792 case 'd': 793 memops(cmd); 794 break; 795 case 'l': 796 memlocate(); 797 break; 798 case 'z': 799 memzcan(); 800 break; 801 case 'i': 802 show_mem(); 803 break; 804 default: 805 termch = cmd; 806 memex(); 807 } 808 break; 809 case 'd': 810 dump(); 811 break; 812 case 'l': 813 symbol_lookup(); 814 break; 815 case 'r': 816 prregs(excp); /* print regs */ 817 break; 818 case 'e': 819 excprint(excp); 820 break; 821 case 'S': 822 super_regs(); 823 break; 824 case 't': 825 backtrace(excp); 826 break; 827 case 'f': 828 cacheflush(); 829 break; 830 case 's': 831 if (do_spu_cmd() == 0) 832 break; 833 if (do_step(excp)) 834 return cmd; 835 break; 836 case 'x': 837 case 'X': 838 return cmd; 839 case EOF: 840 printf(" <no input ...>\n"); 841 mdelay(2000); 842 return cmd; 843 case '?': 844 xmon_puts(help_string); 845 break; 846 case 'b': 847 bpt_cmds(); 848 break; 849 case 'C': 850 csum(); 851 break; 852 case 'c': 853 if (cpu_cmd()) 854 return 0; 855 break; 856 case 'z': 857 bootcmds(); 858 break; 859 case 'p': 860 proccall(); 861 break; 862 #ifdef CONFIG_PPC_STD_MMU 863 case 'u': 864 dump_segments(); 865 break; 866 #endif 867 #ifdef CONFIG_4xx 868 case 'u': 869 dump_tlb_44x(); 870 break; 871 #endif 872 default: 873 printf("Unrecognized command: "); 874 do { 875 if (' ' < cmd && cmd <= '~') 876 putchar(cmd); 877 else 878 printf("\\x%x", cmd); 879 cmd = inchar(); 880 } while (cmd != '\n'); 881 printf(" (type ? for help)\n"); 882 break; 883 } 884 } 885 } 886 887 /* 888 * Step a single instruction. 889 * Some instructions we emulate, others we execute with MSR_SE set. 890 */ 891 static int do_step(struct pt_regs *regs) 892 { 893 unsigned int instr; 894 int stepped; 895 896 /* check we are in 64-bit kernel mode, translation enabled */ 897 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) { 898 if (mread(regs->nip, &instr, 4) == 4) { 899 stepped = emulate_step(regs, instr); 900 if (stepped < 0) { 901 printf("Couldn't single-step %s instruction\n", 902 (IS_RFID(instr)? "rfid": "mtmsrd")); 903 return 0; 904 } 905 if (stepped > 0) { 906 regs->trap = 0xd00 | (regs->trap & 1); 907 printf("stepped to "); 908 xmon_print_symbol(regs->nip, " ", "\n"); 909 ppc_inst_dump(regs->nip, 1, 0); 910 return 0; 911 } 912 } 913 } 914 regs->msr |= MSR_SE; 915 return 1; 916 } 917 918 static void bootcmds(void) 919 { 920 int cmd; 921 922 cmd = inchar(); 923 if (cmd == 'r') 924 ppc_md.restart(NULL); 925 else if (cmd == 'h') 926 ppc_md.halt(); 927 else if (cmd == 'p') 928 ppc_md.power_off(); 929 } 930 931 static int cpu_cmd(void) 932 { 933 #ifdef CONFIG_SMP 934 unsigned long cpu; 935 int timeout; 936 int count; 937 938 if (!scanhex(&cpu)) { 939 /* print cpus waiting or in xmon */ 940 printf("cpus stopped:"); 941 count = 0; 942 for (cpu = 0; cpu < NR_CPUS; ++cpu) { 943 if (cpu_isset(cpu, cpus_in_xmon)) { 944 if (count == 0) 945 printf(" %x", cpu); 946 ++count; 947 } else { 948 if (count > 1) 949 printf("-%x", cpu - 1); 950 count = 0; 951 } 952 } 953 if (count > 1) 954 printf("-%x", NR_CPUS - 1); 955 printf("\n"); 956 return 0; 957 } 958 /* try to switch to cpu specified */ 959 if (!cpu_isset(cpu, cpus_in_xmon)) { 960 printf("cpu 0x%x isn't in xmon\n", cpu); 961 return 0; 962 } 963 xmon_taken = 0; 964 mb(); 965 xmon_owner = cpu; 966 timeout = 10000000; 967 while (!xmon_taken) { 968 if (--timeout == 0) { 969 if (test_and_set_bit(0, &xmon_taken)) 970 break; 971 /* take control back */ 972 mb(); 973 xmon_owner = smp_processor_id(); 974 printf("cpu %u didn't take control\n", cpu); 975 return 0; 976 } 977 barrier(); 978 } 979 return 1; 980 #else 981 return 0; 982 #endif /* CONFIG_SMP */ 983 } 984 985 static unsigned short fcstab[256] = { 986 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 987 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 988 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 989 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 990 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 991 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 992 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 993 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 994 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 995 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 996 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 997 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 998 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 999 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 1000 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 1001 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 1002 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 1003 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 1004 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 1005 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 1006 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 1007 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 1008 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 1009 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 1010 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 1011 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 1012 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 1013 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 1014 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 1015 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 1016 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 1017 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 1018 }; 1019 1020 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) 1021 1022 static void 1023 csum(void) 1024 { 1025 unsigned int i; 1026 unsigned short fcs; 1027 unsigned char v; 1028 1029 if (!scanhex(&adrs)) 1030 return; 1031 if (!scanhex(&ncsum)) 1032 return; 1033 fcs = 0xffff; 1034 for (i = 0; i < ncsum; ++i) { 1035 if (mread(adrs+i, &v, 1) == 0) { 1036 printf("csum stopped at %x\n", adrs+i); 1037 break; 1038 } 1039 fcs = FCS(fcs, v); 1040 } 1041 printf("%x\n", fcs); 1042 } 1043 1044 /* 1045 * Check if this is a suitable place to put a breakpoint. 1046 */ 1047 static long check_bp_loc(unsigned long addr) 1048 { 1049 unsigned int instr; 1050 1051 addr &= ~3; 1052 if (!is_kernel_addr(addr)) { 1053 printf("Breakpoints may only be placed at kernel addresses\n"); 1054 return 0; 1055 } 1056 if (!mread(addr, &instr, sizeof(instr))) { 1057 printf("Can't read instruction at address %lx\n", addr); 1058 return 0; 1059 } 1060 if (IS_MTMSRD(instr) || IS_RFID(instr)) { 1061 printf("Breakpoints may not be placed on mtmsrd or rfid " 1062 "instructions\n"); 1063 return 0; 1064 } 1065 return 1; 1066 } 1067 1068 static char *breakpoint_help_string = 1069 "Breakpoint command usage:\n" 1070 "b show breakpoints\n" 1071 "b <addr> [cnt] set breakpoint at given instr addr\n" 1072 "bc clear all breakpoints\n" 1073 "bc <n/addr> clear breakpoint number n or at addr\n" 1074 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n" 1075 "bd <addr> [cnt] set hardware data breakpoint\n" 1076 ""; 1077 1078 static void 1079 bpt_cmds(void) 1080 { 1081 int cmd; 1082 unsigned long a; 1083 int mode, i; 1084 struct bpt *bp; 1085 const char badaddr[] = "Only kernel addresses are permitted " 1086 "for breakpoints\n"; 1087 1088 cmd = inchar(); 1089 switch (cmd) { 1090 #ifndef CONFIG_8xx 1091 case 'd': /* bd - hardware data breakpoint */ 1092 mode = 7; 1093 cmd = inchar(); 1094 if (cmd == 'r') 1095 mode = 5; 1096 else if (cmd == 'w') 1097 mode = 6; 1098 else 1099 termch = cmd; 1100 dabr.address = 0; 1101 dabr.enabled = 0; 1102 if (scanhex(&dabr.address)) { 1103 if (!is_kernel_addr(dabr.address)) { 1104 printf(badaddr); 1105 break; 1106 } 1107 dabr.address &= ~7; 1108 dabr.enabled = mode | BP_DABR; 1109 } 1110 break; 1111 1112 case 'i': /* bi - hardware instr breakpoint */ 1113 if (!cpu_has_feature(CPU_FTR_IABR)) { 1114 printf("Hardware instruction breakpoint " 1115 "not supported on this cpu\n"); 1116 break; 1117 } 1118 if (iabr) { 1119 iabr->enabled &= ~(BP_IABR | BP_IABR_TE); 1120 iabr = NULL; 1121 } 1122 if (!scanhex(&a)) 1123 break; 1124 if (!check_bp_loc(a)) 1125 break; 1126 bp = new_breakpoint(a); 1127 if (bp != NULL) { 1128 bp->enabled |= BP_IABR | BP_IABR_TE; 1129 iabr = bp; 1130 } 1131 break; 1132 #endif 1133 1134 case 'c': 1135 if (!scanhex(&a)) { 1136 /* clear all breakpoints */ 1137 for (i = 0; i < NBPTS; ++i) 1138 bpts[i].enabled = 0; 1139 iabr = NULL; 1140 dabr.enabled = 0; 1141 printf("All breakpoints cleared\n"); 1142 break; 1143 } 1144 1145 if (a <= NBPTS && a >= 1) { 1146 /* assume a breakpoint number */ 1147 bp = &bpts[a-1]; /* bp nums are 1 based */ 1148 } else { 1149 /* assume a breakpoint address */ 1150 bp = at_breakpoint(a); 1151 if (bp == NULL) { 1152 printf("No breakpoint at %x\n", a); 1153 break; 1154 } 1155 } 1156 1157 printf("Cleared breakpoint %x (", BP_NUM(bp)); 1158 xmon_print_symbol(bp->address, " ", ")\n"); 1159 bp->enabled = 0; 1160 break; 1161 1162 default: 1163 termch = cmd; 1164 cmd = skipbl(); 1165 if (cmd == '?') { 1166 printf(breakpoint_help_string); 1167 break; 1168 } 1169 termch = cmd; 1170 if (!scanhex(&a)) { 1171 /* print all breakpoints */ 1172 printf(" type address\n"); 1173 if (dabr.enabled) { 1174 printf(" data "REG" [", dabr.address); 1175 if (dabr.enabled & 1) 1176 printf("r"); 1177 if (dabr.enabled & 2) 1178 printf("w"); 1179 printf("]\n"); 1180 } 1181 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) { 1182 if (!bp->enabled) 1183 continue; 1184 printf("%2x %s ", BP_NUM(bp), 1185 (bp->enabled & BP_IABR)? "inst": "trap"); 1186 xmon_print_symbol(bp->address, " ", "\n"); 1187 } 1188 break; 1189 } 1190 1191 if (!check_bp_loc(a)) 1192 break; 1193 bp = new_breakpoint(a); 1194 if (bp != NULL) 1195 bp->enabled |= BP_TRAP; 1196 break; 1197 } 1198 } 1199 1200 /* Very cheap human name for vector lookup. */ 1201 static 1202 const char *getvecname(unsigned long vec) 1203 { 1204 char *ret; 1205 1206 switch (vec) { 1207 case 0x100: ret = "(System Reset)"; break; 1208 case 0x200: ret = "(Machine Check)"; break; 1209 case 0x300: ret = "(Data Access)"; break; 1210 case 0x380: ret = "(Data SLB Access)"; break; 1211 case 0x400: ret = "(Instruction Access)"; break; 1212 case 0x480: ret = "(Instruction SLB Access)"; break; 1213 case 0x500: ret = "(Hardware Interrupt)"; break; 1214 case 0x600: ret = "(Alignment)"; break; 1215 case 0x700: ret = "(Program Check)"; break; 1216 case 0x800: ret = "(FPU Unavailable)"; break; 1217 case 0x900: ret = "(Decrementer)"; break; 1218 case 0xc00: ret = "(System Call)"; break; 1219 case 0xd00: ret = "(Single Step)"; break; 1220 case 0xf00: ret = "(Performance Monitor)"; break; 1221 case 0xf20: ret = "(Altivec Unavailable)"; break; 1222 case 0x1300: ret = "(Instruction Breakpoint)"; break; 1223 default: ret = ""; 1224 } 1225 return ret; 1226 } 1227 1228 static void get_function_bounds(unsigned long pc, unsigned long *startp, 1229 unsigned long *endp) 1230 { 1231 unsigned long size, offset; 1232 const char *name; 1233 1234 *startp = *endp = 0; 1235 if (pc == 0) 1236 return; 1237 if (setjmp(bus_error_jmp) == 0) { 1238 catch_memory_errors = 1; 1239 sync(); 1240 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr); 1241 if (name != NULL) { 1242 *startp = pc - offset; 1243 *endp = pc - offset + size; 1244 } 1245 sync(); 1246 } 1247 catch_memory_errors = 0; 1248 } 1249 1250 static int xmon_depth_to_print = 64; 1251 1252 #define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long)) 1253 #define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long)) 1254 1255 #ifdef __powerpc64__ 1256 #define REGS_OFFSET 0x70 1257 #else 1258 #define REGS_OFFSET 16 1259 #endif 1260 1261 static void xmon_show_stack(unsigned long sp, unsigned long lr, 1262 unsigned long pc) 1263 { 1264 unsigned long ip; 1265 unsigned long newsp; 1266 unsigned long marker; 1267 int count = 0; 1268 struct pt_regs regs; 1269 1270 do { 1271 if (sp < PAGE_OFFSET) { 1272 if (sp != 0) 1273 printf("SP (%lx) is in userspace\n", sp); 1274 break; 1275 } 1276 1277 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long)) 1278 || !mread(sp, &newsp, sizeof(unsigned long))) { 1279 printf("Couldn't read stack frame at %lx\n", sp); 1280 break; 1281 } 1282 1283 /* 1284 * For the first stack frame, try to work out if 1285 * LR and/or the saved LR value in the bottommost 1286 * stack frame are valid. 1287 */ 1288 if ((pc | lr) != 0) { 1289 unsigned long fnstart, fnend; 1290 unsigned long nextip; 1291 int printip = 1; 1292 1293 get_function_bounds(pc, &fnstart, &fnend); 1294 nextip = 0; 1295 if (newsp > sp) 1296 mread(newsp + LRSAVE_OFFSET, &nextip, 1297 sizeof(unsigned long)); 1298 if (lr == ip) { 1299 if (lr < PAGE_OFFSET 1300 || (fnstart <= lr && lr < fnend)) 1301 printip = 0; 1302 } else if (lr == nextip) { 1303 printip = 0; 1304 } else if (lr >= PAGE_OFFSET 1305 && !(fnstart <= lr && lr < fnend)) { 1306 printf("[link register ] "); 1307 xmon_print_symbol(lr, " ", "\n"); 1308 } 1309 if (printip) { 1310 printf("["REG"] ", sp); 1311 xmon_print_symbol(ip, " ", " (unreliable)\n"); 1312 } 1313 pc = lr = 0; 1314 1315 } else { 1316 printf("["REG"] ", sp); 1317 xmon_print_symbol(ip, " ", "\n"); 1318 } 1319 1320 /* Look for "regshere" marker to see if this is 1321 an exception frame. */ 1322 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long)) 1323 && marker == STACK_FRAME_REGS_MARKER) { 1324 if (mread(sp + REGS_OFFSET, ®s, sizeof(regs)) 1325 != sizeof(regs)) { 1326 printf("Couldn't read registers at %lx\n", 1327 sp + REGS_OFFSET); 1328 break; 1329 } 1330 printf("--- Exception: %lx %s at ", regs.trap, 1331 getvecname(TRAP(®s))); 1332 pc = regs.nip; 1333 lr = regs.link; 1334 xmon_print_symbol(pc, " ", "\n"); 1335 } 1336 1337 if (newsp == 0) 1338 break; 1339 1340 sp = newsp; 1341 } while (count++ < xmon_depth_to_print); 1342 } 1343 1344 static void backtrace(struct pt_regs *excp) 1345 { 1346 unsigned long sp; 1347 1348 if (scanhex(&sp)) 1349 xmon_show_stack(sp, 0, 0); 1350 else 1351 xmon_show_stack(excp->gpr[1], excp->link, excp->nip); 1352 scannl(); 1353 } 1354 1355 static void print_bug_trap(struct pt_regs *regs) 1356 { 1357 #ifdef CONFIG_BUG 1358 const struct bug_entry *bug; 1359 unsigned long addr; 1360 1361 if (regs->msr & MSR_PR) 1362 return; /* not in kernel */ 1363 addr = regs->nip; /* address of trap instruction */ 1364 if (addr < PAGE_OFFSET) 1365 return; 1366 bug = find_bug(regs->nip); 1367 if (bug == NULL) 1368 return; 1369 if (is_warning_bug(bug)) 1370 return; 1371 1372 #ifdef CONFIG_DEBUG_BUGVERBOSE 1373 printf("kernel BUG at %s:%u!\n", 1374 bug->file, bug->line); 1375 #else 1376 printf("kernel BUG at %p!\n", (void *)bug->bug_addr); 1377 #endif 1378 #endif /* CONFIG_BUG */ 1379 } 1380 1381 static void excprint(struct pt_regs *fp) 1382 { 1383 unsigned long trap; 1384 1385 #ifdef CONFIG_SMP 1386 printf("cpu 0x%x: ", smp_processor_id()); 1387 #endif /* CONFIG_SMP */ 1388 1389 trap = TRAP(fp); 1390 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp); 1391 printf(" pc: "); 1392 xmon_print_symbol(fp->nip, ": ", "\n"); 1393 1394 printf(" lr: ", fp->link); 1395 xmon_print_symbol(fp->link, ": ", "\n"); 1396 1397 printf(" sp: %lx\n", fp->gpr[1]); 1398 printf(" msr: %lx\n", fp->msr); 1399 1400 if (trap == 0x300 || trap == 0x380 || trap == 0x600) { 1401 printf(" dar: %lx\n", fp->dar); 1402 if (trap != 0x380) 1403 printf(" dsisr: %lx\n", fp->dsisr); 1404 } 1405 1406 printf(" current = 0x%lx\n", current); 1407 #ifdef CONFIG_PPC64 1408 printf(" paca = 0x%lx\n", get_paca()); 1409 #endif 1410 if (current) { 1411 printf(" pid = %ld, comm = %s\n", 1412 current->pid, current->comm); 1413 } 1414 1415 if (trap == 0x700) 1416 print_bug_trap(fp); 1417 } 1418 1419 static void prregs(struct pt_regs *fp) 1420 { 1421 int n, trap; 1422 unsigned long base; 1423 struct pt_regs regs; 1424 1425 if (scanhex(&base)) { 1426 if (setjmp(bus_error_jmp) == 0) { 1427 catch_memory_errors = 1; 1428 sync(); 1429 regs = *(struct pt_regs *)base; 1430 sync(); 1431 __delay(200); 1432 } else { 1433 catch_memory_errors = 0; 1434 printf("*** Error reading registers from "REG"\n", 1435 base); 1436 return; 1437 } 1438 catch_memory_errors = 0; 1439 fp = ®s; 1440 } 1441 1442 #ifdef CONFIG_PPC64 1443 if (FULL_REGS(fp)) { 1444 for (n = 0; n < 16; ++n) 1445 printf("R%.2ld = "REG" R%.2ld = "REG"\n", 1446 n, fp->gpr[n], n+16, fp->gpr[n+16]); 1447 } else { 1448 for (n = 0; n < 7; ++n) 1449 printf("R%.2ld = "REG" R%.2ld = "REG"\n", 1450 n, fp->gpr[n], n+7, fp->gpr[n+7]); 1451 } 1452 #else 1453 for (n = 0; n < 32; ++n) { 1454 printf("R%.2d = %.8x%s", n, fp->gpr[n], 1455 (n & 3) == 3? "\n": " "); 1456 if (n == 12 && !FULL_REGS(fp)) { 1457 printf("\n"); 1458 break; 1459 } 1460 } 1461 #endif 1462 printf("pc = "); 1463 xmon_print_symbol(fp->nip, " ", "\n"); 1464 printf("lr = "); 1465 xmon_print_symbol(fp->link, " ", "\n"); 1466 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr); 1467 printf("ctr = "REG" xer = "REG" trap = %4lx\n", 1468 fp->ctr, fp->xer, fp->trap); 1469 trap = TRAP(fp); 1470 if (trap == 0x300 || trap == 0x380 || trap == 0x600) 1471 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr); 1472 } 1473 1474 static void cacheflush(void) 1475 { 1476 int cmd; 1477 unsigned long nflush; 1478 1479 cmd = inchar(); 1480 if (cmd != 'i') 1481 termch = cmd; 1482 scanhex((void *)&adrs); 1483 if (termch != '\n') 1484 termch = 0; 1485 nflush = 1; 1486 scanhex(&nflush); 1487 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES; 1488 if (setjmp(bus_error_jmp) == 0) { 1489 catch_memory_errors = 1; 1490 sync(); 1491 1492 if (cmd != 'i') { 1493 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES) 1494 cflush((void *) adrs); 1495 } else { 1496 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES) 1497 cinval((void *) adrs); 1498 } 1499 sync(); 1500 /* wait a little while to see if we get a machine check */ 1501 __delay(200); 1502 } 1503 catch_memory_errors = 0; 1504 } 1505 1506 static unsigned long 1507 read_spr(int n) 1508 { 1509 unsigned int instrs[2]; 1510 unsigned long (*code)(void); 1511 unsigned long ret = -1UL; 1512 #ifdef CONFIG_PPC64 1513 unsigned long opd[3]; 1514 1515 opd[0] = (unsigned long)instrs; 1516 opd[1] = 0; 1517 opd[2] = 0; 1518 code = (unsigned long (*)(void)) opd; 1519 #else 1520 code = (unsigned long (*)(void)) instrs; 1521 #endif 1522 1523 /* mfspr r3,n; blr */ 1524 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); 1525 instrs[1] = 0x4e800020; 1526 store_inst(instrs); 1527 store_inst(instrs+1); 1528 1529 if (setjmp(bus_error_jmp) == 0) { 1530 catch_memory_errors = 1; 1531 sync(); 1532 1533 ret = code(); 1534 1535 sync(); 1536 /* wait a little while to see if we get a machine check */ 1537 __delay(200); 1538 n = size; 1539 } 1540 1541 return ret; 1542 } 1543 1544 static void 1545 write_spr(int n, unsigned long val) 1546 { 1547 unsigned int instrs[2]; 1548 unsigned long (*code)(unsigned long); 1549 #ifdef CONFIG_PPC64 1550 unsigned long opd[3]; 1551 1552 opd[0] = (unsigned long)instrs; 1553 opd[1] = 0; 1554 opd[2] = 0; 1555 code = (unsigned long (*)(unsigned long)) opd; 1556 #else 1557 code = (unsigned long (*)(unsigned long)) instrs; 1558 #endif 1559 1560 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); 1561 instrs[1] = 0x4e800020; 1562 store_inst(instrs); 1563 store_inst(instrs+1); 1564 1565 if (setjmp(bus_error_jmp) == 0) { 1566 catch_memory_errors = 1; 1567 sync(); 1568 1569 code(val); 1570 1571 sync(); 1572 /* wait a little while to see if we get a machine check */ 1573 __delay(200); 1574 n = size; 1575 } 1576 } 1577 1578 static unsigned long regno; 1579 extern char exc_prolog; 1580 extern char dec_exc; 1581 1582 static void super_regs(void) 1583 { 1584 int cmd; 1585 unsigned long val; 1586 1587 cmd = skipbl(); 1588 if (cmd == '\n') { 1589 unsigned long sp, toc; 1590 asm("mr %0,1" : "=r" (sp) :); 1591 asm("mr %0,2" : "=r" (toc) :); 1592 1593 printf("msr = "REG" sprg0= "REG"\n", 1594 mfmsr(), mfspr(SPRN_SPRG0)); 1595 printf("pvr = "REG" sprg1= "REG"\n", 1596 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); 1597 printf("dec = "REG" sprg2= "REG"\n", 1598 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2)); 1599 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); 1600 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); 1601 #ifdef CONFIG_PPC_ISERIES 1602 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 1603 struct paca_struct *ptrPaca; 1604 struct lppaca *ptrLpPaca; 1605 1606 /* Dump out relevant Paca data areas. */ 1607 printf("Paca: \n"); 1608 ptrPaca = get_paca(); 1609 1610 printf(" Local Processor Control Area (LpPaca): \n"); 1611 ptrLpPaca = ptrPaca->lppaca_ptr; 1612 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", 1613 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); 1614 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", 1615 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); 1616 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); 1617 } 1618 #endif 1619 1620 return; 1621 } 1622 1623 scanhex(®no); 1624 switch (cmd) { 1625 case 'w': 1626 val = read_spr(regno); 1627 scanhex(&val); 1628 write_spr(regno, val); 1629 /* fall through */ 1630 case 'r': 1631 printf("spr %lx = %lx\n", regno, read_spr(regno)); 1632 break; 1633 } 1634 scannl(); 1635 } 1636 1637 /* 1638 * Stuff for reading and writing memory safely 1639 */ 1640 static int 1641 mread(unsigned long adrs, void *buf, int size) 1642 { 1643 volatile int n; 1644 char *p, *q; 1645 1646 n = 0; 1647 if (setjmp(bus_error_jmp) == 0) { 1648 catch_memory_errors = 1; 1649 sync(); 1650 p = (char *)adrs; 1651 q = (char *)buf; 1652 switch (size) { 1653 case 2: 1654 *(u16 *)q = *(u16 *)p; 1655 break; 1656 case 4: 1657 *(u32 *)q = *(u32 *)p; 1658 break; 1659 case 8: 1660 *(u64 *)q = *(u64 *)p; 1661 break; 1662 default: 1663 for( ; n < size; ++n) { 1664 *q++ = *p++; 1665 sync(); 1666 } 1667 } 1668 sync(); 1669 /* wait a little while to see if we get a machine check */ 1670 __delay(200); 1671 n = size; 1672 } 1673 catch_memory_errors = 0; 1674 return n; 1675 } 1676 1677 static int 1678 mwrite(unsigned long adrs, void *buf, int size) 1679 { 1680 volatile int n; 1681 char *p, *q; 1682 1683 n = 0; 1684 if (setjmp(bus_error_jmp) == 0) { 1685 catch_memory_errors = 1; 1686 sync(); 1687 p = (char *) adrs; 1688 q = (char *) buf; 1689 switch (size) { 1690 case 2: 1691 *(u16 *)p = *(u16 *)q; 1692 break; 1693 case 4: 1694 *(u32 *)p = *(u32 *)q; 1695 break; 1696 case 8: 1697 *(u64 *)p = *(u64 *)q; 1698 break; 1699 default: 1700 for ( ; n < size; ++n) { 1701 *p++ = *q++; 1702 sync(); 1703 } 1704 } 1705 sync(); 1706 /* wait a little while to see if we get a machine check */ 1707 __delay(200); 1708 n = size; 1709 } else { 1710 printf("*** Error writing address %x\n", adrs + n); 1711 } 1712 catch_memory_errors = 0; 1713 return n; 1714 } 1715 1716 static int fault_type; 1717 static int fault_except; 1718 static char *fault_chars[] = { "--", "**", "##" }; 1719 1720 static int handle_fault(struct pt_regs *regs) 1721 { 1722 fault_except = TRAP(regs); 1723 switch (TRAP(regs)) { 1724 case 0x200: 1725 fault_type = 0; 1726 break; 1727 case 0x300: 1728 case 0x380: 1729 fault_type = 1; 1730 break; 1731 default: 1732 fault_type = 2; 1733 } 1734 1735 longjmp(bus_error_jmp, 1); 1736 1737 return 0; 1738 } 1739 1740 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t)) 1741 1742 static void 1743 byterev(unsigned char *val, int size) 1744 { 1745 int t; 1746 1747 switch (size) { 1748 case 2: 1749 SWAP(val[0], val[1], t); 1750 break; 1751 case 4: 1752 SWAP(val[0], val[3], t); 1753 SWAP(val[1], val[2], t); 1754 break; 1755 case 8: /* is there really any use for this? */ 1756 SWAP(val[0], val[7], t); 1757 SWAP(val[1], val[6], t); 1758 SWAP(val[2], val[5], t); 1759 SWAP(val[3], val[4], t); 1760 break; 1761 } 1762 } 1763 1764 static int brev; 1765 static int mnoread; 1766 1767 static char *memex_help_string = 1768 "Memory examine command usage:\n" 1769 "m [addr] [flags] examine/change memory\n" 1770 " addr is optional. will start where left off.\n" 1771 " flags may include chars from this set:\n" 1772 " b modify by bytes (default)\n" 1773 " w modify by words (2 byte)\n" 1774 " l modify by longs (4 byte)\n" 1775 " d modify by doubleword (8 byte)\n" 1776 " r toggle reverse byte order mode\n" 1777 " n do not read memory (for i/o spaces)\n" 1778 " . ok to read (default)\n" 1779 "NOTE: flags are saved as defaults\n" 1780 ""; 1781 1782 static char *memex_subcmd_help_string = 1783 "Memory examine subcommands:\n" 1784 " hexval write this val to current location\n" 1785 " 'string' write chars from string to this location\n" 1786 " ' increment address\n" 1787 " ^ decrement address\n" 1788 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n" 1789 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n" 1790 " ` clear no-read flag\n" 1791 " ; stay at this addr\n" 1792 " v change to byte mode\n" 1793 " w change to word (2 byte) mode\n" 1794 " l change to long (4 byte) mode\n" 1795 " u change to doubleword (8 byte) mode\n" 1796 " m addr change current addr\n" 1797 " n toggle no-read flag\n" 1798 " r toggle byte reverse flag\n" 1799 " < count back up count bytes\n" 1800 " > count skip forward count bytes\n" 1801 " x exit this mode\n" 1802 ""; 1803 1804 static void 1805 memex(void) 1806 { 1807 int cmd, inc, i, nslash; 1808 unsigned long n; 1809 unsigned char val[16]; 1810 1811 scanhex((void *)&adrs); 1812 cmd = skipbl(); 1813 if (cmd == '?') { 1814 printf(memex_help_string); 1815 return; 1816 } else { 1817 termch = cmd; 1818 } 1819 last_cmd = "m\n"; 1820 while ((cmd = skipbl()) != '\n') { 1821 switch( cmd ){ 1822 case 'b': size = 1; break; 1823 case 'w': size = 2; break; 1824 case 'l': size = 4; break; 1825 case 'd': size = 8; break; 1826 case 'r': brev = !brev; break; 1827 case 'n': mnoread = 1; break; 1828 case '.': mnoread = 0; break; 1829 } 1830 } 1831 if( size <= 0 ) 1832 size = 1; 1833 else if( size > 8 ) 1834 size = 8; 1835 for(;;){ 1836 if (!mnoread) 1837 n = mread(adrs, val, size); 1838 printf(REG"%c", adrs, brev? 'r': ' '); 1839 if (!mnoread) { 1840 if (brev) 1841 byterev(val, size); 1842 putchar(' '); 1843 for (i = 0; i < n; ++i) 1844 printf("%.2x", val[i]); 1845 for (; i < size; ++i) 1846 printf("%s", fault_chars[fault_type]); 1847 } 1848 putchar(' '); 1849 inc = size; 1850 nslash = 0; 1851 for(;;){ 1852 if( scanhex(&n) ){ 1853 for (i = 0; i < size; ++i) 1854 val[i] = n >> (i * 8); 1855 if (!brev) 1856 byterev(val, size); 1857 mwrite(adrs, val, size); 1858 inc = size; 1859 } 1860 cmd = skipbl(); 1861 if (cmd == '\n') 1862 break; 1863 inc = 0; 1864 switch (cmd) { 1865 case '\'': 1866 for(;;){ 1867 n = inchar(); 1868 if( n == '\\' ) 1869 n = bsesc(); 1870 else if( n == '\'' ) 1871 break; 1872 for (i = 0; i < size; ++i) 1873 val[i] = n >> (i * 8); 1874 if (!brev) 1875 byterev(val, size); 1876 mwrite(adrs, val, size); 1877 adrs += size; 1878 } 1879 adrs -= size; 1880 inc = size; 1881 break; 1882 case ',': 1883 adrs += size; 1884 break; 1885 case '.': 1886 mnoread = 0; 1887 break; 1888 case ';': 1889 break; 1890 case 'x': 1891 case EOF: 1892 scannl(); 1893 return; 1894 case 'b': 1895 case 'v': 1896 size = 1; 1897 break; 1898 case 'w': 1899 size = 2; 1900 break; 1901 case 'l': 1902 size = 4; 1903 break; 1904 case 'u': 1905 size = 8; 1906 break; 1907 case '^': 1908 adrs -= size; 1909 break; 1910 break; 1911 case '/': 1912 if (nslash > 0) 1913 adrs -= 1 << nslash; 1914 else 1915 nslash = 0; 1916 nslash += 4; 1917 adrs += 1 << nslash; 1918 break; 1919 case '\\': 1920 if (nslash < 0) 1921 adrs += 1 << -nslash; 1922 else 1923 nslash = 0; 1924 nslash -= 4; 1925 adrs -= 1 << -nslash; 1926 break; 1927 case 'm': 1928 scanhex((void *)&adrs); 1929 break; 1930 case 'n': 1931 mnoread = 1; 1932 break; 1933 case 'r': 1934 brev = !brev; 1935 break; 1936 case '<': 1937 n = size; 1938 scanhex(&n); 1939 adrs -= n; 1940 break; 1941 case '>': 1942 n = size; 1943 scanhex(&n); 1944 adrs += n; 1945 break; 1946 case '?': 1947 printf(memex_subcmd_help_string); 1948 break; 1949 } 1950 } 1951 adrs += inc; 1952 } 1953 } 1954 1955 static int 1956 bsesc(void) 1957 { 1958 int c; 1959 1960 c = inchar(); 1961 switch( c ){ 1962 case 'n': c = '\n'; break; 1963 case 'r': c = '\r'; break; 1964 case 'b': c = '\b'; break; 1965 case 't': c = '\t'; break; 1966 } 1967 return c; 1968 } 1969 1970 static void xmon_rawdump (unsigned long adrs, long ndump) 1971 { 1972 long n, m, r, nr; 1973 unsigned char temp[16]; 1974 1975 for (n = ndump; n > 0;) { 1976 r = n < 16? n: 16; 1977 nr = mread(adrs, temp, r); 1978 adrs += nr; 1979 for (m = 0; m < r; ++m) { 1980 if (m < nr) 1981 printf("%.2x", temp[m]); 1982 else 1983 printf("%s", fault_chars[fault_type]); 1984 } 1985 n -= r; 1986 if (nr < r) 1987 break; 1988 } 1989 printf("\n"); 1990 } 1991 1992 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ 1993 || ('a' <= (c) && (c) <= 'f') \ 1994 || ('A' <= (c) && (c) <= 'F')) 1995 static void 1996 dump(void) 1997 { 1998 int c; 1999 2000 c = inchar(); 2001 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') 2002 termch = c; 2003 scanhex((void *)&adrs); 2004 if (termch != '\n') 2005 termch = 0; 2006 if (c == 'i') { 2007 scanhex(&nidump); 2008 if (nidump == 0) 2009 nidump = 16; 2010 else if (nidump > MAX_DUMP) 2011 nidump = MAX_DUMP; 2012 adrs += ppc_inst_dump(adrs, nidump, 1); 2013 last_cmd = "di\n"; 2014 } else if (c == 'l') { 2015 dump_log_buf(); 2016 } else if (c == 'r') { 2017 scanhex(&ndump); 2018 if (ndump == 0) 2019 ndump = 64; 2020 xmon_rawdump(adrs, ndump); 2021 adrs += ndump; 2022 last_cmd = "dr\n"; 2023 } else { 2024 scanhex(&ndump); 2025 if (ndump == 0) 2026 ndump = 64; 2027 else if (ndump > MAX_DUMP) 2028 ndump = MAX_DUMP; 2029 prdump(adrs, ndump); 2030 adrs += ndump; 2031 last_cmd = "d\n"; 2032 } 2033 } 2034 2035 static void 2036 prdump(unsigned long adrs, long ndump) 2037 { 2038 long n, m, c, r, nr; 2039 unsigned char temp[16]; 2040 2041 for (n = ndump; n > 0;) { 2042 printf(REG, adrs); 2043 putchar(' '); 2044 r = n < 16? n: 16; 2045 nr = mread(adrs, temp, r); 2046 adrs += nr; 2047 for (m = 0; m < r; ++m) { 2048 if ((m & (sizeof(long) - 1)) == 0 && m > 0) 2049 putchar(' '); 2050 if (m < nr) 2051 printf("%.2x", temp[m]); 2052 else 2053 printf("%s", fault_chars[fault_type]); 2054 } 2055 for (; m < 16; ++m) { 2056 if ((m & (sizeof(long) - 1)) == 0) 2057 putchar(' '); 2058 printf(" "); 2059 } 2060 printf(" |"); 2061 for (m = 0; m < r; ++m) { 2062 if (m < nr) { 2063 c = temp[m]; 2064 putchar(' ' <= c && c <= '~'? c: '.'); 2065 } else 2066 putchar(' '); 2067 } 2068 n -= r; 2069 for (; m < 16; ++m) 2070 putchar(' '); 2071 printf("|\n"); 2072 if (nr < r) 2073 break; 2074 } 2075 } 2076 2077 typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr); 2078 2079 static int 2080 generic_inst_dump(unsigned long adr, long count, int praddr, 2081 instruction_dump_func dump_func) 2082 { 2083 int nr, dotted; 2084 unsigned long first_adr; 2085 unsigned long inst, last_inst = 0; 2086 unsigned char val[4]; 2087 2088 dotted = 0; 2089 for (first_adr = adr; count > 0; --count, adr += 4) { 2090 nr = mread(adr, val, 4); 2091 if (nr == 0) { 2092 if (praddr) { 2093 const char *x = fault_chars[fault_type]; 2094 printf(REG" %s%s%s%s\n", adr, x, x, x, x); 2095 } 2096 break; 2097 } 2098 inst = GETWORD(val); 2099 if (adr > first_adr && inst == last_inst) { 2100 if (!dotted) { 2101 printf(" ...\n"); 2102 dotted = 1; 2103 } 2104 continue; 2105 } 2106 dotted = 0; 2107 last_inst = inst; 2108 if (praddr) 2109 printf(REG" %.8x", adr, inst); 2110 printf("\t"); 2111 dump_func(inst, adr); 2112 printf("\n"); 2113 } 2114 return adr - first_adr; 2115 } 2116 2117 static int 2118 ppc_inst_dump(unsigned long adr, long count, int praddr) 2119 { 2120 return generic_inst_dump(adr, count, praddr, print_insn_powerpc); 2121 } 2122 2123 void 2124 print_address(unsigned long addr) 2125 { 2126 xmon_print_symbol(addr, "\t# ", ""); 2127 } 2128 2129 void 2130 dump_log_buf(void) 2131 { 2132 const unsigned long size = 128; 2133 unsigned long end, addr; 2134 unsigned char buf[size + 1]; 2135 2136 addr = 0; 2137 buf[size] = '\0'; 2138 2139 if (setjmp(bus_error_jmp) != 0) { 2140 printf("Unable to lookup symbol __log_buf!\n"); 2141 return; 2142 } 2143 2144 catch_memory_errors = 1; 2145 sync(); 2146 addr = kallsyms_lookup_name("__log_buf"); 2147 2148 if (! addr) 2149 printf("Symbol __log_buf not found!\n"); 2150 else { 2151 end = addr + (1 << CONFIG_LOG_BUF_SHIFT); 2152 while (addr < end) { 2153 if (! mread(addr, buf, size)) { 2154 printf("Can't read memory at address 0x%lx\n", addr); 2155 break; 2156 } 2157 2158 printf("%s", buf); 2159 2160 if (strlen(buf) < size) 2161 break; 2162 2163 addr += size; 2164 } 2165 } 2166 2167 sync(); 2168 /* wait a little while to see if we get a machine check */ 2169 __delay(200); 2170 catch_memory_errors = 0; 2171 } 2172 2173 /* 2174 * Memory operations - move, set, print differences 2175 */ 2176 static unsigned long mdest; /* destination address */ 2177 static unsigned long msrc; /* source address */ 2178 static unsigned long mval; /* byte value to set memory to */ 2179 static unsigned long mcount; /* # bytes to affect */ 2180 static unsigned long mdiffs; /* max # differences to print */ 2181 2182 static void 2183 memops(int cmd) 2184 { 2185 scanhex((void *)&mdest); 2186 if( termch != '\n' ) 2187 termch = 0; 2188 scanhex((void *)(cmd == 's'? &mval: &msrc)); 2189 if( termch != '\n' ) 2190 termch = 0; 2191 scanhex((void *)&mcount); 2192 switch( cmd ){ 2193 case 'm': 2194 memmove((void *)mdest, (void *)msrc, mcount); 2195 break; 2196 case 's': 2197 memset((void *)mdest, mval, mcount); 2198 break; 2199 case 'd': 2200 if( termch != '\n' ) 2201 termch = 0; 2202 scanhex((void *)&mdiffs); 2203 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs); 2204 break; 2205 } 2206 } 2207 2208 static void 2209 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr) 2210 { 2211 unsigned n, prt; 2212 2213 prt = 0; 2214 for( n = nb; n > 0; --n ) 2215 if( *p1++ != *p2++ ) 2216 if( ++prt <= maxpr ) 2217 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1, 2218 p1[-1], p2 - 1, p2[-1]); 2219 if( prt > maxpr ) 2220 printf("Total of %d differences\n", prt); 2221 } 2222 2223 static unsigned mend; 2224 static unsigned mask; 2225 2226 static void 2227 memlocate(void) 2228 { 2229 unsigned a, n; 2230 unsigned char val[4]; 2231 2232 last_cmd = "ml"; 2233 scanhex((void *)&mdest); 2234 if (termch != '\n') { 2235 termch = 0; 2236 scanhex((void *)&mend); 2237 if (termch != '\n') { 2238 termch = 0; 2239 scanhex((void *)&mval); 2240 mask = ~0; 2241 if (termch != '\n') termch = 0; 2242 scanhex((void *)&mask); 2243 } 2244 } 2245 n = 0; 2246 for (a = mdest; a < mend; a += 4) { 2247 if (mread(a, val, 4) == 4 2248 && ((GETWORD(val) ^ mval) & mask) == 0) { 2249 printf("%.16x: %.16x\n", a, GETWORD(val)); 2250 if (++n >= 10) 2251 break; 2252 } 2253 } 2254 } 2255 2256 static unsigned long mskip = 0x1000; 2257 static unsigned long mlim = 0xffffffff; 2258 2259 static void 2260 memzcan(void) 2261 { 2262 unsigned char v; 2263 unsigned a; 2264 int ok, ook; 2265 2266 scanhex(&mdest); 2267 if (termch != '\n') termch = 0; 2268 scanhex(&mskip); 2269 if (termch != '\n') termch = 0; 2270 scanhex(&mlim); 2271 ook = 0; 2272 for (a = mdest; a < mlim; a += mskip) { 2273 ok = mread(a, &v, 1); 2274 if (ok && !ook) { 2275 printf("%.8x .. ", a); 2276 } else if (!ok && ook) 2277 printf("%.8x\n", a - mskip); 2278 ook = ok; 2279 if (a + mskip < a) 2280 break; 2281 } 2282 if (ook) 2283 printf("%.8x\n", a - mskip); 2284 } 2285 2286 static void proccall(void) 2287 { 2288 unsigned long args[8]; 2289 unsigned long ret; 2290 int i; 2291 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long, 2292 unsigned long, unsigned long, unsigned long, 2293 unsigned long, unsigned long, unsigned long); 2294 callfunc_t func; 2295 2296 if (!scanhex(&adrs)) 2297 return; 2298 if (termch != '\n') 2299 termch = 0; 2300 for (i = 0; i < 8; ++i) 2301 args[i] = 0; 2302 for (i = 0; i < 8; ++i) { 2303 if (!scanhex(&args[i]) || termch == '\n') 2304 break; 2305 termch = 0; 2306 } 2307 func = (callfunc_t) adrs; 2308 ret = 0; 2309 if (setjmp(bus_error_jmp) == 0) { 2310 catch_memory_errors = 1; 2311 sync(); 2312 ret = func(args[0], args[1], args[2], args[3], 2313 args[4], args[5], args[6], args[7]); 2314 sync(); 2315 printf("return value is %x\n", ret); 2316 } else { 2317 printf("*** %x exception occurred\n", fault_except); 2318 } 2319 catch_memory_errors = 0; 2320 } 2321 2322 /* Input scanning routines */ 2323 int 2324 skipbl(void) 2325 { 2326 int c; 2327 2328 if( termch != 0 ){ 2329 c = termch; 2330 termch = 0; 2331 } else 2332 c = inchar(); 2333 while( c == ' ' || c == '\t' ) 2334 c = inchar(); 2335 return c; 2336 } 2337 2338 #define N_PTREGS 44 2339 static char *regnames[N_PTREGS] = { 2340 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 2341 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 2342 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 2343 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 2344 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", 2345 #ifdef CONFIG_PPC64 2346 "softe", 2347 #else 2348 "mq", 2349 #endif 2350 "trap", "dar", "dsisr", "res" 2351 }; 2352 2353 int 2354 scanhex(unsigned long *vp) 2355 { 2356 int c, d; 2357 unsigned long v; 2358 2359 c = skipbl(); 2360 if (c == '%') { 2361 /* parse register name */ 2362 char regname[8]; 2363 int i; 2364 2365 for (i = 0; i < sizeof(regname) - 1; ++i) { 2366 c = inchar(); 2367 if (!isalnum(c)) { 2368 termch = c; 2369 break; 2370 } 2371 regname[i] = c; 2372 } 2373 regname[i] = 0; 2374 for (i = 0; i < N_PTREGS; ++i) { 2375 if (strcmp(regnames[i], regname) == 0) { 2376 if (xmon_regs == NULL) { 2377 printf("regs not available\n"); 2378 return 0; 2379 } 2380 *vp = ((unsigned long *)xmon_regs)[i]; 2381 return 1; 2382 } 2383 } 2384 printf("invalid register name '%%%s'\n", regname); 2385 return 0; 2386 } 2387 2388 /* skip leading "0x" if any */ 2389 2390 if (c == '0') { 2391 c = inchar(); 2392 if (c == 'x') { 2393 c = inchar(); 2394 } else { 2395 d = hexdigit(c); 2396 if (d == EOF) { 2397 termch = c; 2398 *vp = 0; 2399 return 1; 2400 } 2401 } 2402 } else if (c == '$') { 2403 int i; 2404 for (i=0; i<63; i++) { 2405 c = inchar(); 2406 if (isspace(c)) { 2407 termch = c; 2408 break; 2409 } 2410 tmpstr[i] = c; 2411 } 2412 tmpstr[i++] = 0; 2413 *vp = 0; 2414 if (setjmp(bus_error_jmp) == 0) { 2415 catch_memory_errors = 1; 2416 sync(); 2417 *vp = kallsyms_lookup_name(tmpstr); 2418 sync(); 2419 } 2420 catch_memory_errors = 0; 2421 if (!(*vp)) { 2422 printf("unknown symbol '%s'\n", tmpstr); 2423 return 0; 2424 } 2425 return 1; 2426 } 2427 2428 d = hexdigit(c); 2429 if (d == EOF) { 2430 termch = c; 2431 return 0; 2432 } 2433 v = 0; 2434 do { 2435 v = (v << 4) + d; 2436 c = inchar(); 2437 d = hexdigit(c); 2438 } while (d != EOF); 2439 termch = c; 2440 *vp = v; 2441 return 1; 2442 } 2443 2444 static void 2445 scannl(void) 2446 { 2447 int c; 2448 2449 c = termch; 2450 termch = 0; 2451 while( c != '\n' ) 2452 c = inchar(); 2453 } 2454 2455 static int hexdigit(int c) 2456 { 2457 if( '0' <= c && c <= '9' ) 2458 return c - '0'; 2459 if( 'A' <= c && c <= 'F' ) 2460 return c - ('A' - 10); 2461 if( 'a' <= c && c <= 'f' ) 2462 return c - ('a' - 10); 2463 return EOF; 2464 } 2465 2466 void 2467 getstring(char *s, int size) 2468 { 2469 int c; 2470 2471 c = skipbl(); 2472 do { 2473 if( size > 1 ){ 2474 *s++ = c; 2475 --size; 2476 } 2477 c = inchar(); 2478 } while( c != ' ' && c != '\t' && c != '\n' ); 2479 termch = c; 2480 *s = 0; 2481 } 2482 2483 static char line[256]; 2484 static char *lineptr; 2485 2486 static void 2487 flush_input(void) 2488 { 2489 lineptr = NULL; 2490 } 2491 2492 static int 2493 inchar(void) 2494 { 2495 if (lineptr == NULL || *lineptr == 0) { 2496 if (xmon_gets(line, sizeof(line)) == NULL) { 2497 lineptr = NULL; 2498 return EOF; 2499 } 2500 lineptr = line; 2501 } 2502 return *lineptr++; 2503 } 2504 2505 static void 2506 take_input(char *str) 2507 { 2508 lineptr = str; 2509 } 2510 2511 2512 static void 2513 symbol_lookup(void) 2514 { 2515 int type = inchar(); 2516 unsigned long addr; 2517 static char tmp[64]; 2518 2519 switch (type) { 2520 case 'a': 2521 if (scanhex(&addr)) 2522 xmon_print_symbol(addr, ": ", "\n"); 2523 termch = 0; 2524 break; 2525 case 's': 2526 getstring(tmp, 64); 2527 if (setjmp(bus_error_jmp) == 0) { 2528 catch_memory_errors = 1; 2529 sync(); 2530 addr = kallsyms_lookup_name(tmp); 2531 if (addr) 2532 printf("%s: %lx\n", tmp, addr); 2533 else 2534 printf("Symbol '%s' not found.\n", tmp); 2535 sync(); 2536 } 2537 catch_memory_errors = 0; 2538 termch = 0; 2539 break; 2540 } 2541 } 2542 2543 2544 /* Print an address in numeric and symbolic form (if possible) */ 2545 static void xmon_print_symbol(unsigned long address, const char *mid, 2546 const char *after) 2547 { 2548 char *modname; 2549 const char *name = NULL; 2550 unsigned long offset, size; 2551 2552 printf(REG, address); 2553 if (setjmp(bus_error_jmp) == 0) { 2554 catch_memory_errors = 1; 2555 sync(); 2556 name = kallsyms_lookup(address, &size, &offset, &modname, 2557 tmpstr); 2558 sync(); 2559 /* wait a little while to see if we get a machine check */ 2560 __delay(200); 2561 } 2562 2563 catch_memory_errors = 0; 2564 2565 if (name) { 2566 printf("%s%s+%#lx/%#lx", mid, name, offset, size); 2567 if (modname) 2568 printf(" [%s]", modname); 2569 } 2570 printf("%s", after); 2571 } 2572 2573 #ifdef CONFIG_PPC64 2574 static void dump_slb(void) 2575 { 2576 int i; 2577 unsigned long esid,vsid,valid; 2578 unsigned long llp; 2579 2580 printf("SLB contents of cpu %x\n", smp_processor_id()); 2581 2582 for (i = 0; i < mmu_slb_size; i++) { 2583 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i)); 2584 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i)); 2585 valid = (esid & SLB_ESID_V); 2586 if (valid | esid | vsid) { 2587 printf("%02d %016lx %016lx", i, esid, vsid); 2588 if (valid) { 2589 llp = vsid & SLB_VSID_LLP; 2590 if (vsid & SLB_VSID_B_1T) { 2591 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n", 2592 GET_ESID_1T(esid), 2593 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T, 2594 llp); 2595 } else { 2596 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n", 2597 GET_ESID(esid), 2598 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT, 2599 llp); 2600 } 2601 } else 2602 printf("\n"); 2603 } 2604 } 2605 } 2606 2607 static void dump_stab(void) 2608 { 2609 int i; 2610 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr; 2611 2612 printf("Segment table contents of cpu %x\n", smp_processor_id()); 2613 2614 for (i = 0; i < PAGE_SIZE/16; i++) { 2615 unsigned long a, b; 2616 2617 a = *tmp++; 2618 b = *tmp++; 2619 2620 if (a || b) { 2621 printf("%03d %016lx ", i, a); 2622 printf("%016lx\n", b); 2623 } 2624 } 2625 } 2626 2627 void dump_segments(void) 2628 { 2629 if (cpu_has_feature(CPU_FTR_SLB)) 2630 dump_slb(); 2631 else 2632 dump_stab(); 2633 } 2634 #endif 2635 2636 #ifdef CONFIG_PPC_STD_MMU_32 2637 void dump_segments(void) 2638 { 2639 int i; 2640 2641 printf("sr0-15 ="); 2642 for (i = 0; i < 16; ++i) 2643 printf(" %x", mfsrin(i)); 2644 printf("\n"); 2645 } 2646 #endif 2647 2648 #ifdef CONFIG_44x 2649 static void dump_tlb_44x(void) 2650 { 2651 int i; 2652 2653 for (i = 0; i < PPC44x_TLB_SIZE; i++) { 2654 unsigned long w0,w1,w2; 2655 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i)); 2656 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i)); 2657 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i)); 2658 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2); 2659 if (w0 & PPC44x_TLB_VALID) { 2660 printf("V %08x -> %01x%08x %c%c%c%c%c", 2661 w0 & PPC44x_TLB_EPN_MASK, 2662 w1 & PPC44x_TLB_ERPN_MASK, 2663 w1 & PPC44x_TLB_RPN_MASK, 2664 (w2 & PPC44x_TLB_W) ? 'W' : 'w', 2665 (w2 & PPC44x_TLB_I) ? 'I' : 'i', 2666 (w2 & PPC44x_TLB_M) ? 'M' : 'm', 2667 (w2 & PPC44x_TLB_G) ? 'G' : 'g', 2668 (w2 & PPC44x_TLB_E) ? 'E' : 'e'); 2669 } 2670 printf("\n"); 2671 } 2672 } 2673 #endif /* CONFIG_44x */ 2674 2675 static void xmon_init(int enable) 2676 { 2677 #ifdef CONFIG_PPC_ISERIES 2678 if (firmware_has_feature(FW_FEATURE_ISERIES)) 2679 return; 2680 #endif 2681 if (enable) { 2682 __debugger = xmon; 2683 __debugger_ipi = xmon_ipi; 2684 __debugger_bpt = xmon_bpt; 2685 __debugger_sstep = xmon_sstep; 2686 __debugger_iabr_match = xmon_iabr_match; 2687 __debugger_dabr_match = xmon_dabr_match; 2688 __debugger_fault_handler = xmon_fault_handler; 2689 } else { 2690 __debugger = NULL; 2691 __debugger_ipi = NULL; 2692 __debugger_bpt = NULL; 2693 __debugger_sstep = NULL; 2694 __debugger_iabr_match = NULL; 2695 __debugger_dabr_match = NULL; 2696 __debugger_fault_handler = NULL; 2697 } 2698 xmon_map_scc(); 2699 } 2700 2701 #ifdef CONFIG_MAGIC_SYSRQ 2702 static void sysrq_handle_xmon(int key, struct tty_struct *tty) 2703 { 2704 /* ensure xmon is enabled */ 2705 xmon_init(1); 2706 debugger(get_irq_regs()); 2707 } 2708 2709 static struct sysrq_key_op sysrq_xmon_op = 2710 { 2711 .handler = sysrq_handle_xmon, 2712 .help_msg = "Xmon", 2713 .action_msg = "Entering xmon", 2714 }; 2715 2716 static int __init setup_xmon_sysrq(void) 2717 { 2718 #ifdef CONFIG_PPC_ISERIES 2719 if (firmware_has_feature(FW_FEATURE_ISERIES)) 2720 return 0; 2721 #endif 2722 register_sysrq_key('x', &sysrq_xmon_op); 2723 return 0; 2724 } 2725 __initcall(setup_xmon_sysrq); 2726 #endif /* CONFIG_MAGIC_SYSRQ */ 2727 2728 static int __initdata xmon_early, xmon_off; 2729 2730 static int __init early_parse_xmon(char *p) 2731 { 2732 if (!p || strncmp(p, "early", 5) == 0) { 2733 /* just "xmon" is equivalent to "xmon=early" */ 2734 xmon_init(1); 2735 xmon_early = 1; 2736 } else if (strncmp(p, "on", 2) == 0) 2737 xmon_init(1); 2738 else if (strncmp(p, "off", 3) == 0) 2739 xmon_off = 1; 2740 else if (strncmp(p, "nobt", 4) == 0) 2741 xmon_no_auto_backtrace = 1; 2742 else 2743 return 1; 2744 2745 return 0; 2746 } 2747 early_param("xmon", early_parse_xmon); 2748 2749 void __init xmon_setup(void) 2750 { 2751 #ifdef CONFIG_XMON_DEFAULT 2752 if (!xmon_off) 2753 xmon_init(1); 2754 #endif 2755 if (xmon_early) 2756 debugger(NULL); 2757 } 2758 2759 #ifdef CONFIG_SPU_BASE 2760 2761 struct spu_info { 2762 struct spu *spu; 2763 u64 saved_mfc_sr1_RW; 2764 u32 saved_spu_runcntl_RW; 2765 unsigned long dump_addr; 2766 u8 stopped_ok; 2767 }; 2768 2769 #define XMON_NUM_SPUS 16 /* Enough for current hardware */ 2770 2771 static struct spu_info spu_info[XMON_NUM_SPUS]; 2772 2773 void xmon_register_spus(struct list_head *list) 2774 { 2775 struct spu *spu; 2776 2777 list_for_each_entry(spu, list, full_list) { 2778 if (spu->number >= XMON_NUM_SPUS) { 2779 WARN_ON(1); 2780 continue; 2781 } 2782 2783 spu_info[spu->number].spu = spu; 2784 spu_info[spu->number].stopped_ok = 0; 2785 spu_info[spu->number].dump_addr = (unsigned long) 2786 spu_info[spu->number].spu->local_store; 2787 } 2788 } 2789 2790 static void stop_spus(void) 2791 { 2792 struct spu *spu; 2793 int i; 2794 u64 tmp; 2795 2796 for (i = 0; i < XMON_NUM_SPUS; i++) { 2797 if (!spu_info[i].spu) 2798 continue; 2799 2800 if (setjmp(bus_error_jmp) == 0) { 2801 catch_memory_errors = 1; 2802 sync(); 2803 2804 spu = spu_info[i].spu; 2805 2806 spu_info[i].saved_spu_runcntl_RW = 2807 in_be32(&spu->problem->spu_runcntl_RW); 2808 2809 tmp = spu_mfc_sr1_get(spu); 2810 spu_info[i].saved_mfc_sr1_RW = tmp; 2811 2812 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; 2813 spu_mfc_sr1_set(spu, tmp); 2814 2815 sync(); 2816 __delay(200); 2817 2818 spu_info[i].stopped_ok = 1; 2819 2820 printf("Stopped spu %.2d (was %s)\n", i, 2821 spu_info[i].saved_spu_runcntl_RW ? 2822 "running" : "stopped"); 2823 } else { 2824 catch_memory_errors = 0; 2825 printf("*** Error stopping spu %.2d\n", i); 2826 } 2827 catch_memory_errors = 0; 2828 } 2829 } 2830 2831 static void restart_spus(void) 2832 { 2833 struct spu *spu; 2834 int i; 2835 2836 for (i = 0; i < XMON_NUM_SPUS; i++) { 2837 if (!spu_info[i].spu) 2838 continue; 2839 2840 if (!spu_info[i].stopped_ok) { 2841 printf("*** Error, spu %d was not successfully stopped" 2842 ", not restarting\n", i); 2843 continue; 2844 } 2845 2846 if (setjmp(bus_error_jmp) == 0) { 2847 catch_memory_errors = 1; 2848 sync(); 2849 2850 spu = spu_info[i].spu; 2851 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW); 2852 out_be32(&spu->problem->spu_runcntl_RW, 2853 spu_info[i].saved_spu_runcntl_RW); 2854 2855 sync(); 2856 __delay(200); 2857 2858 printf("Restarted spu %.2d\n", i); 2859 } else { 2860 catch_memory_errors = 0; 2861 printf("*** Error restarting spu %.2d\n", i); 2862 } 2863 catch_memory_errors = 0; 2864 } 2865 } 2866 2867 #define DUMP_WIDTH 23 2868 #define DUMP_VALUE(format, field, value) \ 2869 do { \ 2870 if (setjmp(bus_error_jmp) == 0) { \ 2871 catch_memory_errors = 1; \ 2872 sync(); \ 2873 printf(" %-*s = "format"\n", DUMP_WIDTH, \ 2874 #field, value); \ 2875 sync(); \ 2876 __delay(200); \ 2877 } else { \ 2878 catch_memory_errors = 0; \ 2879 printf(" %-*s = *** Error reading field.\n", \ 2880 DUMP_WIDTH, #field); \ 2881 } \ 2882 catch_memory_errors = 0; \ 2883 } while (0) 2884 2885 #define DUMP_FIELD(obj, format, field) \ 2886 DUMP_VALUE(format, field, obj->field) 2887 2888 static void dump_spu_fields(struct spu *spu) 2889 { 2890 printf("Dumping spu fields at address %p:\n", spu); 2891 2892 DUMP_FIELD(spu, "0x%x", number); 2893 DUMP_FIELD(spu, "%s", name); 2894 DUMP_FIELD(spu, "0x%lx", local_store_phys); 2895 DUMP_FIELD(spu, "0x%p", local_store); 2896 DUMP_FIELD(spu, "0x%lx", ls_size); 2897 DUMP_FIELD(spu, "0x%x", node); 2898 DUMP_FIELD(spu, "0x%lx", flags); 2899 DUMP_FIELD(spu, "%d", class_0_pending); 2900 DUMP_FIELD(spu, "0x%lx", class_0_dar); 2901 DUMP_FIELD(spu, "0x%lx", class_1_dar); 2902 DUMP_FIELD(spu, "0x%lx", class_1_dsisr); 2903 DUMP_FIELD(spu, "0x%lx", irqs[0]); 2904 DUMP_FIELD(spu, "0x%lx", irqs[1]); 2905 DUMP_FIELD(spu, "0x%lx", irqs[2]); 2906 DUMP_FIELD(spu, "0x%x", slb_replace); 2907 DUMP_FIELD(spu, "%d", pid); 2908 DUMP_FIELD(spu, "0x%p", mm); 2909 DUMP_FIELD(spu, "0x%p", ctx); 2910 DUMP_FIELD(spu, "0x%p", rq); 2911 DUMP_FIELD(spu, "0x%p", timestamp); 2912 DUMP_FIELD(spu, "0x%lx", problem_phys); 2913 DUMP_FIELD(spu, "0x%p", problem); 2914 DUMP_VALUE("0x%x", problem->spu_runcntl_RW, 2915 in_be32(&spu->problem->spu_runcntl_RW)); 2916 DUMP_VALUE("0x%x", problem->spu_status_R, 2917 in_be32(&spu->problem->spu_status_R)); 2918 DUMP_VALUE("0x%x", problem->spu_npc_RW, 2919 in_be32(&spu->problem->spu_npc_RW)); 2920 DUMP_FIELD(spu, "0x%p", priv2); 2921 DUMP_FIELD(spu, "0x%p", pdata); 2922 } 2923 2924 int 2925 spu_inst_dump(unsigned long adr, long count, int praddr) 2926 { 2927 return generic_inst_dump(adr, count, praddr, print_insn_spu); 2928 } 2929 2930 static void dump_spu_ls(unsigned long num, int subcmd) 2931 { 2932 unsigned long offset, addr, ls_addr; 2933 2934 if (setjmp(bus_error_jmp) == 0) { 2935 catch_memory_errors = 1; 2936 sync(); 2937 ls_addr = (unsigned long)spu_info[num].spu->local_store; 2938 sync(); 2939 __delay(200); 2940 } else { 2941 catch_memory_errors = 0; 2942 printf("*** Error: accessing spu info for spu %d\n", num); 2943 return; 2944 } 2945 catch_memory_errors = 0; 2946 2947 if (scanhex(&offset)) 2948 addr = ls_addr + offset; 2949 else 2950 addr = spu_info[num].dump_addr; 2951 2952 if (addr >= ls_addr + LS_SIZE) { 2953 printf("*** Error: address outside of local store\n"); 2954 return; 2955 } 2956 2957 switch (subcmd) { 2958 case 'i': 2959 addr += spu_inst_dump(addr, 16, 1); 2960 last_cmd = "sdi\n"; 2961 break; 2962 default: 2963 prdump(addr, 64); 2964 addr += 64; 2965 last_cmd = "sd\n"; 2966 break; 2967 } 2968 2969 spu_info[num].dump_addr = addr; 2970 } 2971 2972 static int do_spu_cmd(void) 2973 { 2974 static unsigned long num = 0; 2975 int cmd, subcmd = 0; 2976 2977 cmd = inchar(); 2978 switch (cmd) { 2979 case 's': 2980 stop_spus(); 2981 break; 2982 case 'r': 2983 restart_spus(); 2984 break; 2985 case 'd': 2986 subcmd = inchar(); 2987 if (isxdigit(subcmd) || subcmd == '\n') 2988 termch = subcmd; 2989 case 'f': 2990 scanhex(&num); 2991 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) { 2992 printf("*** Error: invalid spu number\n"); 2993 return 0; 2994 } 2995 2996 switch (cmd) { 2997 case 'f': 2998 dump_spu_fields(spu_info[num].spu); 2999 break; 3000 default: 3001 dump_spu_ls(num, subcmd); 3002 break; 3003 } 3004 3005 break; 3006 default: 3007 return -1; 3008 } 3009 3010 return 0; 3011 } 3012 #else /* ! CONFIG_SPU_BASE */ 3013 static int do_spu_cmd(void) 3014 { 3015 return -1; 3016 } 3017 #endif 3018