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