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