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