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