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