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