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