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