xmon.c (94484B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Routines providing a simple monitor for use on the PowerMac. 4 * 5 * Copyright (C) 1996-2005 Paul Mackerras. 6 * Copyright (C) 2001 PPC64 Team, IBM Corp 7 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp 8 */ 9 10#include <linux/kernel.h> 11#include <linux/errno.h> 12#include <linux/sched/signal.h> 13#include <linux/smp.h> 14#include <linux/mm.h> 15#include <linux/reboot.h> 16#include <linux/delay.h> 17#include <linux/kallsyms.h> 18#include <linux/kmsg_dump.h> 19#include <linux/cpumask.h> 20#include <linux/export.h> 21#include <linux/sysrq.h> 22#include <linux/interrupt.h> 23#include <linux/irq.h> 24#include <linux/bug.h> 25#include <linux/nmi.h> 26#include <linux/ctype.h> 27#include <linux/highmem.h> 28#include <linux/security.h> 29#include <linux/debugfs.h> 30 31#include <asm/ptrace.h> 32#include <asm/smp.h> 33#include <asm/string.h> 34#include <asm/machdep.h> 35#include <asm/xmon.h> 36#include <asm/processor.h> 37#include <asm/mmu.h> 38#include <asm/mmu_context.h> 39#include <asm/plpar_wrappers.h> 40#include <asm/cputable.h> 41#include <asm/rtas.h> 42#include <asm/sstep.h> 43#include <asm/irq_regs.h> 44#include <asm/spu.h> 45#include <asm/spu_priv1.h> 46#include <asm/setjmp.h> 47#include <asm/reg.h> 48#include <asm/debug.h> 49#include <asm/hw_breakpoint.h> 50#include <asm/xive.h> 51#include <asm/opal.h> 52#include <asm/firmware.h> 53#include <asm/code-patching.h> 54#include <asm/sections.h> 55#include <asm/inst.h> 56#include <asm/interrupt.h> 57 58#ifdef CONFIG_PPC64 59#include <asm/hvcall.h> 60#include <asm/paca.h> 61#endif 62 63#include "nonstdio.h" 64#include "dis-asm.h" 65#include "xmon_bpts.h" 66 67#ifdef CONFIG_SMP 68static cpumask_t cpus_in_xmon = CPU_MASK_NONE; 69static unsigned long xmon_taken = 1; 70static int xmon_owner; 71static int xmon_gate; 72static int xmon_batch; 73static unsigned long xmon_batch_start_cpu; 74static cpumask_t xmon_batch_cpus = CPU_MASK_NONE; 75#else 76#define xmon_owner 0 77#endif /* CONFIG_SMP */ 78 79#ifdef CONFIG_PPC_PSERIES 80static int set_indicator_token = RTAS_UNKNOWN_SERVICE; 81#endif 82static unsigned long in_xmon __read_mostly = 0; 83static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT); 84static bool xmon_is_ro = IS_ENABLED(CONFIG_XMON_DEFAULT_RO_MODE); 85 86static unsigned long adrs; 87static int size = 1; 88#define MAX_DUMP (64 * 1024) 89static unsigned long ndump = 64; 90#define MAX_IDUMP (MAX_DUMP >> 2) 91static unsigned long nidump = 16; 92static unsigned long ncsum = 4096; 93static int termch; 94static char tmpstr[128]; 95static int tracing_enabled; 96 97static long bus_error_jmp[JMP_BUF_LEN]; 98static int catch_memory_errors; 99static int catch_spr_faults; 100static long *xmon_fault_jmp[NR_CPUS]; 101 102/* Breakpoint stuff */ 103struct bpt { 104 unsigned long address; 105 u32 *instr; 106 atomic_t ref_count; 107 int enabled; 108 unsigned long pad; 109}; 110 111/* Bits in bpt.enabled */ 112#define BP_CIABR 1 113#define BP_TRAP 2 114#define BP_DABR 4 115 116static struct bpt bpts[NBPTS]; 117static struct bpt dabr[HBP_NUM_MAX]; 118static struct bpt *iabr; 119static unsigned bpinstr = 0x7fe00008; /* trap */ 120 121#define BP_NUM(bp) ((bp) - bpts + 1) 122 123/* Prototypes */ 124static int cmds(struct pt_regs *); 125static int mread(unsigned long, void *, int); 126static int mwrite(unsigned long, void *, int); 127static int mread_instr(unsigned long, ppc_inst_t *); 128static int handle_fault(struct pt_regs *); 129static void byterev(unsigned char *, int); 130static void memex(void); 131static int bsesc(void); 132static void dump(void); 133static void show_pte(unsigned long); 134static void prdump(unsigned long, long); 135static int ppc_inst_dump(unsigned long, long, int); 136static void dump_log_buf(void); 137 138#ifdef CONFIG_SMP 139static int xmon_switch_cpu(unsigned long); 140static int xmon_batch_next_cpu(void); 141static int batch_cmds(struct pt_regs *); 142#endif 143 144#ifdef CONFIG_PPC_POWERNV 145static void dump_opal_msglog(void); 146#else 147static inline void dump_opal_msglog(void) 148{ 149 printf("Machine is not running OPAL firmware.\n"); 150} 151#endif 152 153static void backtrace(struct pt_regs *); 154static void excprint(struct pt_regs *); 155static void prregs(struct pt_regs *); 156static void memops(int); 157static void memlocate(void); 158static void memzcan(void); 159static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned); 160int skipbl(void); 161int scanhex(unsigned long *valp); 162static void scannl(void); 163static int hexdigit(int); 164void getstring(char *, int); 165static void flush_input(void); 166static int inchar(void); 167static void take_input(char *); 168static int read_spr(int, unsigned long *); 169static void write_spr(int, unsigned long); 170static void super_regs(void); 171static void remove_bpts(void); 172static void insert_bpts(void); 173static void remove_cpu_bpts(void); 174static void insert_cpu_bpts(void); 175static struct bpt *at_breakpoint(unsigned long pc); 176static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp); 177static int do_step(struct pt_regs *); 178static void bpt_cmds(void); 179static void cacheflush(void); 180static int cpu_cmd(void); 181static void csum(void); 182static void bootcmds(void); 183static void proccall(void); 184static void show_tasks(void); 185void dump_segments(void); 186static void symbol_lookup(void); 187static void xmon_show_stack(unsigned long sp, unsigned long lr, 188 unsigned long pc); 189static void xmon_print_symbol(unsigned long address, const char *mid, 190 const char *after); 191static const char *getvecname(unsigned long vec); 192 193static int do_spu_cmd(void); 194 195#ifdef CONFIG_44x 196static void dump_tlb_44x(void); 197#endif 198#ifdef CONFIG_PPC_BOOK3E 199static void dump_tlb_book3e(void); 200#endif 201 202static void clear_all_bpt(void); 203 204#ifdef CONFIG_PPC64 205#define REG "%.16lx" 206#else 207#define REG "%.8lx" 208#endif 209 210#ifdef __LITTLE_ENDIAN__ 211#define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0]) 212#else 213#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3]) 214#endif 215 216static const char *xmon_ro_msg = "Operation disabled: xmon in read-only mode\n"; 217 218static char *help_string = "\ 219Commands:\n\ 220 b show breakpoints\n\ 221 bd set data breakpoint\n\ 222 bi set instruction breakpoint\n\ 223 bc clear breakpoint\n" 224#ifdef CONFIG_SMP 225 "\ 226 c print cpus stopped in xmon\n\ 227 c# try to switch to cpu number h (in hex)\n\ 228 c# $ run command '$' (one of 'r','S' or 't') on all cpus in xmon\n" 229#endif 230 "\ 231 C checksum\n\ 232 d dump bytes\n\ 233 d1 dump 1 byte values\n\ 234 d2 dump 2 byte values\n\ 235 d4 dump 4 byte values\n\ 236 d8 dump 8 byte values\n\ 237 di dump instructions\n\ 238 df dump float values\n\ 239 dd dump double values\n\ 240 dl dump the kernel log buffer\n" 241#ifdef CONFIG_PPC_POWERNV 242 "\ 243 do dump the OPAL message log\n" 244#endif 245#ifdef CONFIG_PPC64 246 "\ 247 dp[#] dump paca for current cpu, or cpu #\n\ 248 dpa dump paca for all possible cpus\n" 249#endif 250 "\ 251 dr dump stream of raw bytes\n\ 252 dv dump virtual address translation \n\ 253 dt dump the tracing buffers (uses printk)\n\ 254 dtc dump the tracing buffers for current CPU (uses printk)\n\ 255" 256#ifdef CONFIG_PPC_POWERNV 257" dx# dump xive on CPU #\n\ 258 dxi# dump xive irq state #\n\ 259 dxa dump xive on all CPUs\n" 260#endif 261" e print exception information\n\ 262 f flush cache\n\ 263 la lookup symbol+offset of specified address\n\ 264 ls lookup address of specified symbol\n\ 265 lp s [#] lookup address of percpu symbol s for current cpu, or cpu #\n\ 266 m examine/change memory\n\ 267 mm move a block of memory\n\ 268 ms set a block of memory\n\ 269 md compare two blocks of memory\n\ 270 ml locate a block of memory\n\ 271 mz zero a block of memory\n\ 272 mi show information about memory allocation\n\ 273 p call a procedure\n\ 274 P list processes/tasks\n\ 275 r print registers\n\ 276 s single step\n" 277#ifdef CONFIG_SPU_BASE 278" ss stop execution on all spus\n\ 279 sr restore execution on stopped spus\n\ 280 sf # dump spu fields for spu # (in hex)\n\ 281 sd # dump spu local store for spu # (in hex)\n\ 282 sdi # disassemble spu local store for spu # (in hex)\n" 283#endif 284" S print special registers\n\ 285 Sa print all SPRs\n\ 286 Sr # read SPR #\n\ 287 Sw #v write v to SPR #\n\ 288 t print backtrace\n\ 289 x exit monitor and recover\n\ 290 X exit monitor and don't recover\n" 291#if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E) 292" u dump segment table or SLB\n" 293#elif defined(CONFIG_PPC_BOOK3S_32) 294" u dump segment registers\n" 295#elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E) 296" u dump TLB\n" 297#endif 298" U show uptime information\n" 299" ? help\n" 300" # n limit output to n lines per page (for dp, dpa, dl)\n" 301" zr reboot\n" 302" zh halt\n" 303; 304 305#ifdef CONFIG_SECURITY 306static bool xmon_is_locked_down(void) 307{ 308 static bool lockdown; 309 310 if (!lockdown) { 311 lockdown = !!security_locked_down(LOCKDOWN_XMON_RW); 312 if (lockdown) { 313 printf("xmon: Disabled due to kernel lockdown\n"); 314 xmon_is_ro = true; 315 } 316 } 317 318 if (!xmon_is_ro) { 319 xmon_is_ro = !!security_locked_down(LOCKDOWN_XMON_WR); 320 if (xmon_is_ro) 321 printf("xmon: Read-only due to kernel lockdown\n"); 322 } 323 324 return lockdown; 325} 326#else /* CONFIG_SECURITY */ 327static inline bool xmon_is_locked_down(void) 328{ 329 return false; 330} 331#endif 332 333static struct pt_regs *xmon_regs; 334 335static inline void sync(void) 336{ 337 asm volatile("sync; isync"); 338} 339 340static inline void cflush(void *p) 341{ 342 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p)); 343} 344 345static inline void cinval(void *p) 346{ 347 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); 348} 349 350/** 351 * write_ciabr() - write the CIABR SPR 352 * @ciabr: The value to write. 353 * 354 * This function writes a value to the CIARB register either directly 355 * through mtspr instruction if the kernel is in HV privilege mode or 356 * call a hypervisor function to achieve the same in case the kernel 357 * is in supervisor privilege mode. 358 */ 359static void write_ciabr(unsigned long ciabr) 360{ 361 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 362 return; 363 364 if (cpu_has_feature(CPU_FTR_HVMODE)) { 365 mtspr(SPRN_CIABR, ciabr); 366 return; 367 } 368 plpar_set_ciabr(ciabr); 369} 370 371/** 372 * set_ciabr() - set the CIABR 373 * @addr: The value to set. 374 * 375 * This function sets the correct privilege value into the HW 376 * breakpoint address before writing it up in the CIABR register. 377 */ 378static void set_ciabr(unsigned long addr) 379{ 380 addr &= ~CIABR_PRIV; 381 382 if (cpu_has_feature(CPU_FTR_HVMODE)) 383 addr |= CIABR_PRIV_HYPER; 384 else 385 addr |= CIABR_PRIV_SUPER; 386 write_ciabr(addr); 387} 388 389/* 390 * Disable surveillance (the service processor watchdog function) 391 * while we are in xmon. 392 * XXX we should re-enable it when we leave. :) 393 */ 394#define SURVEILLANCE_TOKEN 9000 395 396static inline void disable_surveillance(void) 397{ 398#ifdef CONFIG_PPC_PSERIES 399 /* Since this can't be a module, args should end up below 4GB. */ 400 static struct rtas_args args; 401 402 /* 403 * At this point we have got all the cpus we can into 404 * xmon, so there is hopefully no other cpu calling RTAS 405 * at the moment, even though we don't take rtas.lock. 406 * If we did try to take rtas.lock there would be a 407 * real possibility of deadlock. 408 */ 409 if (set_indicator_token == RTAS_UNKNOWN_SERVICE) 410 return; 411 412 rtas_call_unlocked(&args, set_indicator_token, 3, 1, NULL, 413 SURVEILLANCE_TOKEN, 0, 0); 414 415#endif /* CONFIG_PPC_PSERIES */ 416} 417 418#ifdef CONFIG_SMP 419static int xmon_speaker; 420 421static void get_output_lock(void) 422{ 423 int me = smp_processor_id() + 0x100; 424 int last_speaker = 0, prev; 425 long timeout; 426 427 if (xmon_speaker == me) 428 return; 429 430 for (;;) { 431 last_speaker = cmpxchg(&xmon_speaker, 0, me); 432 if (last_speaker == 0) 433 return; 434 435 /* 436 * Wait a full second for the lock, we might be on a slow 437 * console, but check every 100us. 438 */ 439 timeout = 10000; 440 while (xmon_speaker == last_speaker) { 441 if (--timeout > 0) { 442 udelay(100); 443 continue; 444 } 445 446 /* hostile takeover */ 447 prev = cmpxchg(&xmon_speaker, last_speaker, me); 448 if (prev == last_speaker) 449 return; 450 break; 451 } 452 } 453} 454 455static void release_output_lock(void) 456{ 457 xmon_speaker = 0; 458} 459 460int cpus_are_in_xmon(void) 461{ 462 return !cpumask_empty(&cpus_in_xmon); 463} 464 465static bool wait_for_other_cpus(int ncpus) 466{ 467 unsigned long timeout; 468 469 /* We wait for 2s, which is a metric "little while" */ 470 for (timeout = 20000; timeout != 0; --timeout) { 471 if (cpumask_weight(&cpus_in_xmon) >= ncpus) 472 return true; 473 udelay(100); 474 barrier(); 475 } 476 477 return false; 478} 479#else /* CONFIG_SMP */ 480static inline void get_output_lock(void) {} 481static inline void release_output_lock(void) {} 482#endif 483 484static void xmon_touch_watchdogs(void) 485{ 486 touch_softlockup_watchdog_sync(); 487 rcu_cpu_stall_reset(); 488 touch_nmi_watchdog(); 489} 490 491static int xmon_core(struct pt_regs *regs, volatile int fromipi) 492{ 493 volatile int cmd = 0; 494 struct bpt *volatile bp; 495 long recurse_jmp[JMP_BUF_LEN]; 496 bool locked_down; 497 unsigned long offset; 498 unsigned long flags; 499#ifdef CONFIG_SMP 500 int cpu; 501 int secondary; 502#endif 503 504 local_irq_save(flags); 505 hard_irq_disable(); 506 507 locked_down = xmon_is_locked_down(); 508 509 if (!fromipi) { 510 tracing_enabled = tracing_is_on(); 511 tracing_off(); 512 } 513 514 bp = in_breakpoint_table(regs->nip, &offset); 515 if (bp != NULL) { 516 regs_set_return_ip(regs, bp->address + offset); 517 atomic_dec(&bp->ref_count); 518 } 519 520 remove_cpu_bpts(); 521 522#ifdef CONFIG_SMP 523 cpu = smp_processor_id(); 524 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) { 525 /* 526 * We catch SPR read/write faults here because the 0x700, 0xf60 527 * etc. handlers don't call debugger_fault_handler(). 528 */ 529 if (catch_spr_faults) 530 longjmp(bus_error_jmp, 1); 531 get_output_lock(); 532 excprint(regs); 533 printf("cpu 0x%x: Exception %lx %s in xmon, " 534 "returning to main loop\n", 535 cpu, regs->trap, getvecname(TRAP(regs))); 536 release_output_lock(); 537 longjmp(xmon_fault_jmp[cpu], 1); 538 } 539 540 if (setjmp(recurse_jmp) != 0) { 541 if (!in_xmon || !xmon_gate) { 542 get_output_lock(); 543 printf("xmon: WARNING: bad recursive fault " 544 "on cpu 0x%x\n", cpu); 545 release_output_lock(); 546 goto waiting; 547 } 548 secondary = !(xmon_taken && cpu == xmon_owner); 549 goto cmdloop; 550 } 551 552 xmon_fault_jmp[cpu] = recurse_jmp; 553 554 bp = NULL; 555 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) 556 bp = at_breakpoint(regs->nip); 557 if (bp || regs_is_unrecoverable(regs)) 558 fromipi = 0; 559 560 if (!fromipi) { 561 get_output_lock(); 562 if (!locked_down) 563 excprint(regs); 564 if (bp) { 565 printf("cpu 0x%x stopped at breakpoint 0x%tx (", 566 cpu, BP_NUM(bp)); 567 xmon_print_symbol(regs->nip, " ", ")\n"); 568 } 569 if (regs_is_unrecoverable(regs)) 570 printf("WARNING: exception is not recoverable, " 571 "can't continue\n"); 572 release_output_lock(); 573 } 574 575 cpumask_set_cpu(cpu, &cpus_in_xmon); 576 577 waiting: 578 secondary = 1; 579 spin_begin(); 580 while (secondary && !xmon_gate) { 581 if (in_xmon == 0) { 582 if (fromipi) { 583 spin_end(); 584 goto leave; 585 } 586 secondary = test_and_set_bit(0, &in_xmon); 587 } 588 spin_cpu_relax(); 589 touch_nmi_watchdog(); 590 } 591 spin_end(); 592 593 if (!secondary && !xmon_gate) { 594 /* we are the first cpu to come in */ 595 /* interrupt other cpu(s) */ 596 int ncpus = num_online_cpus(); 597 598 xmon_owner = cpu; 599 mb(); 600 if (ncpus > 1) { 601 /* 602 * A system reset (trap == 0x100) can be triggered on 603 * all CPUs, so when we come in via 0x100 try waiting 604 * for the other CPUs to come in before we send the 605 * debugger break (IPI). This is similar to 606 * crash_kexec_secondary(). 607 */ 608 if (TRAP(regs) != INTERRUPT_SYSTEM_RESET || !wait_for_other_cpus(ncpus)) 609 smp_send_debugger_break(); 610 611 wait_for_other_cpus(ncpus); 612 } 613 remove_bpts(); 614 disable_surveillance(); 615 616 if (!locked_down) { 617 /* for breakpoint or single step, print curr insn */ 618 if (bp || TRAP(regs) == INTERRUPT_TRACE) 619 ppc_inst_dump(regs->nip, 1, 0); 620 printf("enter ? for help\n"); 621 } 622 623 mb(); 624 xmon_gate = 1; 625 barrier(); 626 touch_nmi_watchdog(); 627 } 628 629 cmdloop: 630 while (in_xmon) { 631 if (secondary) { 632 spin_begin(); 633 if (cpu == xmon_owner) { 634 if (!test_and_set_bit(0, &xmon_taken)) { 635 secondary = 0; 636 spin_end(); 637 continue; 638 } 639 /* missed it */ 640 while (cpu == xmon_owner) 641 spin_cpu_relax(); 642 } 643 spin_cpu_relax(); 644 touch_nmi_watchdog(); 645 } else { 646 cmd = 1; 647#ifdef CONFIG_SMP 648 if (xmon_batch) 649 cmd = batch_cmds(regs); 650#endif 651 if (!locked_down && cmd) 652 cmd = cmds(regs); 653 if (locked_down || cmd != 0) { 654 /* exiting xmon */ 655 insert_bpts(); 656 xmon_gate = 0; 657 wmb(); 658 in_xmon = 0; 659 break; 660 } 661 /* have switched to some other cpu */ 662 secondary = 1; 663 } 664 } 665 leave: 666 cpumask_clear_cpu(cpu, &cpus_in_xmon); 667 xmon_fault_jmp[cpu] = NULL; 668#else 669 /* UP is simple... */ 670 if (in_xmon) { 671 printf("Exception %lx %s in xmon, returning to main loop\n", 672 regs->trap, getvecname(TRAP(regs))); 673 longjmp(xmon_fault_jmp[0], 1); 674 } 675 if (setjmp(recurse_jmp) == 0) { 676 xmon_fault_jmp[0] = recurse_jmp; 677 in_xmon = 1; 678 679 excprint(regs); 680 bp = at_breakpoint(regs->nip); 681 if (bp) { 682 printf("Stopped at breakpoint %tx (", BP_NUM(bp)); 683 xmon_print_symbol(regs->nip, " ", ")\n"); 684 } 685 if (regs_is_unrecoverable(regs)) 686 printf("WARNING: exception is not recoverable, " 687 "can't continue\n"); 688 remove_bpts(); 689 disable_surveillance(); 690 if (!locked_down) { 691 /* for breakpoint or single step, print current insn */ 692 if (bp || TRAP(regs) == INTERRUPT_TRACE) 693 ppc_inst_dump(regs->nip, 1, 0); 694 printf("enter ? for help\n"); 695 } 696 } 697 698 if (!locked_down) 699 cmd = cmds(regs); 700 701 insert_bpts(); 702 in_xmon = 0; 703#endif 704 705#ifdef CONFIG_BOOKE 706 if (regs->msr & MSR_DE) { 707 bp = at_breakpoint(regs->nip); 708 if (bp != NULL) { 709 regs_set_return_ip(regs, (unsigned long) &bp->instr[0]); 710 atomic_inc(&bp->ref_count); 711 } 712 } 713#else 714 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) { 715 bp = at_breakpoint(regs->nip); 716 if (bp != NULL) { 717 int stepped = emulate_step(regs, ppc_inst_read(bp->instr)); 718 if (stepped == 0) { 719 regs_set_return_ip(regs, (unsigned long) &bp->instr[0]); 720 atomic_inc(&bp->ref_count); 721 } else if (stepped < 0) { 722 printf("Couldn't single-step %s instruction\n", 723 IS_RFID(ppc_inst_read(bp->instr))? "rfid": "mtmsrd"); 724 } 725 } 726 } 727#endif 728 if (locked_down) 729 clear_all_bpt(); 730 else 731 insert_cpu_bpts(); 732 733 xmon_touch_watchdogs(); 734 local_irq_restore(flags); 735 736 return cmd != 'X' && cmd != EOF; 737} 738 739int xmon(struct pt_regs *excp) 740{ 741 struct pt_regs regs; 742 743 if (excp == NULL) { 744 ppc_save_regs(®s); 745 excp = ®s; 746 } 747 748 return xmon_core(excp, 0); 749} 750EXPORT_SYMBOL(xmon); 751 752irqreturn_t xmon_irq(int irq, void *d) 753{ 754 unsigned long flags; 755 local_irq_save(flags); 756 printf("Keyboard interrupt\n"); 757 xmon(get_irq_regs()); 758 local_irq_restore(flags); 759 return IRQ_HANDLED; 760} 761 762static int xmon_bpt(struct pt_regs *regs) 763{ 764 struct bpt *bp; 765 unsigned long offset; 766 767 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT)) 768 return 0; 769 770 /* Are we at the trap at bp->instr[1] for some bp? */ 771 bp = in_breakpoint_table(regs->nip, &offset); 772 if (bp != NULL && (offset == 4 || offset == 8)) { 773 regs_set_return_ip(regs, bp->address + offset); 774 atomic_dec(&bp->ref_count); 775 return 1; 776 } 777 778 /* Are we at a breakpoint? */ 779 bp = at_breakpoint(regs->nip); 780 if (!bp) 781 return 0; 782 783 xmon_core(regs, 0); 784 785 return 1; 786} 787 788static int xmon_sstep(struct pt_regs *regs) 789{ 790 if (user_mode(regs)) 791 return 0; 792 xmon_core(regs, 0); 793 return 1; 794} 795 796static int xmon_break_match(struct pt_regs *regs) 797{ 798 int i; 799 800 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT)) 801 return 0; 802 for (i = 0; i < nr_wp_slots(); i++) { 803 if (dabr[i].enabled) 804 goto found; 805 } 806 return 0; 807 808found: 809 xmon_core(regs, 0); 810 return 1; 811} 812 813static int xmon_iabr_match(struct pt_regs *regs) 814{ 815 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT)) 816 return 0; 817 if (iabr == NULL) 818 return 0; 819 xmon_core(regs, 0); 820 return 1; 821} 822 823static int xmon_ipi(struct pt_regs *regs) 824{ 825#ifdef CONFIG_SMP 826 if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon)) 827 xmon_core(regs, 1); 828#endif 829 return 0; 830} 831 832static int xmon_fault_handler(struct pt_regs *regs) 833{ 834 struct bpt *bp; 835 unsigned long offset; 836 837 if (in_xmon && catch_memory_errors) 838 handle_fault(regs); /* doesn't return */ 839 840 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) { 841 bp = in_breakpoint_table(regs->nip, &offset); 842 if (bp != NULL) { 843 regs_set_return_ip(regs, bp->address + offset); 844 atomic_dec(&bp->ref_count); 845 } 846 } 847 848 return 0; 849} 850 851/* Force enable xmon if not already enabled */ 852static inline void force_enable_xmon(void) 853{ 854 /* Enable xmon hooks if needed */ 855 if (!xmon_on) { 856 printf("xmon: Enabling debugger hooks\n"); 857 xmon_on = 1; 858 } 859} 860 861static struct bpt *at_breakpoint(unsigned long pc) 862{ 863 int i; 864 struct bpt *volatile bp; 865 866 bp = bpts; 867 for (i = 0; i < NBPTS; ++i, ++bp) 868 if (bp->enabled && pc == bp->address) 869 return bp; 870 return NULL; 871} 872 873static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp) 874{ 875 unsigned long off; 876 877 off = nip - (unsigned long)bpt_table; 878 if (off >= sizeof(bpt_table)) 879 return NULL; 880 *offp = off & (BPT_SIZE - 1); 881 if (off & 3) 882 return NULL; 883 return bpts + (off / BPT_SIZE); 884} 885 886static struct bpt *new_breakpoint(unsigned long a) 887{ 888 struct bpt *bp; 889 890 a &= ~3UL; 891 bp = at_breakpoint(a); 892 if (bp) 893 return bp; 894 895 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) { 896 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) { 897 bp->address = a; 898 bp->instr = (void *)(bpt_table + ((bp - bpts) * BPT_WORDS)); 899 return bp; 900 } 901 } 902 903 printf("Sorry, no free breakpoints. Please clear one first.\n"); 904 return NULL; 905} 906 907static void insert_bpts(void) 908{ 909 int i; 910 ppc_inst_t instr, instr2; 911 struct bpt *bp, *bp2; 912 913 bp = bpts; 914 for (i = 0; i < NBPTS; ++i, ++bp) { 915 if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0) 916 continue; 917 if (!mread_instr(bp->address, &instr)) { 918 printf("Couldn't read instruction at %lx, " 919 "disabling breakpoint there\n", bp->address); 920 bp->enabled = 0; 921 continue; 922 } 923 if (!can_single_step(ppc_inst_val(instr))) { 924 printf("Breakpoint at %lx is on an instruction that can't be single stepped, disabling it\n", 925 bp->address); 926 bp->enabled = 0; 927 continue; 928 } 929 /* 930 * Check the address is not a suffix by looking for a prefix in 931 * front of it. 932 */ 933 if (mread_instr(bp->address - 4, &instr2) == 8) { 934 printf("Breakpoint at %lx is on the second word of a prefixed instruction, disabling it\n", 935 bp->address); 936 bp->enabled = 0; 937 continue; 938 } 939 /* 940 * We might still be a suffix - if the prefix has already been 941 * replaced by a breakpoint we won't catch it with the above 942 * test. 943 */ 944 bp2 = at_breakpoint(bp->address - 4); 945 if (bp2 && ppc_inst_prefixed(ppc_inst_read(bp2->instr))) { 946 printf("Breakpoint at %lx is on the second word of a prefixed instruction, disabling it\n", 947 bp->address); 948 bp->enabled = 0; 949 continue; 950 } 951 952 patch_instruction(bp->instr, instr); 953 patch_instruction(ppc_inst_next(bp->instr, bp->instr), 954 ppc_inst(bpinstr)); 955 if (bp->enabled & BP_CIABR) 956 continue; 957 if (patch_instruction((u32 *)bp->address, 958 ppc_inst(bpinstr)) != 0) { 959 printf("Couldn't write instruction at %lx, " 960 "disabling breakpoint there\n", bp->address); 961 bp->enabled &= ~BP_TRAP; 962 continue; 963 } 964 } 965} 966 967static void insert_cpu_bpts(void) 968{ 969 int i; 970 struct arch_hw_breakpoint brk; 971 972 for (i = 0; i < nr_wp_slots(); i++) { 973 if (dabr[i].enabled) { 974 brk.address = dabr[i].address; 975 brk.type = (dabr[i].enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL; 976 brk.len = 8; 977 brk.hw_len = 8; 978 __set_breakpoint(i, &brk); 979 } 980 } 981 982 if (iabr) 983 set_ciabr(iabr->address); 984} 985 986static void remove_bpts(void) 987{ 988 int i; 989 struct bpt *bp; 990 ppc_inst_t instr; 991 992 bp = bpts; 993 for (i = 0; i < NBPTS; ++i, ++bp) { 994 if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP) 995 continue; 996 if (mread_instr(bp->address, &instr) 997 && ppc_inst_equal(instr, ppc_inst(bpinstr)) 998 && patch_instruction( 999 (u32 *)bp->address, ppc_inst_read(bp->instr)) != 0) 1000 printf("Couldn't remove breakpoint at %lx\n", 1001 bp->address); 1002 } 1003} 1004 1005static void remove_cpu_bpts(void) 1006{ 1007 hw_breakpoint_disable(); 1008 write_ciabr(0); 1009} 1010 1011/* Based on uptime_proc_show(). */ 1012static void 1013show_uptime(void) 1014{ 1015 struct timespec64 uptime; 1016 1017 if (setjmp(bus_error_jmp) == 0) { 1018 catch_memory_errors = 1; 1019 sync(); 1020 1021 ktime_get_coarse_boottime_ts64(&uptime); 1022 printf("Uptime: %lu.%.2lu seconds\n", (unsigned long)uptime.tv_sec, 1023 ((unsigned long)uptime.tv_nsec / (NSEC_PER_SEC/100))); 1024 1025 sync(); 1026 __delay(200); \ 1027 } 1028 catch_memory_errors = 0; 1029} 1030 1031static void set_lpp_cmd(void) 1032{ 1033 unsigned long lpp; 1034 1035 if (!scanhex(&lpp)) { 1036 printf("Invalid number.\n"); 1037 lpp = 0; 1038 } 1039 xmon_set_pagination_lpp(lpp); 1040} 1041/* Command interpreting routine */ 1042static char *last_cmd; 1043 1044static int 1045cmds(struct pt_regs *excp) 1046{ 1047 int cmd = 0; 1048 1049 last_cmd = NULL; 1050 xmon_regs = excp; 1051 1052 xmon_show_stack(excp->gpr[1], excp->link, excp->nip); 1053 1054 for(;;) { 1055#ifdef CONFIG_SMP 1056 printf("%x:", smp_processor_id()); 1057#endif /* CONFIG_SMP */ 1058 printf("mon> "); 1059 flush_input(); 1060 termch = 0; 1061 cmd = skipbl(); 1062 if( cmd == '\n' ) { 1063 if (last_cmd == NULL) 1064 continue; 1065 take_input(last_cmd); 1066 last_cmd = NULL; 1067 cmd = inchar(); 1068 } 1069 switch (cmd) { 1070 case 'm': 1071 cmd = inchar(); 1072 switch (cmd) { 1073 case 'm': 1074 case 's': 1075 case 'd': 1076 memops(cmd); 1077 break; 1078 case 'l': 1079 memlocate(); 1080 break; 1081 case 'z': 1082 if (xmon_is_ro) { 1083 printf(xmon_ro_msg); 1084 break; 1085 } 1086 memzcan(); 1087 break; 1088 case 'i': 1089 show_mem(0, NULL); 1090 break; 1091 default: 1092 termch = cmd; 1093 memex(); 1094 } 1095 break; 1096 case 'd': 1097 dump(); 1098 break; 1099 case 'l': 1100 symbol_lookup(); 1101 break; 1102 case 'r': 1103 prregs(excp); /* print regs */ 1104 break; 1105 case 'e': 1106 excprint(excp); 1107 break; 1108 case 'S': 1109 super_regs(); 1110 break; 1111 case 't': 1112 backtrace(excp); 1113 break; 1114 case 'f': 1115 cacheflush(); 1116 break; 1117 case 's': 1118 if (do_spu_cmd() == 0) 1119 break; 1120 if (do_step(excp)) 1121 return cmd; 1122 break; 1123 case 'x': 1124 case 'X': 1125 if (tracing_enabled) 1126 tracing_on(); 1127 return cmd; 1128 case EOF: 1129 printf(" <no input ...>\n"); 1130 mdelay(2000); 1131 return cmd; 1132 case '?': 1133 xmon_puts(help_string); 1134 break; 1135 case '#': 1136 set_lpp_cmd(); 1137 break; 1138 case 'b': 1139 bpt_cmds(); 1140 break; 1141 case 'C': 1142 csum(); 1143 break; 1144 case 'c': 1145 if (cpu_cmd()) 1146 return 0; 1147 break; 1148 case 'z': 1149 bootcmds(); 1150 break; 1151 case 'p': 1152 if (xmon_is_ro) { 1153 printf(xmon_ro_msg); 1154 break; 1155 } 1156 proccall(); 1157 break; 1158 case 'P': 1159 show_tasks(); 1160 break; 1161#if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_64S_HASH_MMU) 1162 case 'u': 1163 dump_segments(); 1164 break; 1165#elif defined(CONFIG_44x) 1166 case 'u': 1167 dump_tlb_44x(); 1168 break; 1169#elif defined(CONFIG_PPC_BOOK3E) 1170 case 'u': 1171 dump_tlb_book3e(); 1172 break; 1173#endif 1174 case 'U': 1175 show_uptime(); 1176 break; 1177 default: 1178 printf("Unrecognized command: "); 1179 do { 1180 if (' ' < cmd && cmd <= '~') 1181 putchar(cmd); 1182 else 1183 printf("\\x%x", cmd); 1184 cmd = inchar(); 1185 } while (cmd != '\n'); 1186 printf(" (type ? for help)\n"); 1187 break; 1188 } 1189 } 1190} 1191 1192#ifdef CONFIG_BOOKE 1193static int do_step(struct pt_regs *regs) 1194{ 1195 regs_set_return_msr(regs, regs->msr | MSR_DE); 1196 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); 1197 return 1; 1198} 1199#else 1200/* 1201 * Step a single instruction. 1202 * Some instructions we emulate, others we execute with MSR_SE set. 1203 */ 1204static int do_step(struct pt_regs *regs) 1205{ 1206 ppc_inst_t instr; 1207 int stepped; 1208 1209 force_enable_xmon(); 1210 /* check we are in 64-bit kernel mode, translation enabled */ 1211 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) { 1212 if (mread_instr(regs->nip, &instr)) { 1213 stepped = emulate_step(regs, instr); 1214 if (stepped < 0) { 1215 printf("Couldn't single-step %s instruction\n", 1216 (IS_RFID(instr)? "rfid": "mtmsrd")); 1217 return 0; 1218 } 1219 if (stepped > 0) { 1220 set_trap(regs, 0xd00); 1221 printf("stepped to "); 1222 xmon_print_symbol(regs->nip, " ", "\n"); 1223 ppc_inst_dump(regs->nip, 1, 0); 1224 return 0; 1225 } 1226 } 1227 } 1228 regs_set_return_msr(regs, regs->msr | MSR_SE); 1229 return 1; 1230} 1231#endif 1232 1233static void bootcmds(void) 1234{ 1235 char tmp[64]; 1236 int cmd; 1237 1238 cmd = inchar(); 1239 if (cmd == 'r') { 1240 getstring(tmp, 64); 1241 ppc_md.restart(tmp); 1242 } else if (cmd == 'h') { 1243 ppc_md.halt(); 1244 } else if (cmd == 'p') { 1245 do_kernel_power_off(); 1246 } 1247} 1248 1249#ifdef CONFIG_SMP 1250static int xmon_switch_cpu(unsigned long cpu) 1251{ 1252 int timeout; 1253 1254 xmon_taken = 0; 1255 mb(); 1256 xmon_owner = cpu; 1257 timeout = 10000000; 1258 while (!xmon_taken) { 1259 if (--timeout == 0) { 1260 if (test_and_set_bit(0, &xmon_taken)) 1261 break; 1262 /* take control back */ 1263 mb(); 1264 xmon_owner = smp_processor_id(); 1265 printf("cpu 0x%lx didn't take control\n", cpu); 1266 return 0; 1267 } 1268 barrier(); 1269 } 1270 return 1; 1271} 1272 1273static int xmon_batch_next_cpu(void) 1274{ 1275 unsigned long cpu; 1276 1277 while (!cpumask_empty(&xmon_batch_cpus)) { 1278 cpu = cpumask_next_wrap(smp_processor_id(), &xmon_batch_cpus, 1279 xmon_batch_start_cpu, true); 1280 if (cpu == nr_cpumask_bits) 1281 break; 1282 if (xmon_batch_start_cpu == -1) 1283 xmon_batch_start_cpu = cpu; 1284 if (xmon_switch_cpu(cpu)) 1285 return 0; 1286 cpumask_clear_cpu(cpu, &xmon_batch_cpus); 1287 } 1288 1289 xmon_batch = 0; 1290 printf("%x:mon> \n", smp_processor_id()); 1291 return 1; 1292} 1293 1294static int batch_cmds(struct pt_regs *excp) 1295{ 1296 int cmd; 1297 1298 /* simulate command entry */ 1299 cmd = xmon_batch; 1300 termch = '\n'; 1301 1302 last_cmd = NULL; 1303 xmon_regs = excp; 1304 1305 printf("%x:", smp_processor_id()); 1306 printf("mon> "); 1307 printf("%c\n", (char)cmd); 1308 1309 switch (cmd) { 1310 case 'r': 1311 prregs(excp); /* print regs */ 1312 break; 1313 case 'S': 1314 super_regs(); 1315 break; 1316 case 't': 1317 backtrace(excp); 1318 break; 1319 } 1320 1321 cpumask_clear_cpu(smp_processor_id(), &xmon_batch_cpus); 1322 1323 return xmon_batch_next_cpu(); 1324} 1325 1326static int cpu_cmd(void) 1327{ 1328 unsigned long cpu, first_cpu, last_cpu; 1329 1330 cpu = skipbl(); 1331 if (cpu == '#') { 1332 xmon_batch = skipbl(); 1333 if (xmon_batch) { 1334 switch (xmon_batch) { 1335 case 'r': 1336 case 'S': 1337 case 't': 1338 cpumask_copy(&xmon_batch_cpus, &cpus_in_xmon); 1339 if (cpumask_weight(&xmon_batch_cpus) <= 1) { 1340 printf("There are no other cpus in xmon\n"); 1341 break; 1342 } 1343 xmon_batch_start_cpu = -1; 1344 if (!xmon_batch_next_cpu()) 1345 return 1; 1346 break; 1347 default: 1348 printf("c# only supports 'r', 'S' and 't' commands\n"); 1349 } 1350 xmon_batch = 0; 1351 return 0; 1352 } 1353 } 1354 termch = cpu; 1355 1356 if (!scanhex(&cpu)) { 1357 /* print cpus waiting or in xmon */ 1358 printf("cpus stopped:"); 1359 last_cpu = first_cpu = NR_CPUS; 1360 for_each_possible_cpu(cpu) { 1361 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) { 1362 if (cpu == last_cpu + 1) { 1363 last_cpu = cpu; 1364 } else { 1365 if (last_cpu != first_cpu) 1366 printf("-0x%lx", last_cpu); 1367 last_cpu = first_cpu = cpu; 1368 printf(" 0x%lx", cpu); 1369 } 1370 } 1371 } 1372 if (last_cpu != first_cpu) 1373 printf("-0x%lx", last_cpu); 1374 printf("\n"); 1375 return 0; 1376 } 1377 /* try to switch to cpu specified */ 1378 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) { 1379 printf("cpu 0x%lx isn't in xmon\n", cpu); 1380#ifdef CONFIG_PPC64 1381 printf("backtrace of paca[0x%lx].saved_r1 (possibly stale):\n", cpu); 1382 xmon_show_stack(paca_ptrs[cpu]->saved_r1, 0, 0); 1383#endif 1384 return 0; 1385 } 1386 1387 return xmon_switch_cpu(cpu); 1388} 1389#else 1390static int cpu_cmd(void) 1391{ 1392 return 0; 1393} 1394#endif /* CONFIG_SMP */ 1395 1396static unsigned short fcstab[256] = { 1397 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 1398 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 1399 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 1400 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 1401 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 1402 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 1403 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 1404 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 1405 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 1406 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 1407 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 1408 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 1409 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 1410 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 1411 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 1412 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 1413 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 1414 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 1415 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 1416 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 1417 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 1418 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 1419 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 1420 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 1421 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 1422 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 1423 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 1424 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 1425 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 1426 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 1427 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 1428 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 1429}; 1430 1431#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) 1432 1433static void 1434csum(void) 1435{ 1436 unsigned int i; 1437 unsigned short fcs; 1438 unsigned char v; 1439 1440 if (!scanhex(&adrs)) 1441 return; 1442 if (!scanhex(&ncsum)) 1443 return; 1444 fcs = 0xffff; 1445 for (i = 0; i < ncsum; ++i) { 1446 if (mread(adrs+i, &v, 1) == 0) { 1447 printf("csum stopped at "REG"\n", adrs+i); 1448 break; 1449 } 1450 fcs = FCS(fcs, v); 1451 } 1452 printf("%x\n", fcs); 1453} 1454 1455/* 1456 * Check if this is a suitable place to put a breakpoint. 1457 */ 1458static long check_bp_loc(unsigned long addr) 1459{ 1460 ppc_inst_t instr; 1461 1462 addr &= ~3; 1463 if (!is_kernel_addr(addr)) { 1464 printf("Breakpoints may only be placed at kernel addresses\n"); 1465 return 0; 1466 } 1467 if (!mread_instr(addr, &instr)) { 1468 printf("Can't read instruction at address %lx\n", addr); 1469 return 0; 1470 } 1471 if (!can_single_step(ppc_inst_val(instr))) { 1472 printf("Breakpoints may not be placed on instructions that can't be single stepped\n"); 1473 return 0; 1474 } 1475 return 1; 1476} 1477 1478static int find_free_data_bpt(void) 1479{ 1480 int i; 1481 1482 for (i = 0; i < nr_wp_slots(); i++) { 1483 if (!dabr[i].enabled) 1484 return i; 1485 } 1486 printf("Couldn't find free breakpoint register\n"); 1487 return -1; 1488} 1489 1490static void print_data_bpts(void) 1491{ 1492 int i; 1493 1494 for (i = 0; i < nr_wp_slots(); i++) { 1495 if (!dabr[i].enabled) 1496 continue; 1497 1498 printf(" data "REG" [", dabr[i].address); 1499 if (dabr[i].enabled & 1) 1500 printf("r"); 1501 if (dabr[i].enabled & 2) 1502 printf("w"); 1503 printf("]\n"); 1504 } 1505} 1506 1507static char *breakpoint_help_string = 1508 "Breakpoint command usage:\n" 1509 "b show breakpoints\n" 1510 "b <addr> [cnt] set breakpoint at given instr addr\n" 1511 "bc clear all breakpoints\n" 1512 "bc <n/addr> clear breakpoint number n or at addr\n" 1513 "bi <addr> [cnt] set hardware instr breakpoint (POWER8 only)\n" 1514 "bd <addr> [cnt] set hardware data breakpoint\n" 1515 ""; 1516 1517static void 1518bpt_cmds(void) 1519{ 1520 int cmd; 1521 unsigned long a; 1522 int i; 1523 struct bpt *bp; 1524 1525 cmd = inchar(); 1526 1527 switch (cmd) { 1528 static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n"; 1529 int mode; 1530 case 'd': /* bd - hardware data breakpoint */ 1531 if (xmon_is_ro) { 1532 printf(xmon_ro_msg); 1533 break; 1534 } 1535 if (!ppc_breakpoint_available()) { 1536 printf("Hardware data breakpoint not supported on this cpu\n"); 1537 break; 1538 } 1539 i = find_free_data_bpt(); 1540 if (i < 0) 1541 break; 1542 mode = 7; 1543 cmd = inchar(); 1544 if (cmd == 'r') 1545 mode = 5; 1546 else if (cmd == 'w') 1547 mode = 6; 1548 else 1549 termch = cmd; 1550 dabr[i].address = 0; 1551 dabr[i].enabled = 0; 1552 if (scanhex(&dabr[i].address)) { 1553 if (!is_kernel_addr(dabr[i].address)) { 1554 printf(badaddr); 1555 break; 1556 } 1557 dabr[i].address &= ~HW_BRK_TYPE_DABR; 1558 dabr[i].enabled = mode | BP_DABR; 1559 } 1560 1561 force_enable_xmon(); 1562 break; 1563 1564 case 'i': /* bi - hardware instr breakpoint */ 1565 if (xmon_is_ro) { 1566 printf(xmon_ro_msg); 1567 break; 1568 } 1569 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) { 1570 printf("Hardware instruction breakpoint " 1571 "not supported on this cpu\n"); 1572 break; 1573 } 1574 if (iabr) { 1575 iabr->enabled &= ~BP_CIABR; 1576 iabr = NULL; 1577 } 1578 if (!scanhex(&a)) 1579 break; 1580 if (!check_bp_loc(a)) 1581 break; 1582 bp = new_breakpoint(a); 1583 if (bp != NULL) { 1584 bp->enabled |= BP_CIABR; 1585 iabr = bp; 1586 force_enable_xmon(); 1587 } 1588 break; 1589 1590 case 'c': 1591 if (!scanhex(&a)) { 1592 /* clear all breakpoints */ 1593 for (i = 0; i < NBPTS; ++i) 1594 bpts[i].enabled = 0; 1595 iabr = NULL; 1596 for (i = 0; i < nr_wp_slots(); i++) 1597 dabr[i].enabled = 0; 1598 1599 printf("All breakpoints cleared\n"); 1600 break; 1601 } 1602 1603 if (a <= NBPTS && a >= 1) { 1604 /* assume a breakpoint number */ 1605 bp = &bpts[a-1]; /* bp nums are 1 based */ 1606 } else { 1607 /* assume a breakpoint address */ 1608 bp = at_breakpoint(a); 1609 if (bp == NULL) { 1610 printf("No breakpoint at %lx\n", a); 1611 break; 1612 } 1613 } 1614 1615 printf("Cleared breakpoint %tx (", BP_NUM(bp)); 1616 xmon_print_symbol(bp->address, " ", ")\n"); 1617 bp->enabled = 0; 1618 break; 1619 1620 default: 1621 termch = cmd; 1622 cmd = skipbl(); 1623 if (cmd == '?') { 1624 printf(breakpoint_help_string); 1625 break; 1626 } 1627 termch = cmd; 1628 1629 if (xmon_is_ro || !scanhex(&a)) { 1630 /* print all breakpoints */ 1631 printf(" type address\n"); 1632 print_data_bpts(); 1633 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) { 1634 if (!bp->enabled) 1635 continue; 1636 printf("%tx %s ", BP_NUM(bp), 1637 (bp->enabled & BP_CIABR) ? "inst": "trap"); 1638 xmon_print_symbol(bp->address, " ", "\n"); 1639 } 1640 break; 1641 } 1642 1643 if (!check_bp_loc(a)) 1644 break; 1645 bp = new_breakpoint(a); 1646 if (bp != NULL) { 1647 bp->enabled |= BP_TRAP; 1648 force_enable_xmon(); 1649 } 1650 break; 1651 } 1652} 1653 1654/* Very cheap human name for vector lookup. */ 1655static 1656const char *getvecname(unsigned long vec) 1657{ 1658 char *ret; 1659 1660 switch (vec) { 1661 case 0x100: ret = "(System Reset)"; break; 1662 case 0x200: ret = "(Machine Check)"; break; 1663 case 0x300: ret = "(Data Access)"; break; 1664 case 0x380: 1665 if (radix_enabled()) 1666 ret = "(Data Access Out of Range)"; 1667 else 1668 ret = "(Data SLB Access)"; 1669 break; 1670 case 0x400: ret = "(Instruction Access)"; break; 1671 case 0x480: 1672 if (radix_enabled()) 1673 ret = "(Instruction Access Out of Range)"; 1674 else 1675 ret = "(Instruction SLB Access)"; 1676 break; 1677 case 0x500: ret = "(Hardware Interrupt)"; break; 1678 case 0x600: ret = "(Alignment)"; break; 1679 case 0x700: ret = "(Program Check)"; break; 1680 case 0x800: ret = "(FPU Unavailable)"; break; 1681 case 0x900: ret = "(Decrementer)"; break; 1682 case 0x980: ret = "(Hypervisor Decrementer)"; break; 1683 case 0xa00: ret = "(Doorbell)"; break; 1684 case 0xc00: ret = "(System Call)"; break; 1685 case 0xd00: ret = "(Single Step)"; break; 1686 case 0xe40: ret = "(Emulation Assist)"; break; 1687 case 0xe60: ret = "(HMI)"; break; 1688 case 0xe80: ret = "(Hypervisor Doorbell)"; break; 1689 case 0xf00: ret = "(Performance Monitor)"; break; 1690 case 0xf20: ret = "(Altivec Unavailable)"; break; 1691 case 0x1300: ret = "(Instruction Breakpoint)"; break; 1692 case 0x1500: ret = "(Denormalisation)"; break; 1693 case 0x1700: ret = "(Altivec Assist)"; break; 1694 case 0x3000: ret = "(System Call Vectored)"; break; 1695 default: ret = ""; 1696 } 1697 return ret; 1698} 1699 1700static void get_function_bounds(unsigned long pc, unsigned long *startp, 1701 unsigned long *endp) 1702{ 1703 unsigned long size, offset; 1704 const char *name; 1705 1706 *startp = *endp = 0; 1707 if (pc == 0) 1708 return; 1709 if (setjmp(bus_error_jmp) == 0) { 1710 catch_memory_errors = 1; 1711 sync(); 1712 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr); 1713 if (name != NULL) { 1714 *startp = pc - offset; 1715 *endp = pc - offset + size; 1716 } 1717 sync(); 1718 } 1719 catch_memory_errors = 0; 1720} 1721 1722#define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long)) 1723#define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long)) 1724 1725static void xmon_show_stack(unsigned long sp, unsigned long lr, 1726 unsigned long pc) 1727{ 1728 int max_to_print = 64; 1729 unsigned long ip; 1730 unsigned long newsp; 1731 unsigned long marker; 1732 struct pt_regs regs; 1733 1734 while (max_to_print--) { 1735 if (!is_kernel_addr(sp)) { 1736 if (sp != 0) 1737 printf("SP (%lx) is in userspace\n", sp); 1738 break; 1739 } 1740 1741 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long)) 1742 || !mread(sp, &newsp, sizeof(unsigned long))) { 1743 printf("Couldn't read stack frame at %lx\n", sp); 1744 break; 1745 } 1746 1747 /* 1748 * For the first stack frame, try to work out if 1749 * LR and/or the saved LR value in the bottommost 1750 * stack frame are valid. 1751 */ 1752 if ((pc | lr) != 0) { 1753 unsigned long fnstart, fnend; 1754 unsigned long nextip; 1755 int printip = 1; 1756 1757 get_function_bounds(pc, &fnstart, &fnend); 1758 nextip = 0; 1759 if (newsp > sp) 1760 mread(newsp + LRSAVE_OFFSET, &nextip, 1761 sizeof(unsigned long)); 1762 if (lr == ip) { 1763 if (!is_kernel_addr(lr) 1764 || (fnstart <= lr && lr < fnend)) 1765 printip = 0; 1766 } else if (lr == nextip) { 1767 printip = 0; 1768 } else if (is_kernel_addr(lr) 1769 && !(fnstart <= lr && lr < fnend)) { 1770 printf("[link register ] "); 1771 xmon_print_symbol(lr, " ", "\n"); 1772 } 1773 if (printip) { 1774 printf("["REG"] ", sp); 1775 xmon_print_symbol(ip, " ", " (unreliable)\n"); 1776 } 1777 pc = lr = 0; 1778 1779 } else { 1780 printf("["REG"] ", sp); 1781 xmon_print_symbol(ip, " ", "\n"); 1782 } 1783 1784 /* Look for "regshere" marker to see if this is 1785 an exception frame. */ 1786 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long)) 1787 && marker == STACK_FRAME_REGS_MARKER) { 1788 if (mread(sp + STACK_FRAME_OVERHEAD, ®s, sizeof(regs)) 1789 != sizeof(regs)) { 1790 printf("Couldn't read registers at %lx\n", 1791 sp + STACK_FRAME_OVERHEAD); 1792 break; 1793 } 1794 printf("--- Exception: %lx %s at ", regs.trap, 1795 getvecname(TRAP(®s))); 1796 pc = regs.nip; 1797 lr = regs.link; 1798 xmon_print_symbol(pc, " ", "\n"); 1799 } 1800 1801 if (newsp == 0) 1802 break; 1803 1804 sp = newsp; 1805 } 1806} 1807 1808static void backtrace(struct pt_regs *excp) 1809{ 1810 unsigned long sp; 1811 1812 if (scanhex(&sp)) 1813 xmon_show_stack(sp, 0, 0); 1814 else 1815 xmon_show_stack(excp->gpr[1], excp->link, excp->nip); 1816 scannl(); 1817} 1818 1819static void print_bug_trap(struct pt_regs *regs) 1820{ 1821#ifdef CONFIG_BUG 1822 const struct bug_entry *bug; 1823 unsigned long addr; 1824 1825 if (regs->msr & MSR_PR) 1826 return; /* not in kernel */ 1827 addr = regs->nip; /* address of trap instruction */ 1828 if (!is_kernel_addr(addr)) 1829 return; 1830 bug = find_bug(regs->nip); 1831 if (bug == NULL) 1832 return; 1833 if (is_warning_bug(bug)) 1834 return; 1835 1836#ifdef CONFIG_DEBUG_BUGVERBOSE 1837 printf("kernel BUG at %s:%u!\n", 1838 (char *)bug + bug->file_disp, bug->line); 1839#else 1840 printf("kernel BUG at %px!\n", (void *)bug + bug->bug_addr_disp); 1841#endif 1842#endif /* CONFIG_BUG */ 1843} 1844 1845static void excprint(struct pt_regs *fp) 1846{ 1847 unsigned long trap; 1848 1849#ifdef CONFIG_SMP 1850 printf("cpu 0x%x: ", smp_processor_id()); 1851#endif /* CONFIG_SMP */ 1852 1853 trap = TRAP(fp); 1854 printf("Vector: %lx %s at [%px]\n", fp->trap, getvecname(trap), fp); 1855 printf(" pc: "); 1856 xmon_print_symbol(fp->nip, ": ", "\n"); 1857 1858 printf(" lr: "); 1859 xmon_print_symbol(fp->link, ": ", "\n"); 1860 1861 printf(" sp: %lx\n", fp->gpr[1]); 1862 printf(" msr: %lx\n", fp->msr); 1863 1864 if (trap == INTERRUPT_DATA_STORAGE || 1865 trap == INTERRUPT_DATA_SEGMENT || 1866 trap == INTERRUPT_ALIGNMENT || 1867 trap == INTERRUPT_MACHINE_CHECK) { 1868 printf(" dar: %lx\n", fp->dar); 1869 if (trap != INTERRUPT_DATA_SEGMENT) 1870 printf(" dsisr: %lx\n", fp->dsisr); 1871 } 1872 1873 printf(" current = 0x%px\n", current); 1874#ifdef CONFIG_PPC64 1875 printf(" paca = 0x%px\t irqmask: 0x%02x\t irq_happened: 0x%02x\n", 1876 local_paca, local_paca->irq_soft_mask, local_paca->irq_happened); 1877#endif 1878 if (current) { 1879 printf(" pid = %d, comm = %s\n", 1880 current->pid, current->comm); 1881 } 1882 1883 if (trap == INTERRUPT_PROGRAM) 1884 print_bug_trap(fp); 1885 1886 printf(linux_banner); 1887} 1888 1889static void prregs(struct pt_regs *fp) 1890{ 1891 int n, trap; 1892 unsigned long base; 1893 struct pt_regs regs; 1894 1895 if (scanhex(&base)) { 1896 if (setjmp(bus_error_jmp) == 0) { 1897 catch_memory_errors = 1; 1898 sync(); 1899 regs = *(struct pt_regs *)base; 1900 sync(); 1901 __delay(200); 1902 } else { 1903 catch_memory_errors = 0; 1904 printf("*** Error reading registers from "REG"\n", 1905 base); 1906 return; 1907 } 1908 catch_memory_errors = 0; 1909 fp = ®s; 1910 } 1911 1912#ifdef CONFIG_PPC64 1913#define R_PER_LINE 2 1914#else 1915#define R_PER_LINE 4 1916#endif 1917 1918 for (n = 0; n < 32; ++n) { 1919 printf("R%.2d = "REG"%s", n, fp->gpr[n], 1920 (n % R_PER_LINE) == R_PER_LINE - 1 ? "\n" : " "); 1921 } 1922 1923 printf("pc = "); 1924 xmon_print_symbol(fp->nip, " ", "\n"); 1925 if (!trap_is_syscall(fp) && cpu_has_feature(CPU_FTR_CFAR)) { 1926 printf("cfar= "); 1927 xmon_print_symbol(fp->orig_gpr3, " ", "\n"); 1928 } 1929 printf("lr = "); 1930 xmon_print_symbol(fp->link, " ", "\n"); 1931 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr); 1932 printf("ctr = "REG" xer = "REG" trap = %4lx\n", 1933 fp->ctr, fp->xer, fp->trap); 1934 trap = TRAP(fp); 1935 if (trap == INTERRUPT_DATA_STORAGE || 1936 trap == INTERRUPT_DATA_SEGMENT || 1937 trap == INTERRUPT_ALIGNMENT) 1938 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr); 1939} 1940 1941static void cacheflush(void) 1942{ 1943 int cmd; 1944 unsigned long nflush; 1945 1946 cmd = inchar(); 1947 if (cmd != 'i') 1948 termch = cmd; 1949 scanhex((void *)&adrs); 1950 if (termch != '\n') 1951 termch = 0; 1952 nflush = 1; 1953 scanhex(&nflush); 1954 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES; 1955 if (setjmp(bus_error_jmp) == 0) { 1956 catch_memory_errors = 1; 1957 sync(); 1958 1959 if (cmd != 'i' || IS_ENABLED(CONFIG_PPC_BOOK3S_64)) { 1960 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES) 1961 cflush((void *) adrs); 1962 } else { 1963 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES) 1964 cinval((void *) adrs); 1965 } 1966 sync(); 1967 /* wait a little while to see if we get a machine check */ 1968 __delay(200); 1969 } 1970 catch_memory_errors = 0; 1971} 1972 1973extern unsigned long xmon_mfspr(int spr, unsigned long default_value); 1974extern void xmon_mtspr(int spr, unsigned long value); 1975 1976static int 1977read_spr(int n, unsigned long *vp) 1978{ 1979 unsigned long ret = -1UL; 1980 int ok = 0; 1981 1982 if (setjmp(bus_error_jmp) == 0) { 1983 catch_spr_faults = 1; 1984 sync(); 1985 1986 ret = xmon_mfspr(n, *vp); 1987 1988 sync(); 1989 *vp = ret; 1990 ok = 1; 1991 } 1992 catch_spr_faults = 0; 1993 1994 return ok; 1995} 1996 1997static void 1998write_spr(int n, unsigned long val) 1999{ 2000 if (xmon_is_ro) { 2001 printf(xmon_ro_msg); 2002 return; 2003 } 2004 2005 if (setjmp(bus_error_jmp) == 0) { 2006 catch_spr_faults = 1; 2007 sync(); 2008 2009 xmon_mtspr(n, val); 2010 2011 sync(); 2012 } else { 2013 printf("SPR 0x%03x (%4d) Faulted during write\n", n, n); 2014 } 2015 catch_spr_faults = 0; 2016} 2017 2018static void dump_206_sprs(void) 2019{ 2020#ifdef CONFIG_PPC64 2021 if (!cpu_has_feature(CPU_FTR_ARCH_206)) 2022 return; 2023 2024 /* Actually some of these pre-date 2.06, but whatever */ 2025 2026 printf("srr0 = %.16lx srr1 = %.16lx dsisr = %.8lx\n", 2027 mfspr(SPRN_SRR0), mfspr(SPRN_SRR1), mfspr(SPRN_DSISR)); 2028 printf("dscr = %.16lx ppr = %.16lx pir = %.8lx\n", 2029 mfspr(SPRN_DSCR), mfspr(SPRN_PPR), mfspr(SPRN_PIR)); 2030 printf("amr = %.16lx uamor = %.16lx\n", 2031 mfspr(SPRN_AMR), mfspr(SPRN_UAMOR)); 2032 2033 if (!(mfmsr() & MSR_HV)) 2034 return; 2035 2036 printf("sdr1 = %.16lx hdar = %.16lx hdsisr = %.8lx\n", 2037 mfspr(SPRN_SDR1), mfspr(SPRN_HDAR), mfspr(SPRN_HDSISR)); 2038 printf("hsrr0 = %.16lx hsrr1 = %.16lx hdec = %.16lx\n", 2039 mfspr(SPRN_HSRR0), mfspr(SPRN_HSRR1), mfspr(SPRN_HDEC)); 2040 printf("lpcr = %.16lx pcr = %.16lx lpidr = %.8lx\n", 2041 mfspr(SPRN_LPCR), mfspr(SPRN_PCR), mfspr(SPRN_LPID)); 2042 printf("hsprg0 = %.16lx hsprg1 = %.16lx amor = %.16lx\n", 2043 mfspr(SPRN_HSPRG0), mfspr(SPRN_HSPRG1), mfspr(SPRN_AMOR)); 2044 printf("dabr = %.16lx dabrx = %.16lx\n", 2045 mfspr(SPRN_DABR), mfspr(SPRN_DABRX)); 2046#endif 2047} 2048 2049static void dump_207_sprs(void) 2050{ 2051#ifdef CONFIG_PPC64 2052 unsigned long msr; 2053 2054 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 2055 return; 2056 2057 printf("dpdes = %.16lx tir = %.16lx cir = %.8lx\n", 2058 mfspr(SPRN_DPDES), mfspr(SPRN_TIR), mfspr(SPRN_CIR)); 2059 2060 printf("fscr = %.16lx tar = %.16lx pspb = %.8lx\n", 2061 mfspr(SPRN_FSCR), mfspr(SPRN_TAR), mfspr(SPRN_PSPB)); 2062 2063 msr = mfmsr(); 2064 if (msr & MSR_TM) { 2065 /* Only if TM has been enabled in the kernel */ 2066 printf("tfhar = %.16lx tfiar = %.16lx texasr = %.16lx\n", 2067 mfspr(SPRN_TFHAR), mfspr(SPRN_TFIAR), 2068 mfspr(SPRN_TEXASR)); 2069 } 2070 2071 printf("mmcr0 = %.16lx mmcr1 = %.16lx mmcr2 = %.16lx\n", 2072 mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCR2)); 2073 printf("pmc1 = %.8lx pmc2 = %.8lx pmc3 = %.8lx pmc4 = %.8lx\n", 2074 mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), 2075 mfspr(SPRN_PMC3), mfspr(SPRN_PMC4)); 2076 printf("mmcra = %.16lx siar = %.16lx pmc5 = %.8lx\n", 2077 mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR), mfspr(SPRN_PMC5)); 2078 printf("sdar = %.16lx sier = %.16lx pmc6 = %.8lx\n", 2079 mfspr(SPRN_SDAR), mfspr(SPRN_SIER), mfspr(SPRN_PMC6)); 2080 printf("ebbhr = %.16lx ebbrr = %.16lx bescr = %.16lx\n", 2081 mfspr(SPRN_EBBHR), mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR)); 2082 printf("iamr = %.16lx\n", mfspr(SPRN_IAMR)); 2083 2084 if (!(msr & MSR_HV)) 2085 return; 2086 2087 printf("hfscr = %.16lx dhdes = %.16lx rpr = %.16lx\n", 2088 mfspr(SPRN_HFSCR), mfspr(SPRN_DHDES), mfspr(SPRN_RPR)); 2089 printf("dawr0 = %.16lx dawrx0 = %.16lx\n", 2090 mfspr(SPRN_DAWR0), mfspr(SPRN_DAWRX0)); 2091 if (nr_wp_slots() > 1) { 2092 printf("dawr1 = %.16lx dawrx1 = %.16lx\n", 2093 mfspr(SPRN_DAWR1), mfspr(SPRN_DAWRX1)); 2094 } 2095 printf("ciabr = %.16lx\n", mfspr(SPRN_CIABR)); 2096#endif 2097} 2098 2099static void dump_300_sprs(void) 2100{ 2101#ifdef CONFIG_PPC64 2102 bool hv = mfmsr() & MSR_HV; 2103 2104 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2105 return; 2106 2107 if (cpu_has_feature(CPU_FTR_P9_TIDR)) { 2108 printf("pidr = %.16lx tidr = %.16lx\n", 2109 mfspr(SPRN_PID), mfspr(SPRN_TIDR)); 2110 } else { 2111 printf("pidr = %.16lx\n", 2112 mfspr(SPRN_PID)); 2113 } 2114 2115 printf("psscr = %.16lx\n", 2116 hv ? mfspr(SPRN_PSSCR) : mfspr(SPRN_PSSCR_PR)); 2117 2118 if (!hv) 2119 return; 2120 2121 printf("ptcr = %.16lx asdr = %.16lx\n", 2122 mfspr(SPRN_PTCR), mfspr(SPRN_ASDR)); 2123#endif 2124} 2125 2126static void dump_310_sprs(void) 2127{ 2128#ifdef CONFIG_PPC64 2129 if (!cpu_has_feature(CPU_FTR_ARCH_31)) 2130 return; 2131 2132 printf("mmcr3 = %.16lx, sier2 = %.16lx, sier3 = %.16lx\n", 2133 mfspr(SPRN_MMCR3), mfspr(SPRN_SIER2), mfspr(SPRN_SIER3)); 2134 2135#endif 2136} 2137 2138static void dump_one_spr(int spr, bool show_unimplemented) 2139{ 2140 unsigned long val; 2141 2142 val = 0xdeadbeef; 2143 if (!read_spr(spr, &val)) { 2144 printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr); 2145 return; 2146 } 2147 2148 if (val == 0xdeadbeef) { 2149 /* Looks like read was a nop, confirm */ 2150 val = 0x0badcafe; 2151 if (!read_spr(spr, &val)) { 2152 printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr); 2153 return; 2154 } 2155 2156 if (val == 0x0badcafe) { 2157 if (show_unimplemented) 2158 printf("SPR 0x%03x (%4d) Unimplemented\n", spr, spr); 2159 return; 2160 } 2161 } 2162 2163 printf("SPR 0x%03x (%4d) = 0x%lx\n", spr, spr, val); 2164} 2165 2166static void super_regs(void) 2167{ 2168 static unsigned long regno; 2169 int cmd; 2170 int spr; 2171 2172 cmd = skipbl(); 2173 2174 switch (cmd) { 2175 case '\n': { 2176 unsigned long sp, toc; 2177 asm("mr %0,1" : "=r" (sp) :); 2178 asm("mr %0,2" : "=r" (toc) :); 2179 2180 printf("msr = "REG" sprg0 = "REG"\n", 2181 mfmsr(), mfspr(SPRN_SPRG0)); 2182 printf("pvr = "REG" sprg1 = "REG"\n", 2183 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); 2184 printf("dec = "REG" sprg2 = "REG"\n", 2185 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2)); 2186 printf("sp = "REG" sprg3 = "REG"\n", sp, mfspr(SPRN_SPRG3)); 2187 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); 2188 2189 dump_206_sprs(); 2190 dump_207_sprs(); 2191 dump_300_sprs(); 2192 dump_310_sprs(); 2193 2194 return; 2195 } 2196 case 'w': { 2197 unsigned long val; 2198 scanhex(®no); 2199 val = 0; 2200 read_spr(regno, &val); 2201 scanhex(&val); 2202 write_spr(regno, val); 2203 dump_one_spr(regno, true); 2204 break; 2205 } 2206 case 'r': 2207 scanhex(®no); 2208 dump_one_spr(regno, true); 2209 break; 2210 case 'a': 2211 /* dump ALL SPRs */ 2212 for (spr = 1; spr < 1024; ++spr) 2213 dump_one_spr(spr, false); 2214 break; 2215 } 2216 2217 scannl(); 2218} 2219 2220/* 2221 * Stuff for reading and writing memory safely 2222 */ 2223static int 2224mread(unsigned long adrs, void *buf, int size) 2225{ 2226 volatile int n; 2227 char *p, *q; 2228 2229 n = 0; 2230 if (setjmp(bus_error_jmp) == 0) { 2231 catch_memory_errors = 1; 2232 sync(); 2233 p = (char *)adrs; 2234 q = (char *)buf; 2235 switch (size) { 2236 case 2: 2237 *(u16 *)q = *(u16 *)p; 2238 break; 2239 case 4: 2240 *(u32 *)q = *(u32 *)p; 2241 break; 2242 case 8: 2243 *(u64 *)q = *(u64 *)p; 2244 break; 2245 default: 2246 for( ; n < size; ++n) { 2247 *q++ = *p++; 2248 sync(); 2249 } 2250 } 2251 sync(); 2252 /* wait a little while to see if we get a machine check */ 2253 __delay(200); 2254 n = size; 2255 } 2256 catch_memory_errors = 0; 2257 return n; 2258} 2259 2260static int 2261mwrite(unsigned long adrs, void *buf, int size) 2262{ 2263 volatile int n; 2264 char *p, *q; 2265 2266 n = 0; 2267 2268 if (xmon_is_ro) { 2269 printf(xmon_ro_msg); 2270 return n; 2271 } 2272 2273 if (setjmp(bus_error_jmp) == 0) { 2274 catch_memory_errors = 1; 2275 sync(); 2276 p = (char *) adrs; 2277 q = (char *) buf; 2278 switch (size) { 2279 case 2: 2280 *(u16 *)p = *(u16 *)q; 2281 break; 2282 case 4: 2283 *(u32 *)p = *(u32 *)q; 2284 break; 2285 case 8: 2286 *(u64 *)p = *(u64 *)q; 2287 break; 2288 default: 2289 for ( ; n < size; ++n) { 2290 *p++ = *q++; 2291 sync(); 2292 } 2293 } 2294 sync(); 2295 /* wait a little while to see if we get a machine check */ 2296 __delay(200); 2297 n = size; 2298 } else { 2299 printf("*** Error writing address "REG"\n", adrs + n); 2300 } 2301 catch_memory_errors = 0; 2302 return n; 2303} 2304 2305static int 2306mread_instr(unsigned long adrs, ppc_inst_t *instr) 2307{ 2308 volatile int n; 2309 2310 n = 0; 2311 if (setjmp(bus_error_jmp) == 0) { 2312 catch_memory_errors = 1; 2313 sync(); 2314 *instr = ppc_inst_read((u32 *)adrs); 2315 sync(); 2316 /* wait a little while to see if we get a machine check */ 2317 __delay(200); 2318 n = ppc_inst_len(*instr); 2319 } 2320 catch_memory_errors = 0; 2321 return n; 2322} 2323 2324static int fault_type; 2325static int fault_except; 2326static char *fault_chars[] = { "--", "**", "##" }; 2327 2328static int handle_fault(struct pt_regs *regs) 2329{ 2330 fault_except = TRAP(regs); 2331 switch (TRAP(regs)) { 2332 case 0x200: 2333 fault_type = 0; 2334 break; 2335 case 0x300: 2336 case 0x380: 2337 fault_type = 1; 2338 break; 2339 default: 2340 fault_type = 2; 2341 } 2342 2343 longjmp(bus_error_jmp, 1); 2344 2345 return 0; 2346} 2347 2348#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t)) 2349 2350static void 2351byterev(unsigned char *val, int size) 2352{ 2353 int t; 2354 2355 switch (size) { 2356 case 2: 2357 SWAP(val[0], val[1], t); 2358 break; 2359 case 4: 2360 SWAP(val[0], val[3], t); 2361 SWAP(val[1], val[2], t); 2362 break; 2363 case 8: /* is there really any use for this? */ 2364 SWAP(val[0], val[7], t); 2365 SWAP(val[1], val[6], t); 2366 SWAP(val[2], val[5], t); 2367 SWAP(val[3], val[4], t); 2368 break; 2369 } 2370} 2371 2372static int brev; 2373static int mnoread; 2374 2375static char *memex_help_string = 2376 "Memory examine command usage:\n" 2377 "m [addr] [flags] examine/change memory\n" 2378 " addr is optional. will start where left off.\n" 2379 " flags may include chars from this set:\n" 2380 " b modify by bytes (default)\n" 2381 " w modify by words (2 byte)\n" 2382 " l modify by longs (4 byte)\n" 2383 " d modify by doubleword (8 byte)\n" 2384 " r toggle reverse byte order mode\n" 2385 " n do not read memory (for i/o spaces)\n" 2386 " . ok to read (default)\n" 2387 "NOTE: flags are saved as defaults\n" 2388 ""; 2389 2390static char *memex_subcmd_help_string = 2391 "Memory examine subcommands:\n" 2392 " hexval write this val to current location\n" 2393 " 'string' write chars from string to this location\n" 2394 " ' increment address\n" 2395 " ^ decrement address\n" 2396 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n" 2397 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n" 2398 " ` clear no-read flag\n" 2399 " ; stay at this addr\n" 2400 " v change to byte mode\n" 2401 " w change to word (2 byte) mode\n" 2402 " l change to long (4 byte) mode\n" 2403 " u change to doubleword (8 byte) mode\n" 2404 " m addr change current addr\n" 2405 " n toggle no-read flag\n" 2406 " r toggle byte reverse flag\n" 2407 " < count back up count bytes\n" 2408 " > count skip forward count bytes\n" 2409 " x exit this mode\n" 2410 ""; 2411 2412static void 2413memex(void) 2414{ 2415 int cmd, inc, i, nslash; 2416 unsigned long n; 2417 unsigned char val[16]; 2418 2419 scanhex((void *)&adrs); 2420 cmd = skipbl(); 2421 if (cmd == '?') { 2422 printf(memex_help_string); 2423 return; 2424 } else { 2425 termch = cmd; 2426 } 2427 last_cmd = "m\n"; 2428 while ((cmd = skipbl()) != '\n') { 2429 switch( cmd ){ 2430 case 'b': size = 1; break; 2431 case 'w': size = 2; break; 2432 case 'l': size = 4; break; 2433 case 'd': size = 8; break; 2434 case 'r': brev = !brev; break; 2435 case 'n': mnoread = 1; break; 2436 case '.': mnoread = 0; break; 2437 } 2438 } 2439 if( size <= 0 ) 2440 size = 1; 2441 else if( size > 8 ) 2442 size = 8; 2443 for(;;){ 2444 if (!mnoread) 2445 n = mread(adrs, val, size); 2446 printf(REG"%c", adrs, brev? 'r': ' '); 2447 if (!mnoread) { 2448 if (brev) 2449 byterev(val, size); 2450 putchar(' '); 2451 for (i = 0; i < n; ++i) 2452 printf("%.2x", val[i]); 2453 for (; i < size; ++i) 2454 printf("%s", fault_chars[fault_type]); 2455 } 2456 putchar(' '); 2457 inc = size; 2458 nslash = 0; 2459 for(;;){ 2460 if( scanhex(&n) ){ 2461 for (i = 0; i < size; ++i) 2462 val[i] = n >> (i * 8); 2463 if (!brev) 2464 byterev(val, size); 2465 mwrite(adrs, val, size); 2466 inc = size; 2467 } 2468 cmd = skipbl(); 2469 if (cmd == '\n') 2470 break; 2471 inc = 0; 2472 switch (cmd) { 2473 case '\'': 2474 for(;;){ 2475 n = inchar(); 2476 if( n == '\\' ) 2477 n = bsesc(); 2478 else if( n == '\'' ) 2479 break; 2480 for (i = 0; i < size; ++i) 2481 val[i] = n >> (i * 8); 2482 if (!brev) 2483 byterev(val, size); 2484 mwrite(adrs, val, size); 2485 adrs += size; 2486 } 2487 adrs -= size; 2488 inc = size; 2489 break; 2490 case ',': 2491 adrs += size; 2492 break; 2493 case '.': 2494 mnoread = 0; 2495 break; 2496 case ';': 2497 break; 2498 case 'x': 2499 case EOF: 2500 scannl(); 2501 return; 2502 case 'b': 2503 case 'v': 2504 size = 1; 2505 break; 2506 case 'w': 2507 size = 2; 2508 break; 2509 case 'l': 2510 size = 4; 2511 break; 2512 case 'u': 2513 size = 8; 2514 break; 2515 case '^': 2516 adrs -= size; 2517 break; 2518 case '/': 2519 if (nslash > 0) 2520 adrs -= 1 << nslash; 2521 else 2522 nslash = 0; 2523 nslash += 4; 2524 adrs += 1 << nslash; 2525 break; 2526 case '\\': 2527 if (nslash < 0) 2528 adrs += 1 << -nslash; 2529 else 2530 nslash = 0; 2531 nslash -= 4; 2532 adrs -= 1 << -nslash; 2533 break; 2534 case 'm': 2535 scanhex((void *)&adrs); 2536 break; 2537 case 'n': 2538 mnoread = 1; 2539 break; 2540 case 'r': 2541 brev = !brev; 2542 break; 2543 case '<': 2544 n = size; 2545 scanhex(&n); 2546 adrs -= n; 2547 break; 2548 case '>': 2549 n = size; 2550 scanhex(&n); 2551 adrs += n; 2552 break; 2553 case '?': 2554 printf(memex_subcmd_help_string); 2555 break; 2556 } 2557 } 2558 adrs += inc; 2559 } 2560} 2561 2562static int 2563bsesc(void) 2564{ 2565 int c; 2566 2567 c = inchar(); 2568 switch( c ){ 2569 case 'n': c = '\n'; break; 2570 case 'r': c = '\r'; break; 2571 case 'b': c = '\b'; break; 2572 case 't': c = '\t'; break; 2573 } 2574 return c; 2575} 2576 2577static void xmon_rawdump (unsigned long adrs, long ndump) 2578{ 2579 long n, m, r, nr; 2580 unsigned char temp[16]; 2581 2582 for (n = ndump; n > 0;) { 2583 r = n < 16? n: 16; 2584 nr = mread(adrs, temp, r); 2585 adrs += nr; 2586 for (m = 0; m < r; ++m) { 2587 if (m < nr) 2588 printf("%.2x", temp[m]); 2589 else 2590 printf("%s", fault_chars[fault_type]); 2591 } 2592 n -= r; 2593 if (nr < r) 2594 break; 2595 } 2596 printf("\n"); 2597} 2598 2599static void dump_tracing(void) 2600{ 2601 int c; 2602 2603 c = inchar(); 2604 if (c == 'c') 2605 ftrace_dump(DUMP_ORIG); 2606 else 2607 ftrace_dump(DUMP_ALL); 2608} 2609 2610#ifdef CONFIG_PPC64 2611static void dump_one_paca(int cpu) 2612{ 2613 struct paca_struct *p; 2614#ifdef CONFIG_PPC_64S_HASH_MMU 2615 int i = 0; 2616#endif 2617 2618 if (setjmp(bus_error_jmp) != 0) { 2619 printf("*** Error dumping paca for cpu 0x%x!\n", cpu); 2620 return; 2621 } 2622 2623 catch_memory_errors = 1; 2624 sync(); 2625 2626 p = paca_ptrs[cpu]; 2627 2628 printf("paca for cpu 0x%x @ %px:\n", cpu, p); 2629 2630 printf(" %-*s = %s\n", 25, "possible", cpu_possible(cpu) ? "yes" : "no"); 2631 printf(" %-*s = %s\n", 25, "present", cpu_present(cpu) ? "yes" : "no"); 2632 printf(" %-*s = %s\n", 25, "online", cpu_online(cpu) ? "yes" : "no"); 2633 2634#define DUMP(paca, name, format) \ 2635 printf(" %-*s = "format"\t(0x%lx)\n", 25, #name, 18, paca->name, \ 2636 offsetof(struct paca_struct, name)); 2637 2638 DUMP(p, lock_token, "%#-*x"); 2639 DUMP(p, paca_index, "%#-*x"); 2640 DUMP(p, kernel_toc, "%#-*llx"); 2641 DUMP(p, kernelbase, "%#-*llx"); 2642 DUMP(p, kernel_msr, "%#-*llx"); 2643 DUMP(p, emergency_sp, "%-*px"); 2644#ifdef CONFIG_PPC_BOOK3S_64 2645 DUMP(p, nmi_emergency_sp, "%-*px"); 2646 DUMP(p, mc_emergency_sp, "%-*px"); 2647 DUMP(p, in_nmi, "%#-*x"); 2648 DUMP(p, in_mce, "%#-*x"); 2649 DUMP(p, hmi_event_available, "%#-*x"); 2650#endif 2651 DUMP(p, data_offset, "%#-*llx"); 2652 DUMP(p, hw_cpu_id, "%#-*x"); 2653 DUMP(p, cpu_start, "%#-*x"); 2654 DUMP(p, kexec_state, "%#-*x"); 2655#ifdef CONFIG_PPC_BOOK3S_64 2656#ifdef CONFIG_PPC_64S_HASH_MMU 2657 if (!early_radix_enabled()) { 2658 for (i = 0; i < SLB_NUM_BOLTED; i++) { 2659 u64 esid, vsid; 2660 2661 if (!p->slb_shadow_ptr) 2662 continue; 2663 2664 esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid); 2665 vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid); 2666 2667 if (esid || vsid) { 2668 printf(" %-*s[%d] = 0x%016llx 0x%016llx\n", 2669 22, "slb_shadow", i, esid, vsid); 2670 } 2671 } 2672 DUMP(p, vmalloc_sllp, "%#-*x"); 2673 DUMP(p, stab_rr, "%#-*x"); 2674 DUMP(p, slb_used_bitmap, "%#-*x"); 2675 DUMP(p, slb_kern_bitmap, "%#-*x"); 2676 2677 if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { 2678 DUMP(p, slb_cache_ptr, "%#-*x"); 2679 for (i = 0; i < SLB_CACHE_ENTRIES; i++) 2680 printf(" %-*s[%d] = 0x%016x\n", 2681 22, "slb_cache", i, p->slb_cache[i]); 2682 } 2683 } 2684#endif 2685 2686 DUMP(p, rfi_flush_fallback_area, "%-*px"); 2687#endif 2688 DUMP(p, dscr_default, "%#-*llx"); 2689#ifdef CONFIG_PPC_BOOK3E 2690 DUMP(p, pgd, "%-*px"); 2691 DUMP(p, kernel_pgd, "%-*px"); 2692 DUMP(p, tcd_ptr, "%-*px"); 2693 DUMP(p, mc_kstack, "%-*px"); 2694 DUMP(p, crit_kstack, "%-*px"); 2695 DUMP(p, dbg_kstack, "%-*px"); 2696#endif 2697 DUMP(p, __current, "%-*px"); 2698 DUMP(p, kstack, "%#-*llx"); 2699 printf(" %-*s = 0x%016llx\n", 25, "kstack_base", p->kstack & ~(THREAD_SIZE - 1)); 2700#ifdef CONFIG_STACKPROTECTOR 2701 DUMP(p, canary, "%#-*lx"); 2702#endif 2703 DUMP(p, saved_r1, "%#-*llx"); 2704#ifdef CONFIG_PPC_BOOK3E 2705 DUMP(p, trap_save, "%#-*x"); 2706#endif 2707 DUMP(p, irq_soft_mask, "%#-*x"); 2708 DUMP(p, irq_happened, "%#-*x"); 2709#ifdef CONFIG_MMIOWB 2710 DUMP(p, mmiowb_state.nesting_count, "%#-*x"); 2711 DUMP(p, mmiowb_state.mmiowb_pending, "%#-*x"); 2712#endif 2713 DUMP(p, irq_work_pending, "%#-*x"); 2714 DUMP(p, sprg_vdso, "%#-*llx"); 2715 2716#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 2717 DUMP(p, tm_scratch, "%#-*llx"); 2718#endif 2719 2720#ifdef CONFIG_PPC_POWERNV 2721 DUMP(p, idle_state, "%#-*lx"); 2722 if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { 2723 DUMP(p, thread_idle_state, "%#-*x"); 2724 DUMP(p, subcore_sibling_mask, "%#-*x"); 2725 } else { 2726#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE 2727 DUMP(p, requested_psscr, "%#-*llx"); 2728 DUMP(p, dont_stop.counter, "%#-*x"); 2729#endif 2730 } 2731#endif 2732 2733 DUMP(p, accounting.utime, "%#-*lx"); 2734 DUMP(p, accounting.stime, "%#-*lx"); 2735#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 2736 DUMP(p, accounting.utime_scaled, "%#-*lx"); 2737#endif 2738 DUMP(p, accounting.starttime, "%#-*lx"); 2739 DUMP(p, accounting.starttime_user, "%#-*lx"); 2740#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 2741 DUMP(p, accounting.startspurr, "%#-*lx"); 2742 DUMP(p, accounting.utime_sspurr, "%#-*lx"); 2743#endif 2744 DUMP(p, accounting.steal_time, "%#-*lx"); 2745#undef DUMP 2746 2747 catch_memory_errors = 0; 2748 sync(); 2749} 2750 2751static void dump_all_pacas(void) 2752{ 2753 int cpu; 2754 2755 if (num_possible_cpus() == 0) { 2756 printf("No possible cpus, use 'dp #' to dump individual cpus\n"); 2757 return; 2758 } 2759 2760 for_each_possible_cpu(cpu) 2761 dump_one_paca(cpu); 2762} 2763 2764static void dump_pacas(void) 2765{ 2766 unsigned long num; 2767 int c; 2768 2769 c = inchar(); 2770 if (c == 'a') { 2771 dump_all_pacas(); 2772 return; 2773 } 2774 2775 termch = c; /* Put c back, it wasn't 'a' */ 2776 2777 if (scanhex(&num)) 2778 dump_one_paca(num); 2779 else 2780 dump_one_paca(xmon_owner); 2781} 2782#endif 2783 2784#ifdef CONFIG_PPC_POWERNV 2785static void dump_one_xive(int cpu) 2786{ 2787 unsigned int hwid = get_hard_smp_processor_id(cpu); 2788 bool hv = cpu_has_feature(CPU_FTR_HVMODE); 2789 2790 if (hv) { 2791 opal_xive_dump(XIVE_DUMP_TM_HYP, hwid); 2792 opal_xive_dump(XIVE_DUMP_TM_POOL, hwid); 2793 opal_xive_dump(XIVE_DUMP_TM_OS, hwid); 2794 opal_xive_dump(XIVE_DUMP_TM_USER, hwid); 2795 opal_xive_dump(XIVE_DUMP_VP, hwid); 2796 opal_xive_dump(XIVE_DUMP_EMU_STATE, hwid); 2797 } 2798 2799 if (setjmp(bus_error_jmp) != 0) { 2800 catch_memory_errors = 0; 2801 printf("*** Error dumping xive on cpu %d\n", cpu); 2802 return; 2803 } 2804 2805 catch_memory_errors = 1; 2806 sync(); 2807 xmon_xive_do_dump(cpu); 2808 sync(); 2809 __delay(200); 2810 catch_memory_errors = 0; 2811} 2812 2813static void dump_all_xives(void) 2814{ 2815 int cpu; 2816 2817 if (num_online_cpus() == 0) { 2818 printf("No possible cpus, use 'dx #' to dump individual cpus\n"); 2819 return; 2820 } 2821 2822 for_each_online_cpu(cpu) 2823 dump_one_xive(cpu); 2824} 2825 2826static void dump_xives(void) 2827{ 2828 unsigned long num; 2829 int c; 2830 2831 if (!xive_enabled()) { 2832 printf("Xive disabled on this system\n"); 2833 return; 2834 } 2835 2836 c = inchar(); 2837 if (c == 'a') { 2838 dump_all_xives(); 2839 return; 2840 } else if (c == 'i') { 2841 if (scanhex(&num)) 2842 xmon_xive_get_irq_config(num, NULL); 2843 else 2844 xmon_xive_get_irq_all(); 2845 return; 2846 } 2847 2848 termch = c; /* Put c back, it wasn't 'a' */ 2849 2850 if (scanhex(&num)) 2851 dump_one_xive(num); 2852 else 2853 dump_one_xive(xmon_owner); 2854} 2855#endif /* CONFIG_PPC_POWERNV */ 2856 2857static void dump_by_size(unsigned long addr, long count, int size) 2858{ 2859 unsigned char temp[16]; 2860 int i, j; 2861 u64 val; 2862 2863 count = ALIGN(count, 16); 2864 2865 for (i = 0; i < count; i += 16, addr += 16) { 2866 printf(REG, addr); 2867 2868 if (mread(addr, temp, 16) != 16) { 2869 printf("\nFaulted reading %d bytes from 0x"REG"\n", 16, addr); 2870 return; 2871 } 2872 2873 for (j = 0; j < 16; j += size) { 2874 putchar(' '); 2875 switch (size) { 2876 case 1: val = temp[j]; break; 2877 case 2: val = *(u16 *)&temp[j]; break; 2878 case 4: val = *(u32 *)&temp[j]; break; 2879 case 8: val = *(u64 *)&temp[j]; break; 2880 default: val = 0; 2881 } 2882 2883 printf("%0*llx", size * 2, val); 2884 } 2885 printf(" |"); 2886 for (j = 0; j < 16; ++j) { 2887 val = temp[j]; 2888 putchar(' ' <= val && val <= '~' ? val : '.'); 2889 } 2890 printf("|\n"); 2891 } 2892} 2893 2894static void 2895dump(void) 2896{ 2897 static char last[] = { "d?\n" }; 2898 int c; 2899 2900 c = inchar(); 2901 2902#ifdef CONFIG_PPC64 2903 if (c == 'p') { 2904 xmon_start_pagination(); 2905 dump_pacas(); 2906 xmon_end_pagination(); 2907 return; 2908 } 2909#endif 2910#ifdef CONFIG_PPC_POWERNV 2911 if (c == 'x') { 2912 xmon_start_pagination(); 2913 dump_xives(); 2914 xmon_end_pagination(); 2915 return; 2916 } 2917#endif 2918 2919 if (c == 't') { 2920 dump_tracing(); 2921 return; 2922 } 2923 2924 if (c == '\n') 2925 termch = c; 2926 2927 scanhex((void *)&adrs); 2928 if (termch != '\n') 2929 termch = 0; 2930 if (c == 'i') { 2931 scanhex(&nidump); 2932 if (nidump == 0) 2933 nidump = 16; 2934 else if (nidump > MAX_IDUMP) 2935 nidump = MAX_IDUMP; 2936 adrs += ppc_inst_dump(adrs, nidump, 1); 2937 last_cmd = "di\n"; 2938 } else if (c == 'l') { 2939 dump_log_buf(); 2940 } else if (c == 'o') { 2941 dump_opal_msglog(); 2942 } else if (c == 'v') { 2943 /* dump virtual to physical translation */ 2944 show_pte(adrs); 2945 } else if (c == 'r') { 2946 scanhex(&ndump); 2947 if (ndump == 0) 2948 ndump = 64; 2949 xmon_rawdump(adrs, ndump); 2950 adrs += ndump; 2951 last_cmd = "dr\n"; 2952 } else { 2953 scanhex(&ndump); 2954 if (ndump == 0) 2955 ndump = 64; 2956 else if (ndump > MAX_DUMP) 2957 ndump = MAX_DUMP; 2958 2959 switch (c) { 2960 case '8': 2961 case '4': 2962 case '2': 2963 case '1': 2964 ndump = ALIGN(ndump, 16); 2965 dump_by_size(adrs, ndump, c - '0'); 2966 last[1] = c; 2967 last_cmd = last; 2968 break; 2969 default: 2970 prdump(adrs, ndump); 2971 last_cmd = "d\n"; 2972 } 2973 2974 adrs += ndump; 2975 } 2976} 2977 2978static void 2979prdump(unsigned long adrs, long ndump) 2980{ 2981 long n, m, c, r, nr; 2982 unsigned char temp[16]; 2983 2984 for (n = ndump; n > 0;) { 2985 printf(REG, adrs); 2986 putchar(' '); 2987 r = n < 16? n: 16; 2988 nr = mread(adrs, temp, r); 2989 adrs += nr; 2990 for (m = 0; m < r; ++m) { 2991 if ((m & (sizeof(long) - 1)) == 0 && m > 0) 2992 putchar(' '); 2993 if (m < nr) 2994 printf("%.2x", temp[m]); 2995 else 2996 printf("%s", fault_chars[fault_type]); 2997 } 2998 for (; m < 16; ++m) { 2999 if ((m & (sizeof(long) - 1)) == 0) 3000 putchar(' '); 3001 printf(" "); 3002 } 3003 printf(" |"); 3004 for (m = 0; m < r; ++m) { 3005 if (m < nr) { 3006 c = temp[m]; 3007 putchar(' ' <= c && c <= '~'? c: '.'); 3008 } else 3009 putchar(' '); 3010 } 3011 n -= r; 3012 for (; m < 16; ++m) 3013 putchar(' '); 3014 printf("|\n"); 3015 if (nr < r) 3016 break; 3017 } 3018} 3019 3020typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr); 3021 3022static int 3023generic_inst_dump(unsigned long adr, long count, int praddr, 3024 instruction_dump_func dump_func) 3025{ 3026 int nr, dotted; 3027 unsigned long first_adr; 3028 ppc_inst_t inst, last_inst = ppc_inst(0); 3029 3030 dotted = 0; 3031 for (first_adr = adr; count > 0; --count, adr += ppc_inst_len(inst)) { 3032 nr = mread_instr(adr, &inst); 3033 if (nr == 0) { 3034 if (praddr) { 3035 const char *x = fault_chars[fault_type]; 3036 printf(REG" %s%s%s%s\n", adr, x, x, x, x); 3037 } 3038 break; 3039 } 3040 if (adr > first_adr && ppc_inst_equal(inst, last_inst)) { 3041 if (!dotted) { 3042 printf(" ...\n"); 3043 dotted = 1; 3044 } 3045 continue; 3046 } 3047 dotted = 0; 3048 last_inst = inst; 3049 if (praddr) 3050 printf(REG" %s", adr, ppc_inst_as_str(inst)); 3051 printf("\t"); 3052 if (!ppc_inst_prefixed(inst)) 3053 dump_func(ppc_inst_val(inst), adr); 3054 else 3055 dump_func(ppc_inst_as_ulong(inst), adr); 3056 printf("\n"); 3057 } 3058 return adr - first_adr; 3059} 3060 3061static int 3062ppc_inst_dump(unsigned long adr, long count, int praddr) 3063{ 3064 return generic_inst_dump(adr, count, praddr, print_insn_powerpc); 3065} 3066 3067void 3068print_address(unsigned long addr) 3069{ 3070 xmon_print_symbol(addr, "\t# ", ""); 3071} 3072 3073static void 3074dump_log_buf(void) 3075{ 3076 struct kmsg_dump_iter iter; 3077 static unsigned char buf[1024]; 3078 size_t len; 3079 3080 if (setjmp(bus_error_jmp) != 0) { 3081 printf("Error dumping printk buffer!\n"); 3082 return; 3083 } 3084 3085 catch_memory_errors = 1; 3086 sync(); 3087 3088 kmsg_dump_rewind(&iter); 3089 xmon_start_pagination(); 3090 while (kmsg_dump_get_line(&iter, false, buf, sizeof(buf), &len)) { 3091 buf[len] = '\0'; 3092 printf("%s", buf); 3093 } 3094 xmon_end_pagination(); 3095 3096 sync(); 3097 /* wait a little while to see if we get a machine check */ 3098 __delay(200); 3099 catch_memory_errors = 0; 3100} 3101 3102#ifdef CONFIG_PPC_POWERNV 3103static void dump_opal_msglog(void) 3104{ 3105 unsigned char buf[128]; 3106 ssize_t res; 3107 volatile loff_t pos = 0; 3108 3109 if (!firmware_has_feature(FW_FEATURE_OPAL)) { 3110 printf("Machine is not running OPAL firmware.\n"); 3111 return; 3112 } 3113 3114 if (setjmp(bus_error_jmp) != 0) { 3115 printf("Error dumping OPAL msglog!\n"); 3116 return; 3117 } 3118 3119 catch_memory_errors = 1; 3120 sync(); 3121 3122 xmon_start_pagination(); 3123 while ((res = opal_msglog_copy(buf, pos, sizeof(buf) - 1))) { 3124 if (res < 0) { 3125 printf("Error dumping OPAL msglog! Error: %zd\n", res); 3126 break; 3127 } 3128 buf[res] = '\0'; 3129 printf("%s", buf); 3130 pos += res; 3131 } 3132 xmon_end_pagination(); 3133 3134 sync(); 3135 /* wait a little while to see if we get a machine check */ 3136 __delay(200); 3137 catch_memory_errors = 0; 3138} 3139#endif 3140 3141/* 3142 * Memory operations - move, set, print differences 3143 */ 3144static unsigned long mdest; /* destination address */ 3145static unsigned long msrc; /* source address */ 3146static unsigned long mval; /* byte value to set memory to */ 3147static unsigned long mcount; /* # bytes to affect */ 3148static unsigned long mdiffs; /* max # differences to print */ 3149 3150static void 3151memops(int cmd) 3152{ 3153 scanhex((void *)&mdest); 3154 if( termch != '\n' ) 3155 termch = 0; 3156 scanhex((void *)(cmd == 's'? &mval: &msrc)); 3157 if( termch != '\n' ) 3158 termch = 0; 3159 scanhex((void *)&mcount); 3160 switch( cmd ){ 3161 case 'm': 3162 if (xmon_is_ro) { 3163 printf(xmon_ro_msg); 3164 break; 3165 } 3166 memmove((void *)mdest, (void *)msrc, mcount); 3167 break; 3168 case 's': 3169 if (xmon_is_ro) { 3170 printf(xmon_ro_msg); 3171 break; 3172 } 3173 memset((void *)mdest, mval, mcount); 3174 break; 3175 case 'd': 3176 if( termch != '\n' ) 3177 termch = 0; 3178 scanhex((void *)&mdiffs); 3179 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs); 3180 break; 3181 } 3182} 3183 3184static void 3185memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr) 3186{ 3187 unsigned n, prt; 3188 3189 prt = 0; 3190 for( n = nb; n > 0; --n ) 3191 if( *p1++ != *p2++ ) 3192 if( ++prt <= maxpr ) 3193 printf("%px %.2x # %px %.2x\n", p1 - 1, 3194 p1[-1], p2 - 1, p2[-1]); 3195 if( prt > maxpr ) 3196 printf("Total of %d differences\n", prt); 3197} 3198 3199static unsigned mend; 3200static unsigned mask; 3201 3202static void 3203memlocate(void) 3204{ 3205 unsigned a, n; 3206 unsigned char val[4]; 3207 3208 last_cmd = "ml"; 3209 scanhex((void *)&mdest); 3210 if (termch != '\n') { 3211 termch = 0; 3212 scanhex((void *)&mend); 3213 if (termch != '\n') { 3214 termch = 0; 3215 scanhex((void *)&mval); 3216 mask = ~0; 3217 if (termch != '\n') termch = 0; 3218 scanhex((void *)&mask); 3219 } 3220 } 3221 n = 0; 3222 for (a = mdest; a < mend; a += 4) { 3223 if (mread(a, val, 4) == 4 3224 && ((GETWORD(val) ^ mval) & mask) == 0) { 3225 printf("%.16x: %.16x\n", a, GETWORD(val)); 3226 if (++n >= 10) 3227 break; 3228 } 3229 } 3230} 3231 3232static unsigned long mskip = 0x1000; 3233static unsigned long mlim = 0xffffffff; 3234 3235static void 3236memzcan(void) 3237{ 3238 unsigned char v; 3239 unsigned a; 3240 int ok, ook; 3241 3242 scanhex(&mdest); 3243 if (termch != '\n') termch = 0; 3244 scanhex(&mskip); 3245 if (termch != '\n') termch = 0; 3246 scanhex(&mlim); 3247 ook = 0; 3248 for (a = mdest; a < mlim; a += mskip) { 3249 ok = mread(a, &v, 1); 3250 if (ok && !ook) { 3251 printf("%.8x .. ", a); 3252 } else if (!ok && ook) 3253 printf("%.8lx\n", a - mskip); 3254 ook = ok; 3255 if (a + mskip < a) 3256 break; 3257 } 3258 if (ook) 3259 printf("%.8lx\n", a - mskip); 3260} 3261 3262static void show_task(struct task_struct *volatile tsk) 3263{ 3264 unsigned int p_state = READ_ONCE(tsk->__state); 3265 char state; 3266 3267 /* 3268 * Cloned from kdb_task_state_char(), which is not entirely 3269 * appropriate for calling from xmon. This could be moved 3270 * to a common, generic, routine used by both. 3271 */ 3272 state = (p_state == TASK_RUNNING) ? 'R' : 3273 (p_state & TASK_UNINTERRUPTIBLE) ? 'D' : 3274 (p_state & TASK_STOPPED) ? 'T' : 3275 (p_state & TASK_TRACED) ? 'C' : 3276 (tsk->exit_state & EXIT_ZOMBIE) ? 'Z' : 3277 (tsk->exit_state & EXIT_DEAD) ? 'E' : 3278 (p_state & TASK_INTERRUPTIBLE) ? 'S' : '?'; 3279 3280 printf("%16px %16lx %16px %6d %6d %c %2d %s\n", tsk, 3281 tsk->thread.ksp, tsk->thread.regs, 3282 tsk->pid, rcu_dereference(tsk->parent)->pid, 3283 state, task_cpu(tsk), 3284 tsk->comm); 3285} 3286 3287#ifdef CONFIG_PPC_BOOK3S_64 3288static void format_pte(void *ptep, unsigned long pte) 3289{ 3290 pte_t entry = __pte(pte); 3291 3292 printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte); 3293 printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK); 3294 3295 printf("Flags = %s%s%s%s%s\n", 3296 pte_young(entry) ? "Accessed " : "", 3297 pte_dirty(entry) ? "Dirty " : "", 3298 pte_read(entry) ? "Read " : "", 3299 pte_write(entry) ? "Write " : "", 3300 pte_exec(entry) ? "Exec " : ""); 3301} 3302 3303static void show_pte(unsigned long addr) 3304{ 3305 unsigned long tskv = 0; 3306 struct task_struct *volatile tsk = NULL; 3307 struct mm_struct *mm; 3308 pgd_t *pgdp; 3309 p4d_t *p4dp; 3310 pud_t *pudp; 3311 pmd_t *pmdp; 3312 pte_t *ptep; 3313 3314 if (!scanhex(&tskv)) 3315 mm = &init_mm; 3316 else 3317 tsk = (struct task_struct *)tskv; 3318 3319 if (tsk == NULL) 3320 mm = &init_mm; 3321 else 3322 mm = tsk->active_mm; 3323 3324 if (setjmp(bus_error_jmp) != 0) { 3325 catch_memory_errors = 0; 3326 printf("*** Error dumping pte for task %px\n", tsk); 3327 return; 3328 } 3329 3330 catch_memory_errors = 1; 3331 sync(); 3332 3333 if (mm == &init_mm) 3334 pgdp = pgd_offset_k(addr); 3335 else 3336 pgdp = pgd_offset(mm, addr); 3337 3338 p4dp = p4d_offset(pgdp, addr); 3339 3340 if (p4d_none(*p4dp)) { 3341 printf("No valid P4D\n"); 3342 return; 3343 } 3344 3345 if (p4d_is_leaf(*p4dp)) { 3346 format_pte(p4dp, p4d_val(*p4dp)); 3347 return; 3348 } 3349 3350 printf("p4dp @ 0x%px = 0x%016lx\n", p4dp, p4d_val(*p4dp)); 3351 3352 pudp = pud_offset(p4dp, addr); 3353 3354 if (pud_none(*pudp)) { 3355 printf("No valid PUD\n"); 3356 return; 3357 } 3358 3359 if (pud_is_leaf(*pudp)) { 3360 format_pte(pudp, pud_val(*pudp)); 3361 return; 3362 } 3363 3364 printf("pudp @ 0x%px = 0x%016lx\n", pudp, pud_val(*pudp)); 3365 3366 pmdp = pmd_offset(pudp, addr); 3367 3368 if (pmd_none(*pmdp)) { 3369 printf("No valid PMD\n"); 3370 return; 3371 } 3372 3373 if (pmd_is_leaf(*pmdp)) { 3374 format_pte(pmdp, pmd_val(*pmdp)); 3375 return; 3376 } 3377 printf("pmdp @ 0x%px = 0x%016lx\n", pmdp, pmd_val(*pmdp)); 3378 3379 ptep = pte_offset_map(pmdp, addr); 3380 if (pte_none(*ptep)) { 3381 printf("no valid PTE\n"); 3382 return; 3383 } 3384 3385 format_pte(ptep, pte_val(*ptep)); 3386 3387 sync(); 3388 __delay(200); 3389 catch_memory_errors = 0; 3390} 3391#else 3392static void show_pte(unsigned long addr) 3393{ 3394 printf("show_pte not yet implemented\n"); 3395} 3396#endif /* CONFIG_PPC_BOOK3S_64 */ 3397 3398static void show_tasks(void) 3399{ 3400 unsigned long tskv; 3401 struct task_struct *volatile tsk = NULL; 3402 3403 printf(" task_struct ->thread.ksp ->thread.regs PID PPID S P CMD\n"); 3404 3405 if (scanhex(&tskv)) 3406 tsk = (struct task_struct *)tskv; 3407 3408 if (setjmp(bus_error_jmp) != 0) { 3409 catch_memory_errors = 0; 3410 printf("*** Error dumping task %px\n", tsk); 3411 return; 3412 } 3413 3414 catch_memory_errors = 1; 3415 sync(); 3416 3417 if (tsk) 3418 show_task(tsk); 3419 else 3420 for_each_process(tsk) 3421 show_task(tsk); 3422 3423 sync(); 3424 __delay(200); 3425 catch_memory_errors = 0; 3426} 3427 3428static void proccall(void) 3429{ 3430 unsigned long args[8]; 3431 unsigned long ret; 3432 int i; 3433 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long, 3434 unsigned long, unsigned long, unsigned long, 3435 unsigned long, unsigned long, unsigned long); 3436 callfunc_t func; 3437 3438 if (!scanhex(&adrs)) 3439 return; 3440 if (termch != '\n') 3441 termch = 0; 3442 for (i = 0; i < 8; ++i) 3443 args[i] = 0; 3444 for (i = 0; i < 8; ++i) { 3445 if (!scanhex(&args[i]) || termch == '\n') 3446 break; 3447 termch = 0; 3448 } 3449 func = (callfunc_t) adrs; 3450 ret = 0; 3451 if (setjmp(bus_error_jmp) == 0) { 3452 catch_memory_errors = 1; 3453 sync(); 3454 ret = func(args[0], args[1], args[2], args[3], 3455 args[4], args[5], args[6], args[7]); 3456 sync(); 3457 printf("return value is 0x%lx\n", ret); 3458 } else { 3459 printf("*** %x exception occurred\n", fault_except); 3460 } 3461 catch_memory_errors = 0; 3462} 3463 3464/* Input scanning routines */ 3465int 3466skipbl(void) 3467{ 3468 int c; 3469 3470 if( termch != 0 ){ 3471 c = termch; 3472 termch = 0; 3473 } else 3474 c = inchar(); 3475 while( c == ' ' || c == '\t' ) 3476 c = inchar(); 3477 return c; 3478} 3479 3480#define N_PTREGS 44 3481static const char *regnames[N_PTREGS] = { 3482 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 3483 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 3484 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 3485 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 3486 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", 3487#ifdef CONFIG_PPC64 3488 "softe", 3489#else 3490 "mq", 3491#endif 3492 "trap", "dar", "dsisr", "res" 3493}; 3494 3495int 3496scanhex(unsigned long *vp) 3497{ 3498 int c, d; 3499 unsigned long v; 3500 3501 c = skipbl(); 3502 if (c == '%') { 3503 /* parse register name */ 3504 char regname[8]; 3505 int i; 3506 3507 for (i = 0; i < sizeof(regname) - 1; ++i) { 3508 c = inchar(); 3509 if (!isalnum(c)) { 3510 termch = c; 3511 break; 3512 } 3513 regname[i] = c; 3514 } 3515 regname[i] = 0; 3516 i = match_string(regnames, N_PTREGS, regname); 3517 if (i < 0) { 3518 printf("invalid register name '%%%s'\n", regname); 3519 return 0; 3520 } 3521 if (xmon_regs == NULL) { 3522 printf("regs not available\n"); 3523 return 0; 3524 } 3525 *vp = ((unsigned long *)xmon_regs)[i]; 3526 return 1; 3527 } 3528 3529 /* skip leading "0x" if any */ 3530 3531 if (c == '0') { 3532 c = inchar(); 3533 if (c == 'x') { 3534 c = inchar(); 3535 } else { 3536 d = hexdigit(c); 3537 if (d == EOF) { 3538 termch = c; 3539 *vp = 0; 3540 return 1; 3541 } 3542 } 3543 } else if (c == '$') { 3544 int i; 3545 for (i=0; i<63; i++) { 3546 c = inchar(); 3547 if (isspace(c) || c == '\0') { 3548 termch = c; 3549 break; 3550 } 3551 tmpstr[i] = c; 3552 } 3553 tmpstr[i++] = 0; 3554 *vp = 0; 3555 if (setjmp(bus_error_jmp) == 0) { 3556 catch_memory_errors = 1; 3557 sync(); 3558 *vp = kallsyms_lookup_name(tmpstr); 3559 sync(); 3560 } 3561 catch_memory_errors = 0; 3562 if (!(*vp)) { 3563 printf("unknown symbol '%s'\n", tmpstr); 3564 return 0; 3565 } 3566 return 1; 3567 } 3568 3569 d = hexdigit(c); 3570 if (d == EOF) { 3571 termch = c; 3572 return 0; 3573 } 3574 v = 0; 3575 do { 3576 v = (v << 4) + d; 3577 c = inchar(); 3578 d = hexdigit(c); 3579 } while (d != EOF); 3580 termch = c; 3581 *vp = v; 3582 return 1; 3583} 3584 3585static void 3586scannl(void) 3587{ 3588 int c; 3589 3590 c = termch; 3591 termch = 0; 3592 while( c != '\n' ) 3593 c = inchar(); 3594} 3595 3596static int hexdigit(int c) 3597{ 3598 if( '0' <= c && c <= '9' ) 3599 return c - '0'; 3600 if( 'A' <= c && c <= 'F' ) 3601 return c - ('A' - 10); 3602 if( 'a' <= c && c <= 'f' ) 3603 return c - ('a' - 10); 3604 return EOF; 3605} 3606 3607void 3608getstring(char *s, int size) 3609{ 3610 int c; 3611 3612 c = skipbl(); 3613 if (c == '\n') { 3614 *s = 0; 3615 return; 3616 } 3617 3618 do { 3619 if( size > 1 ){ 3620 *s++ = c; 3621 --size; 3622 } 3623 c = inchar(); 3624 } while( c != ' ' && c != '\t' && c != '\n' ); 3625 termch = c; 3626 *s = 0; 3627} 3628 3629static char line[256]; 3630static char *lineptr; 3631 3632static void 3633flush_input(void) 3634{ 3635 lineptr = NULL; 3636} 3637 3638static int 3639inchar(void) 3640{ 3641 if (lineptr == NULL || *lineptr == 0) { 3642 if (xmon_gets(line, sizeof(line)) == NULL) { 3643 lineptr = NULL; 3644 return EOF; 3645 } 3646 lineptr = line; 3647 } 3648 return *lineptr++; 3649} 3650 3651static void 3652take_input(char *str) 3653{ 3654 lineptr = str; 3655} 3656 3657 3658static void 3659symbol_lookup(void) 3660{ 3661 int type = inchar(); 3662 unsigned long addr, cpu; 3663 void __percpu *ptr = NULL; 3664 static char tmp[64]; 3665 3666 switch (type) { 3667 case 'a': 3668 if (scanhex(&addr)) 3669 xmon_print_symbol(addr, ": ", "\n"); 3670 termch = 0; 3671 break; 3672 case 's': 3673 getstring(tmp, 64); 3674 if (setjmp(bus_error_jmp) == 0) { 3675 catch_memory_errors = 1; 3676 sync(); 3677 addr = kallsyms_lookup_name(tmp); 3678 if (addr) 3679 printf("%s: %lx\n", tmp, addr); 3680 else 3681 printf("Symbol '%s' not found.\n", tmp); 3682 sync(); 3683 } 3684 catch_memory_errors = 0; 3685 termch = 0; 3686 break; 3687 case 'p': 3688 getstring(tmp, 64); 3689 if (setjmp(bus_error_jmp) == 0) { 3690 catch_memory_errors = 1; 3691 sync(); 3692 ptr = (void __percpu *)kallsyms_lookup_name(tmp); 3693 sync(); 3694 } 3695 3696 if (ptr && 3697 ptr >= (void __percpu *)__per_cpu_start && 3698 ptr < (void __percpu *)__per_cpu_end) 3699 { 3700 if (scanhex(&cpu) && cpu < num_possible_cpus()) { 3701 addr = (unsigned long)per_cpu_ptr(ptr, cpu); 3702 } else { 3703 cpu = raw_smp_processor_id(); 3704 addr = (unsigned long)this_cpu_ptr(ptr); 3705 } 3706 3707 printf("%s for cpu 0x%lx: %lx\n", tmp, cpu, addr); 3708 } else { 3709 printf("Percpu symbol '%s' not found.\n", tmp); 3710 } 3711 3712 catch_memory_errors = 0; 3713 termch = 0; 3714 break; 3715 } 3716} 3717 3718 3719/* Print an address in numeric and symbolic form (if possible) */ 3720static void xmon_print_symbol(unsigned long address, const char *mid, 3721 const char *after) 3722{ 3723 char *modname; 3724 const char *volatile name = NULL; 3725 unsigned long offset, size; 3726 3727 printf(REG, address); 3728 if (setjmp(bus_error_jmp) == 0) { 3729 catch_memory_errors = 1; 3730 sync(); 3731 name = kallsyms_lookup(address, &size, &offset, &modname, 3732 tmpstr); 3733 sync(); 3734 /* wait a little while to see if we get a machine check */ 3735 __delay(200); 3736 } 3737 3738 catch_memory_errors = 0; 3739 3740 if (name) { 3741 printf("%s%s+%#lx/%#lx", mid, name, offset, size); 3742 if (modname) 3743 printf(" [%s]", modname); 3744 } 3745 printf("%s", after); 3746} 3747 3748#ifdef CONFIG_PPC_64S_HASH_MMU 3749void dump_segments(void) 3750{ 3751 int i; 3752 unsigned long esid,vsid; 3753 unsigned long llp; 3754 3755 printf("SLB contents of cpu 0x%x\n", smp_processor_id()); 3756 3757 for (i = 0; i < mmu_slb_size; i++) { 3758 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i)); 3759 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i)); 3760 3761 if (!esid && !vsid) 3762 continue; 3763 3764 printf("%02d %016lx %016lx", i, esid, vsid); 3765 3766 if (!(esid & SLB_ESID_V)) { 3767 printf("\n"); 3768 continue; 3769 } 3770 3771 llp = vsid & SLB_VSID_LLP; 3772 if (vsid & SLB_VSID_B_1T) { 3773 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n", 3774 GET_ESID_1T(esid), 3775 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T, 3776 llp); 3777 } else { 3778 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n", 3779 GET_ESID(esid), 3780 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT, 3781 llp); 3782 } 3783 } 3784} 3785#endif 3786 3787#ifdef CONFIG_PPC_BOOK3S_32 3788void dump_segments(void) 3789{ 3790 int i; 3791 3792 printf("sr0-15 ="); 3793 for (i = 0; i < 16; ++i) 3794 printf(" %x", mfsr(i << 28)); 3795 printf("\n"); 3796} 3797#endif 3798 3799#ifdef CONFIG_44x 3800static void dump_tlb_44x(void) 3801{ 3802 int i; 3803 3804 for (i = 0; i < PPC44x_TLB_SIZE; i++) { 3805 unsigned long w0,w1,w2; 3806 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i)); 3807 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i)); 3808 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i)); 3809 printf("[%02x] %08lx %08lx %08lx ", i, w0, w1, w2); 3810 if (w0 & PPC44x_TLB_VALID) { 3811 printf("V %08lx -> %01lx%08lx %c%c%c%c%c", 3812 w0 & PPC44x_TLB_EPN_MASK, 3813 w1 & PPC44x_TLB_ERPN_MASK, 3814 w1 & PPC44x_TLB_RPN_MASK, 3815 (w2 & PPC44x_TLB_W) ? 'W' : 'w', 3816 (w2 & PPC44x_TLB_I) ? 'I' : 'i', 3817 (w2 & PPC44x_TLB_M) ? 'M' : 'm', 3818 (w2 & PPC44x_TLB_G) ? 'G' : 'g', 3819 (w2 & PPC44x_TLB_E) ? 'E' : 'e'); 3820 } 3821 printf("\n"); 3822 } 3823} 3824#endif /* CONFIG_44x */ 3825 3826#ifdef CONFIG_PPC_BOOK3E 3827static void dump_tlb_book3e(void) 3828{ 3829 u32 mmucfg, pidmask, lpidmask; 3830 u64 ramask; 3831 int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0; 3832 int mmu_version; 3833 static const char *pgsz_names[] = { 3834 " 1K", 3835 " 2K", 3836 " 4K", 3837 " 8K", 3838 " 16K", 3839 " 32K", 3840 " 64K", 3841 "128K", 3842 "256K", 3843 "512K", 3844 " 1M", 3845 " 2M", 3846 " 4M", 3847 " 8M", 3848 " 16M", 3849 " 32M", 3850 " 64M", 3851 "128M", 3852 "256M", 3853 "512M", 3854 " 1G", 3855 " 2G", 3856 " 4G", 3857 " 8G", 3858 " 16G", 3859 " 32G", 3860 " 64G", 3861 "128G", 3862 "256G", 3863 "512G", 3864 " 1T", 3865 " 2T", 3866 }; 3867 3868 /* Gather some infos about the MMU */ 3869 mmucfg = mfspr(SPRN_MMUCFG); 3870 mmu_version = (mmucfg & 3) + 1; 3871 ntlbs = ((mmucfg >> 2) & 3) + 1; 3872 pidsz = ((mmucfg >> 6) & 0x1f) + 1; 3873 lpidsz = (mmucfg >> 24) & 0xf; 3874 rasz = (mmucfg >> 16) & 0x7f; 3875 if ((mmu_version > 1) && (mmucfg & 0x10000)) 3876 lrat = 1; 3877 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n", 3878 mmu_version, ntlbs, pidsz, lpidsz, rasz); 3879 pidmask = (1ul << pidsz) - 1; 3880 lpidmask = (1ul << lpidsz) - 1; 3881 ramask = (1ull << rasz) - 1; 3882 3883 for (tlb = 0; tlb < ntlbs; tlb++) { 3884 u32 tlbcfg; 3885 int nent, assoc, new_cc = 1; 3886 printf("TLB %d:\n------\n", tlb); 3887 switch(tlb) { 3888 case 0: 3889 tlbcfg = mfspr(SPRN_TLB0CFG); 3890 break; 3891 case 1: 3892 tlbcfg = mfspr(SPRN_TLB1CFG); 3893 break; 3894 case 2: 3895 tlbcfg = mfspr(SPRN_TLB2CFG); 3896 break; 3897 case 3: 3898 tlbcfg = mfspr(SPRN_TLB3CFG); 3899 break; 3900 default: 3901 printf("Unsupported TLB number !\n"); 3902 continue; 3903 } 3904 nent = tlbcfg & 0xfff; 3905 assoc = (tlbcfg >> 24) & 0xff; 3906 for (i = 0; i < nent; i++) { 3907 u32 mas0 = MAS0_TLBSEL(tlb); 3908 u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K); 3909 u64 mas2 = 0; 3910 u64 mas7_mas3; 3911 int esel = i, cc = i; 3912 3913 if (assoc != 0) { 3914 cc = i / assoc; 3915 esel = i % assoc; 3916 mas2 = cc * 0x1000; 3917 } 3918 3919 mas0 |= MAS0_ESEL(esel); 3920 mtspr(SPRN_MAS0, mas0); 3921 mtspr(SPRN_MAS1, mas1); 3922 mtspr(SPRN_MAS2, mas2); 3923 asm volatile("tlbre 0,0,0" : : : "memory"); 3924 mas1 = mfspr(SPRN_MAS1); 3925 mas2 = mfspr(SPRN_MAS2); 3926 mas7_mas3 = mfspr(SPRN_MAS7_MAS3); 3927 if (assoc && (i % assoc) == 0) 3928 new_cc = 1; 3929 if (!(mas1 & MAS1_VALID)) 3930 continue; 3931 if (assoc == 0) 3932 printf("%04x- ", i); 3933 else if (new_cc) 3934 printf("%04x-%c", cc, 'A' + esel); 3935 else 3936 printf(" |%c", 'A' + esel); 3937 new_cc = 0; 3938 printf(" %016llx %04x %s %c%c AS%c", 3939 mas2 & ~0x3ffull, 3940 (mas1 >> 16) & 0x3fff, 3941 pgsz_names[(mas1 >> 7) & 0x1f], 3942 mas1 & MAS1_IND ? 'I' : ' ', 3943 mas1 & MAS1_IPROT ? 'P' : ' ', 3944 mas1 & MAS1_TS ? '1' : '0'); 3945 printf(" %c%c%c%c%c%c%c", 3946 mas2 & MAS2_X0 ? 'a' : ' ', 3947 mas2 & MAS2_X1 ? 'v' : ' ', 3948 mas2 & MAS2_W ? 'w' : ' ', 3949 mas2 & MAS2_I ? 'i' : ' ', 3950 mas2 & MAS2_M ? 'm' : ' ', 3951 mas2 & MAS2_G ? 'g' : ' ', 3952 mas2 & MAS2_E ? 'e' : ' '); 3953 printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull); 3954 if (mas1 & MAS1_IND) 3955 printf(" %s\n", 3956 pgsz_names[(mas7_mas3 >> 1) & 0x1f]); 3957 else 3958 printf(" U%c%c%c S%c%c%c\n", 3959 mas7_mas3 & MAS3_UX ? 'x' : ' ', 3960 mas7_mas3 & MAS3_UW ? 'w' : ' ', 3961 mas7_mas3 & MAS3_UR ? 'r' : ' ', 3962 mas7_mas3 & MAS3_SX ? 'x' : ' ', 3963 mas7_mas3 & MAS3_SW ? 'w' : ' ', 3964 mas7_mas3 & MAS3_SR ? 'r' : ' '); 3965 } 3966 } 3967} 3968#endif /* CONFIG_PPC_BOOK3E */ 3969 3970static void xmon_init(int enable) 3971{ 3972 if (enable) { 3973 __debugger = xmon; 3974 __debugger_ipi = xmon_ipi; 3975 __debugger_bpt = xmon_bpt; 3976 __debugger_sstep = xmon_sstep; 3977 __debugger_iabr_match = xmon_iabr_match; 3978 __debugger_break_match = xmon_break_match; 3979 __debugger_fault_handler = xmon_fault_handler; 3980 3981#ifdef CONFIG_PPC_PSERIES 3982 /* 3983 * Get the token here to avoid trying to get a lock 3984 * during the crash, causing a deadlock. 3985 */ 3986 set_indicator_token = rtas_token("set-indicator"); 3987#endif 3988 } else { 3989 __debugger = NULL; 3990 __debugger_ipi = NULL; 3991 __debugger_bpt = NULL; 3992 __debugger_sstep = NULL; 3993 __debugger_iabr_match = NULL; 3994 __debugger_break_match = NULL; 3995 __debugger_fault_handler = NULL; 3996 } 3997} 3998 3999#ifdef CONFIG_MAGIC_SYSRQ 4000static void sysrq_handle_xmon(int key) 4001{ 4002 if (xmon_is_locked_down()) { 4003 clear_all_bpt(); 4004 xmon_init(0); 4005 return; 4006 } 4007 /* ensure xmon is enabled */ 4008 xmon_init(1); 4009 debugger(get_irq_regs()); 4010 if (!xmon_on) 4011 xmon_init(0); 4012} 4013 4014static const struct sysrq_key_op sysrq_xmon_op = { 4015 .handler = sysrq_handle_xmon, 4016 .help_msg = "xmon(x)", 4017 .action_msg = "Entering xmon", 4018}; 4019 4020static int __init setup_xmon_sysrq(void) 4021{ 4022 register_sysrq_key('x', &sysrq_xmon_op); 4023 return 0; 4024} 4025device_initcall(setup_xmon_sysrq); 4026#endif /* CONFIG_MAGIC_SYSRQ */ 4027 4028static void clear_all_bpt(void) 4029{ 4030 int i; 4031 4032 /* clear/unpatch all breakpoints */ 4033 remove_bpts(); 4034 remove_cpu_bpts(); 4035 4036 /* Disable all breakpoints */ 4037 for (i = 0; i < NBPTS; ++i) 4038 bpts[i].enabled = 0; 4039 4040 /* Clear any data or iabr breakpoints */ 4041 iabr = NULL; 4042 for (i = 0; i < nr_wp_slots(); i++) 4043 dabr[i].enabled = 0; 4044} 4045 4046#ifdef CONFIG_DEBUG_FS 4047static int xmon_dbgfs_set(void *data, u64 val) 4048{ 4049 xmon_on = !!val; 4050 xmon_init(xmon_on); 4051 4052 /* make sure all breakpoints removed when disabling */ 4053 if (!xmon_on) { 4054 clear_all_bpt(); 4055 get_output_lock(); 4056 printf("xmon: All breakpoints cleared\n"); 4057 release_output_lock(); 4058 } 4059 4060 return 0; 4061} 4062 4063static int xmon_dbgfs_get(void *data, u64 *val) 4064{ 4065 *val = xmon_on; 4066 return 0; 4067} 4068 4069DEFINE_SIMPLE_ATTRIBUTE(xmon_dbgfs_ops, xmon_dbgfs_get, 4070 xmon_dbgfs_set, "%llu\n"); 4071 4072static int __init setup_xmon_dbgfs(void) 4073{ 4074 debugfs_create_file("xmon", 0600, arch_debugfs_dir, NULL, 4075 &xmon_dbgfs_ops); 4076 return 0; 4077} 4078device_initcall(setup_xmon_dbgfs); 4079#endif /* CONFIG_DEBUG_FS */ 4080 4081static int xmon_early __initdata; 4082 4083static int __init early_parse_xmon(char *p) 4084{ 4085 if (xmon_is_locked_down()) { 4086 xmon_init(0); 4087 xmon_early = 0; 4088 xmon_on = 0; 4089 } else if (!p || strncmp(p, "early", 5) == 0) { 4090 /* just "xmon" is equivalent to "xmon=early" */ 4091 xmon_init(1); 4092 xmon_early = 1; 4093 xmon_on = 1; 4094 } else if (strncmp(p, "on", 2) == 0) { 4095 xmon_init(1); 4096 xmon_on = 1; 4097 } else if (strncmp(p, "rw", 2) == 0) { 4098 xmon_init(1); 4099 xmon_on = 1; 4100 xmon_is_ro = false; 4101 } else if (strncmp(p, "ro", 2) == 0) { 4102 xmon_init(1); 4103 xmon_on = 1; 4104 xmon_is_ro = true; 4105 } else if (strncmp(p, "off", 3) == 0) 4106 xmon_on = 0; 4107 else 4108 return 1; 4109 4110 return 0; 4111} 4112early_param("xmon", early_parse_xmon); 4113 4114void __init xmon_setup(void) 4115{ 4116 if (xmon_on) 4117 xmon_init(1); 4118 if (xmon_early) 4119 debugger(NULL); 4120} 4121 4122#ifdef CONFIG_SPU_BASE 4123 4124struct spu_info { 4125 struct spu *spu; 4126 u64 saved_mfc_sr1_RW; 4127 u32 saved_spu_runcntl_RW; 4128 unsigned long dump_addr; 4129 u8 stopped_ok; 4130}; 4131 4132#define XMON_NUM_SPUS 16 /* Enough for current hardware */ 4133 4134static struct spu_info spu_info[XMON_NUM_SPUS]; 4135 4136void __init xmon_register_spus(struct list_head *list) 4137{ 4138 struct spu *spu; 4139 4140 list_for_each_entry(spu, list, full_list) { 4141 if (spu->number >= XMON_NUM_SPUS) { 4142 WARN_ON(1); 4143 continue; 4144 } 4145 4146 spu_info[spu->number].spu = spu; 4147 spu_info[spu->number].stopped_ok = 0; 4148 spu_info[spu->number].dump_addr = (unsigned long) 4149 spu_info[spu->number].spu->local_store; 4150 } 4151} 4152 4153static void stop_spus(void) 4154{ 4155 struct spu *spu; 4156 volatile int i; 4157 u64 tmp; 4158 4159 for (i = 0; i < XMON_NUM_SPUS; i++) { 4160 if (!spu_info[i].spu) 4161 continue; 4162 4163 if (setjmp(bus_error_jmp) == 0) { 4164 catch_memory_errors = 1; 4165 sync(); 4166 4167 spu = spu_info[i].spu; 4168 4169 spu_info[i].saved_spu_runcntl_RW = 4170 in_be32(&spu->problem->spu_runcntl_RW); 4171 4172 tmp = spu_mfc_sr1_get(spu); 4173 spu_info[i].saved_mfc_sr1_RW = tmp; 4174 4175 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; 4176 spu_mfc_sr1_set(spu, tmp); 4177 4178 sync(); 4179 __delay(200); 4180 4181 spu_info[i].stopped_ok = 1; 4182 4183 printf("Stopped spu %.2d (was %s)\n", i, 4184 spu_info[i].saved_spu_runcntl_RW ? 4185 "running" : "stopped"); 4186 } else { 4187 catch_memory_errors = 0; 4188 printf("*** Error stopping spu %.2d\n", i); 4189 } 4190 catch_memory_errors = 0; 4191 } 4192} 4193 4194static void restart_spus(void) 4195{ 4196 struct spu *spu; 4197 volatile int i; 4198 4199 for (i = 0; i < XMON_NUM_SPUS; i++) { 4200 if (!spu_info[i].spu) 4201 continue; 4202 4203 if (!spu_info[i].stopped_ok) { 4204 printf("*** Error, spu %d was not successfully stopped" 4205 ", not restarting\n", i); 4206 continue; 4207 } 4208 4209 if (setjmp(bus_error_jmp) == 0) { 4210 catch_memory_errors = 1; 4211 sync(); 4212 4213 spu = spu_info[i].spu; 4214 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW); 4215 out_be32(&spu->problem->spu_runcntl_RW, 4216 spu_info[i].saved_spu_runcntl_RW); 4217 4218 sync(); 4219 __delay(200); 4220 4221 printf("Restarted spu %.2d\n", i); 4222 } else { 4223 catch_memory_errors = 0; 4224 printf("*** Error restarting spu %.2d\n", i); 4225 } 4226 catch_memory_errors = 0; 4227 } 4228} 4229 4230#define DUMP_WIDTH 23 4231#define DUMP_VALUE(format, field, value) \ 4232do { \ 4233 if (setjmp(bus_error_jmp) == 0) { \ 4234 catch_memory_errors = 1; \ 4235 sync(); \ 4236 printf(" %-*s = "format"\n", DUMP_WIDTH, \ 4237 #field, value); \ 4238 sync(); \ 4239 __delay(200); \ 4240 } else { \ 4241 catch_memory_errors = 0; \ 4242 printf(" %-*s = *** Error reading field.\n", \ 4243 DUMP_WIDTH, #field); \ 4244 } \ 4245 catch_memory_errors = 0; \ 4246} while (0) 4247 4248#define DUMP_FIELD(obj, format, field) \ 4249 DUMP_VALUE(format, field, obj->field) 4250 4251static void dump_spu_fields(struct spu *spu) 4252{ 4253 printf("Dumping spu fields at address %p:\n", spu); 4254 4255 DUMP_FIELD(spu, "0x%x", number); 4256 DUMP_FIELD(spu, "%s", name); 4257 DUMP_FIELD(spu, "0x%lx", local_store_phys); 4258 DUMP_FIELD(spu, "0x%p", local_store); 4259 DUMP_FIELD(spu, "0x%lx", ls_size); 4260 DUMP_FIELD(spu, "0x%x", node); 4261 DUMP_FIELD(spu, "0x%lx", flags); 4262 DUMP_FIELD(spu, "%llu", class_0_pending); 4263 DUMP_FIELD(spu, "0x%llx", class_0_dar); 4264 DUMP_FIELD(spu, "0x%llx", class_1_dar); 4265 DUMP_FIELD(spu, "0x%llx", class_1_dsisr); 4266 DUMP_FIELD(spu, "0x%x", irqs[0]); 4267 DUMP_FIELD(spu, "0x%x", irqs[1]); 4268 DUMP_FIELD(spu, "0x%x", irqs[2]); 4269 DUMP_FIELD(spu, "0x%x", slb_replace); 4270 DUMP_FIELD(spu, "%d", pid); 4271 DUMP_FIELD(spu, "0x%p", mm); 4272 DUMP_FIELD(spu, "0x%p", ctx); 4273 DUMP_FIELD(spu, "0x%p", rq); 4274 DUMP_FIELD(spu, "0x%llx", timestamp); 4275 DUMP_FIELD(spu, "0x%lx", problem_phys); 4276 DUMP_FIELD(spu, "0x%p", problem); 4277 DUMP_VALUE("0x%x", problem->spu_runcntl_RW, 4278 in_be32(&spu->problem->spu_runcntl_RW)); 4279 DUMP_VALUE("0x%x", problem->spu_status_R, 4280 in_be32(&spu->problem->spu_status_R)); 4281 DUMP_VALUE("0x%x", problem->spu_npc_RW, 4282 in_be32(&spu->problem->spu_npc_RW)); 4283 DUMP_FIELD(spu, "0x%p", priv2); 4284 DUMP_FIELD(spu, "0x%p", pdata); 4285} 4286 4287static int spu_inst_dump(unsigned long adr, long count, int praddr) 4288{ 4289 return generic_inst_dump(adr, count, praddr, print_insn_spu); 4290} 4291 4292static void dump_spu_ls(unsigned long num, int subcmd) 4293{ 4294 unsigned long offset, addr, ls_addr; 4295 4296 if (setjmp(bus_error_jmp) == 0) { 4297 catch_memory_errors = 1; 4298 sync(); 4299 ls_addr = (unsigned long)spu_info[num].spu->local_store; 4300 sync(); 4301 __delay(200); 4302 } else { 4303 catch_memory_errors = 0; 4304 printf("*** Error: accessing spu info for spu %ld\n", num); 4305 return; 4306 } 4307 catch_memory_errors = 0; 4308 4309 if (scanhex(&offset)) 4310 addr = ls_addr + offset; 4311 else 4312 addr = spu_info[num].dump_addr; 4313 4314 if (addr >= ls_addr + LS_SIZE) { 4315 printf("*** Error: address outside of local store\n"); 4316 return; 4317 } 4318 4319 switch (subcmd) { 4320 case 'i': 4321 addr += spu_inst_dump(addr, 16, 1); 4322 last_cmd = "sdi\n"; 4323 break; 4324 default: 4325 prdump(addr, 64); 4326 addr += 64; 4327 last_cmd = "sd\n"; 4328 break; 4329 } 4330 4331 spu_info[num].dump_addr = addr; 4332} 4333 4334static int do_spu_cmd(void) 4335{ 4336 static unsigned long num = 0; 4337 int cmd, subcmd = 0; 4338 4339 cmd = inchar(); 4340 switch (cmd) { 4341 case 's': 4342 stop_spus(); 4343 break; 4344 case 'r': 4345 restart_spus(); 4346 break; 4347 case 'd': 4348 subcmd = inchar(); 4349 if (isxdigit(subcmd) || subcmd == '\n') 4350 termch = subcmd; 4351 fallthrough; 4352 case 'f': 4353 scanhex(&num); 4354 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) { 4355 printf("*** Error: invalid spu number\n"); 4356 return 0; 4357 } 4358 4359 switch (cmd) { 4360 case 'f': 4361 dump_spu_fields(spu_info[num].spu); 4362 break; 4363 default: 4364 dump_spu_ls(num, subcmd); 4365 break; 4366 } 4367 4368 break; 4369 default: 4370 return -1; 4371 } 4372 4373 return 0; 4374} 4375#else /* ! CONFIG_SPU_BASE */ 4376static int do_spu_cmd(void) 4377{ 4378 return -1; 4379} 4380#endif