linux/arch/ppc/xmon/xmon.c
<<
>>
Prefs
   1/*
   2 * Routines providing a simple monitor for use on the PowerMac.
   3 *
   4 * Copyright (C) 1996 Paul Mackerras.
   5 */
   6#include <linux/errno.h>
   7#include <linux/sched.h>
   8#include <linux/smp.h>
   9#include <linux/interrupt.h>
  10#include <linux/bitops.h>
  11#include <linux/kallsyms.h>
  12#include <asm/ptrace.h>
  13#include <asm/string.h>
  14#include <asm/machdep.h>
  15#include <asm/xmon.h>
  16#include "nonstdio.h"
  17#include "privinst.h"
  18
  19#define scanhex xmon_scanhex
  20#define skipbl  xmon_skipbl
  21
  22#ifdef CONFIG_SMP
  23static unsigned long cpus_in_xmon = 0;
  24static unsigned long got_xmon = 0;
  25static volatile int take_xmon = -1;
  26#endif /* CONFIG_SMP */
  27
  28static unsigned adrs;
  29static int size = 1;
  30static unsigned ndump = 64;
  31static unsigned nidump = 16;
  32static unsigned ncsum = 4096;
  33static int termch;
  34
  35static u_int bus_error_jmp[100];
  36#define setjmp xmon_setjmp
  37#define longjmp xmon_longjmp
  38
  39/* Breakpoint stuff */
  40struct bpt {
  41        unsigned address;
  42        unsigned instr;
  43        unsigned count;
  44        unsigned char enabled;
  45};
  46
  47#define NBPTS   16
  48static struct bpt bpts[NBPTS];
  49static struct bpt dabr;
  50static struct bpt iabr;
  51static unsigned bpinstr = 0x7fe00008;   /* trap */
  52
  53/* Prototypes */
  54extern void (*debugger_fault_handler)(struct pt_regs *);
  55static int cmds(struct pt_regs *);
  56static int mread(unsigned, void *, int);
  57static int mwrite(unsigned, void *, int);
  58static void handle_fault(struct pt_regs *);
  59static void byterev(unsigned char *, int);
  60static void memex(void);
  61static int bsesc(void);
  62static void dump(void);
  63static void prdump(unsigned, int);
  64#ifdef __MWERKS__
  65static void prndump(unsigned, int);
  66static int nvreadb(unsigned);
  67#endif
  68static int ppc_inst_dump(unsigned, int);
  69void print_address(unsigned);
  70static int getsp(void);
  71static void dump_hash_table(void);
  72static void backtrace(struct pt_regs *);
  73static void excprint(struct pt_regs *);
  74static void prregs(struct pt_regs *);
  75static void memops(int);
  76static void memlocate(void);
  77static void memzcan(void);
  78static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
  79int skipbl(void);
  80int scanhex(unsigned *valp);
  81static void scannl(void);
  82static int hexdigit(int);
  83void getstring(char *, int);
  84static void flush_input(void);
  85static int inchar(void);
  86static void take_input(char *);
  87/* static void openforth(void); */
  88static unsigned read_spr(int);
  89static void write_spr(int, unsigned);
  90static void super_regs(void);
  91static void symbol_lookup(void);
  92static void remove_bpts(void);
  93static void insert_bpts(void);
  94static struct bpt *at_breakpoint(unsigned pc);
  95static void bpt_cmds(void);
  96void cacheflush(void);
  97#ifdef CONFIG_SMP
  98static void cpu_cmd(void);
  99#endif /* CONFIG_SMP */
 100static void csum(void);
 101static void bootcmds(void);
 102static void proccall(void);
 103static void printtime(void);
 104
 105extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
 106extern void printf(const char *fmt, ...);
 107extern int putchar(int ch);
 108extern int setjmp(u_int *);
 109extern void longjmp(u_int *, int);
 110
 111extern void xmon_enter(void);
 112extern void xmon_leave(void);
 113
 114static unsigned start_tb[NR_CPUS][2];
 115static unsigned stop_tb[NR_CPUS][2];
 116
 117#define GETWORD(v)      (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
 118
 119#define isxdigit(c)     (('0' <= (c) && (c) <= '9') \
 120                         || ('a' <= (c) && (c) <= 'f') \
 121                         || ('A' <= (c) && (c) <= 'F'))
 122#define isalnum(c)      (('0' <= (c) && (c) <= '9') \
 123                         || ('a' <= (c) && (c) <= 'z') \
 124                         || ('A' <= (c) && (c) <= 'Z'))
 125#define isspace(c)      (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
 126
 127static char *help_string = "\
 128Commands:\n\
 129  d     dump bytes\n\
 130  di    dump instructions\n\
 131  df    dump float values\n\
 132  dd    dump double values\n\
 133  e     print exception information\n\
 134  h     dump hash table\n\
 135  m     examine/change memory\n\
 136  mm    move a block of memory\n\
 137  ms    set a block of memory\n\
 138  md    compare two blocks of memory\n\
 139  r     print registers\n\
 140  S     print special registers\n\
 141  t     print backtrace\n\
 142  la    lookup address\n\
 143  ls    lookup symbol\n\
 144  C     checksum\n\
 145  p     call function with arguments\n\
 146  T     print time\n\
 147  x     exit monitor\n\
 148  zr    reboot\n\
 149  zh    halt\n\
 150";
 151
 152static int xmon_trace[NR_CPUS];
 153#define SSTEP   1               /* stepping because of 's' command */
 154#define BRSTEP  2               /* stepping over breakpoint */
 155
 156#ifdef CONFIG_4xx
 157#define MSR_SSTEP_ENABLE 0x200
 158#else
 159#define MSR_SSTEP_ENABLE 0x400
 160#endif
 161
 162static struct pt_regs *xmon_regs[NR_CPUS];
 163
 164extern inline void sync(void)
 165{
 166        asm volatile("sync; isync");
 167}
 168
 169extern inline void __delay(unsigned int loops)
 170{
 171        if (loops != 0)
 172                __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
 173                                     "r" (loops) : "ctr");
 174}
 175
 176/* Print an address in numeric and symbolic form (if possible) */
 177static void xmon_print_symbol(unsigned long address, const char *mid,
 178                              const char *after)
 179{
 180        char *modname;
 181        const char *name = NULL;
 182        unsigned long offset, size;
 183        static char tmpstr[128];
 184
 185        printf("%.8lx", address);
 186        if (setjmp(bus_error_jmp) == 0) {
 187                debugger_fault_handler = handle_fault;
 188                sync();
 189                name = kallsyms_lookup(address, &size, &offset, &modname,
 190                                       tmpstr);
 191                sync();
 192                /* wait a little while to see if we get a machine check */
 193                __delay(200);
 194        }
 195        debugger_fault_handler = NULL;
 196
 197        if (name) {
 198                printf("%s%s+%#lx/%#lx", mid, name, offset, size);
 199                if (modname)
 200                        printf(" [%s]", modname);
 201        }
 202        printf("%s", after);
 203}
 204
 205static void get_tb(unsigned *p)
 206{
 207        unsigned hi, lo, hiagain;
 208
 209        if ((get_pvr() >> 16) == 1)
 210                return;
 211
 212        do {
 213                asm volatile("mftbu %0; mftb %1; mftbu %2"
 214                             : "=r" (hi), "=r" (lo), "=r" (hiagain));
 215        } while (hi != hiagain);
 216        p[0] = hi;
 217        p[1] = lo;
 218}
 219
 220static inline void xmon_enable_sstep(struct pt_regs *regs)
 221{
 222        regs->msr |= MSR_SSTEP_ENABLE;
 223#ifdef CONFIG_4xx
 224        mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
 225#endif
 226}
 227
 228int xmon(struct pt_regs *excp)
 229{
 230        struct pt_regs regs;
 231        int msr, cmd;
 232
 233        get_tb(stop_tb[smp_processor_id()]);
 234        if (excp == NULL) {
 235                asm volatile ("stw      0,0(%0)\n\
 236                        lwz     0,0(1)\n\
 237                        stw     0,4(%0)\n\
 238                        stmw    2,8(%0)" : : "b" (&regs));
 239                regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
 240                regs.msr = get_msr();
 241                regs.ctr = get_ctr();
 242                regs.xer = get_xer();
 243                regs.ccr = get_cr();
 244                regs.trap = 0;
 245                excp = &regs;
 246        }
 247
 248        msr = get_msr();
 249        set_msr(msr & ~0x8000); /* disable interrupts */
 250        xmon_regs[smp_processor_id()] = excp;
 251        xmon_enter();
 252        excprint(excp);
 253#ifdef CONFIG_SMP
 254        if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
 255                for (;;)
 256                        ;
 257        while (test_and_set_bit(0, &got_xmon)) {
 258                if (take_xmon == smp_processor_id()) {
 259                        take_xmon = -1;
 260                        break;
 261                }
 262        }
 263        /*
 264         * XXX: breakpoints are removed while any cpu is in xmon
 265         */
 266#endif /* CONFIG_SMP */
 267        remove_bpts();
 268        cmd = cmds(excp);
 269        if (cmd == 's') {
 270                xmon_trace[smp_processor_id()] = SSTEP;
 271                xmon_enable_sstep(excp);
 272        } else if (at_breakpoint(excp->nip)) {
 273                xmon_trace[smp_processor_id()] = BRSTEP;
 274                xmon_enable_sstep(excp);
 275        } else {
 276                xmon_trace[smp_processor_id()] = 0;
 277                insert_bpts();
 278        }
 279        xmon_leave();
 280        xmon_regs[smp_processor_id()] = NULL;
 281#ifdef CONFIG_SMP
 282        clear_bit(0, &got_xmon);
 283        clear_bit(smp_processor_id(), &cpus_in_xmon);
 284#endif /* CONFIG_SMP */
 285        set_msr(msr);           /* restore interrupt enable */
 286        get_tb(start_tb[smp_processor_id()]);
 287
 288        return cmd != 'X';
 289}
 290
 291irqreturn_t
 292xmon_irq(int irq, void *d, struct pt_regs *regs)
 293{
 294        unsigned long flags;
 295        local_irq_save(flags);
 296        printf("Keyboard interrupt\n");
 297        xmon(regs);
 298        local_irq_restore(flags);
 299        return IRQ_HANDLED;
 300}
 301
 302int
 303xmon_bpt(struct pt_regs *regs)
 304{
 305        struct bpt *bp;
 306
 307        bp = at_breakpoint(regs->nip);
 308        if (!bp)
 309                return 0;
 310        if (bp->count) {
 311                --bp->count;
 312                remove_bpts();
 313                excprint(regs);
 314                xmon_trace[smp_processor_id()] = BRSTEP;
 315                xmon_enable_sstep(regs);
 316        } else {
 317                xmon(regs);
 318        }
 319        return 1;
 320}
 321
 322int
 323xmon_sstep(struct pt_regs *regs)
 324{
 325        if (!xmon_trace[smp_processor_id()])
 326                return 0;
 327        if (xmon_trace[smp_processor_id()] == BRSTEP) {
 328                xmon_trace[smp_processor_id()] = 0;
 329                insert_bpts();
 330        } else {
 331                xmon(regs);
 332        }
 333        return 1;
 334}
 335
 336int
 337xmon_dabr_match(struct pt_regs *regs)
 338{
 339        if (dabr.enabled && dabr.count) {
 340                --dabr.count;
 341                remove_bpts();
 342                excprint(regs);
 343                xmon_trace[smp_processor_id()] = BRSTEP;
 344                regs->msr |= 0x400;
 345        } else {
 346                dabr.instr = regs->nip;
 347                xmon(regs);
 348        }
 349        return 1;
 350}
 351
 352int
 353xmon_iabr_match(struct pt_regs *regs)
 354{
 355        if (iabr.enabled && iabr.count) {
 356                --iabr.count;
 357                remove_bpts();
 358                excprint(regs);
 359                xmon_trace[smp_processor_id()] = BRSTEP;
 360                regs->msr |= 0x400;
 361        } else {
 362                xmon(regs);
 363        }
 364        return 1;
 365}
 366
 367static struct bpt *
 368at_breakpoint(unsigned pc)
 369{
 370        int i;
 371        struct bpt *bp;
 372
 373        if (dabr.enabled && pc == dabr.instr)
 374                return &dabr;
 375        if (iabr.enabled && pc == iabr.address)
 376                return &iabr;
 377        bp = bpts;
 378        for (i = 0; i < NBPTS; ++i, ++bp)
 379                if (bp->enabled && pc == bp->address)
 380                        return bp;
 381        return NULL;
 382}
 383
 384static void
 385insert_bpts(void)
 386{
 387        int i;
 388        struct bpt *bp;
 389
 390        bp = bpts;
 391        for (i = 0; i < NBPTS; ++i, ++bp) {
 392                if (!bp->enabled)
 393                        continue;
 394                if (mread(bp->address, &bp->instr, 4) != 4
 395                    || mwrite(bp->address, &bpinstr, 4) != 4) {
 396                        printf("Couldn't insert breakpoint at %x, disabling\n",
 397                               bp->address);
 398                        bp->enabled = 0;
 399                }
 400                store_inst((void *) bp->address);
 401        }
 402#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
 403        if (dabr.enabled)
 404                set_dabr(dabr.address);
 405        if (iabr.enabled)
 406                set_iabr(iabr.address);
 407#endif
 408}
 409
 410static void
 411remove_bpts(void)
 412{
 413        int i;
 414        struct bpt *bp;
 415        unsigned instr;
 416
 417#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
 418        set_dabr(0);
 419        set_iabr(0);
 420#endif
 421        bp = bpts;
 422        for (i = 0; i < NBPTS; ++i, ++bp) {
 423                if (!bp->enabled)
 424                        continue;
 425                if (mread(bp->address, &instr, 4) == 4
 426                    && instr == bpinstr
 427                    && mwrite(bp->address, &bp->instr, 4) != 4)
 428                        printf("Couldn't remove breakpoint at %x\n",
 429                               bp->address);
 430                store_inst((void *) bp->address);
 431        }
 432}
 433
 434static char *last_cmd;
 435
 436/* Command interpreting routine */
 437static int
 438cmds(struct pt_regs *excp)
 439{
 440        int cmd;
 441
 442        last_cmd = NULL;
 443        for(;;) {
 444#ifdef CONFIG_SMP
 445                printf("%d:", smp_processor_id());
 446#endif /* CONFIG_SMP */
 447                printf("mon> ");
 448                fflush(stdout);
 449                flush_input();
 450                termch = 0;
 451                cmd = skipbl();
 452                if( cmd == '\n' ) {
 453                        if (last_cmd == NULL)
 454                                continue;
 455                        take_input(last_cmd);
 456                        last_cmd = NULL;
 457                        cmd = inchar();
 458                }
 459                switch (cmd) {
 460                case 'm':
 461                        cmd = inchar();
 462                        switch (cmd) {
 463                        case 'm':
 464                        case 's':
 465                        case 'd':
 466                                memops(cmd);
 467                                break;
 468                        case 'l':
 469                                memlocate();
 470                                break;
 471                        case 'z':
 472                                memzcan();
 473                                break;
 474                        default:
 475                                termch = cmd;
 476                                memex();
 477                        }
 478                        break;
 479                case 'd':
 480                        dump();
 481                        break;
 482                case 'l':
 483                        symbol_lookup();
 484                        break;
 485                case 'r':
 486                        if (excp != NULL)
 487                                prregs(excp);   /* print regs */
 488                        break;
 489                case 'e':
 490                        if (excp == NULL)
 491                                printf("No exception information\n");
 492                        else
 493                                excprint(excp);
 494                        break;
 495                case 'S':
 496                        super_regs();
 497                        break;
 498                case 't':
 499                        backtrace(excp);
 500                        break;
 501                case 'f':
 502                        cacheflush();
 503                        break;
 504                case 'h':
 505                        dump_hash_table();
 506                        break;
 507                case 's':
 508                case 'x':
 509                case EOF:
 510                        return cmd;
 511                case '?':
 512                        printf(help_string);
 513                        break;
 514                default:
 515                        printf("Unrecognized command: ");
 516                        if( ' ' < cmd && cmd <= '~' )
 517                                putchar(cmd);
 518                        else
 519                                printf("\\x%x", cmd);
 520                        printf(" (type ? for help)\n");
 521                        break;
 522                case 'b':
 523                        bpt_cmds();
 524                        break;
 525                case 'C':
 526                        csum();
 527                        break;
 528#ifdef CONFIG_SMP
 529                case 'c':
 530                        cpu_cmd();
 531                        break;
 532#endif /* CONFIG_SMP */
 533                case 'z':
 534                        bootcmds();
 535                        break;
 536                case 'p':
 537                        proccall();
 538                        break;
 539                case 'T':
 540                        printtime();
 541                        break;
 542                }
 543        }
 544}
 545
 546extern unsigned tb_to_us;
 547
 548#define mulhwu(x,y) \
 549({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
 550
 551static void printtime(void)
 552{
 553        unsigned int delta;
 554
 555        delta = stop_tb[smp_processor_id()][1]
 556                - start_tb[smp_processor_id()][1];
 557        delta = mulhwu(tb_to_us, delta);
 558        printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
 559}
 560
 561static void bootcmds(void)
 562{
 563        int cmd;
 564
 565        cmd = inchar();
 566        if (cmd == 'r')
 567                ppc_md.restart(NULL);
 568        else if (cmd == 'h')
 569                ppc_md.halt();
 570        else if (cmd == 'p')
 571                ppc_md.power_off();
 572}
 573
 574#ifdef CONFIG_SMP
 575static void cpu_cmd(void)
 576{
 577        unsigned cpu;
 578        int timeout;
 579        int cmd;
 580
 581        cmd = inchar();
 582        if (cmd == 'i') {
 583                /* interrupt other cpu(s) */
 584                cpu = MSG_ALL_BUT_SELF;
 585                if (scanhex(&cpu))
 586                        smp_send_xmon_break(cpu);
 587                return;
 588        }
 589        termch = cmd;
 590        if (!scanhex(&cpu)) {
 591                /* print cpus waiting or in xmon */
 592                printf("cpus stopped:");
 593                for (cpu = 0; cpu < NR_CPUS; ++cpu) {
 594                        if (test_bit(cpu, &cpus_in_xmon)) {
 595                                printf(" %d", cpu);
 596                                if (cpu == smp_processor_id())
 597                                        printf("*", cpu);
 598                        }
 599                }
 600                printf("\n");
 601                return;
 602        }
 603        /* try to switch to cpu specified */
 604        take_xmon = cpu;
 605        timeout = 10000000;
 606        while (take_xmon >= 0) {
 607                if (--timeout == 0) {
 608                        /* yes there's a race here */
 609                        take_xmon = -1;
 610                        printf("cpu %u didn't take control\n", cpu);
 611                        return;
 612                }
 613        }
 614        /* now have to wait to be given control back */
 615        while (test_and_set_bit(0, &got_xmon)) {
 616                if (take_xmon == smp_processor_id()) {
 617                        take_xmon = -1;
 618                        break;
 619                }
 620        }
 621}
 622#endif /* CONFIG_SMP */
 623
 624
 625static unsigned short fcstab[256] = {
 626        0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
 627        0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
 628        0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
 629        0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
 630        0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
 631        0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
 632        0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
 633        0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
 634        0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
 635        0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
 636        0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
 637        0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
 638        0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
 639        0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
 640        0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
 641        0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
 642        0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
 643        0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
 644        0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
 645        0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
 646        0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
 647        0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
 648        0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
 649        0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
 650        0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
 651        0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
 652        0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
 653        0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
 654        0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
 655        0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
 656        0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
 657        0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
 658};
 659
 660#define FCS(fcs, c)     (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
 661
 662static void
 663csum(void)
 664{
 665        unsigned int i;
 666        unsigned short fcs;
 667        unsigned char v;
 668
 669        if (!scanhex(&adrs))
 670                return;
 671        if (!scanhex(&ncsum))
 672                return;
 673        fcs = 0xffff;
 674        for (i = 0; i < ncsum; ++i) {
 675                if (mread(adrs+i, &v, 1) == 0) {
 676                        printf("csum stopped at %x\n", adrs+i);
 677                        break;
 678                }
 679                fcs = FCS(fcs, v);
 680        }
 681        printf("%x\n", fcs);
 682}
 683
 684static void
 685bpt_cmds(void)
 686{
 687        int cmd;
 688        unsigned a;
 689        int mode, i;
 690        struct bpt *bp;
 691
 692        cmd = inchar();
 693        switch (cmd) {
 694#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
 695        case 'd':
 696                mode = 7;
 697                cmd = inchar();
 698                if (cmd == 'r')
 699                        mode = 5;
 700                else if (cmd == 'w')
 701                        mode = 6;
 702                else
 703                        termch = cmd;
 704                cmd = inchar();
 705                if (cmd == 'p')
 706                        mode &= ~4;
 707                else
 708                        termch = cmd;
 709                dabr.address = 0;
 710                dabr.count = 0;
 711                dabr.enabled = scanhex(&dabr.address);
 712                scanhex(&dabr.count);
 713                if (dabr.enabled)
 714                        dabr.address = (dabr.address & ~7) | mode;
 715                break;
 716        case 'i':
 717                cmd = inchar();
 718                if (cmd == 'p')
 719                        mode = 2;
 720                else
 721                        mode = 3;
 722                iabr.address = 0;
 723                iabr.count = 0;
 724                iabr.enabled = scanhex(&iabr.address);
 725                if (iabr.enabled)
 726                        iabr.address |= mode;
 727                scanhex(&iabr.count);
 728                break;
 729#endif
 730        case 'c':
 731                if (!scanhex(&a)) {
 732                        /* clear all breakpoints */
 733                        for (i = 0; i < NBPTS; ++i)
 734                                bpts[i].enabled = 0;
 735                        iabr.enabled = 0;
 736                        dabr.enabled = 0;
 737                        printf("All breakpoints cleared\n");
 738                } else {
 739                        bp = at_breakpoint(a);
 740                        if (bp == 0) {
 741                                printf("No breakpoint at %x\n", a);
 742                        } else {
 743                                bp->enabled = 0;
 744                        }
 745                }
 746                break;
 747        default:
 748                termch = cmd;
 749                if (!scanhex(&a)) {
 750                        /* print all breakpoints */
 751                        printf("type  address   count\n");
 752                        if (dabr.enabled) {
 753                                printf("data %.8x %8x [", dabr.address & ~7,
 754                                       dabr.count);
 755                                if (dabr.address & 1)
 756                                        printf("r");
 757                                if (dabr.address & 2)
 758                                        printf("w");
 759                                if (!(dabr.address & 4))
 760                                        printf("p");
 761                                printf("]\n");
 762                        }
 763                        if (iabr.enabled)
 764                                printf("inst %.8x %8x\n", iabr.address & ~3,
 765                                       iabr.count);
 766                        for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
 767                                if (bp->enabled)
 768                                        printf("trap %.8x %8x\n", bp->address,
 769                                               bp->count);
 770                        break;
 771                }
 772                bp = at_breakpoint(a);
 773                if (bp == 0) {
 774                        for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
 775                                if (!bp->enabled)
 776                                        break;
 777                        if (bp >= &bpts[NBPTS]) {
 778                                printf("Sorry, no free breakpoints\n");
 779                                break;
 780                        }
 781                }
 782                bp->enabled = 1;
 783                bp->address = a;
 784                bp->count = 0;
 785                scanhex(&bp->count);
 786                break;
 787        }
 788}
 789
 790static void
 791backtrace(struct pt_regs *excp)
 792{
 793        unsigned sp;
 794        unsigned stack[2];
 795        struct pt_regs regs;
 796        extern char ret_from_except, ret_from_except_full, ret_from_syscall;
 797
 798        printf("backtrace:\n");
 799        
 800        if (excp != NULL)
 801                sp = excp->gpr[1];
 802        else
 803                sp = getsp();
 804        scanhex(&sp);
 805        scannl();
 806        for (; sp != 0; sp = stack[0]) {
 807                if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 808                        break;
 809                printf("[%.8lx] ", stack[0]);
 810                xmon_print_symbol(stack[1], " ", "\n");
 811                if (stack[1] == (unsigned) &ret_from_except
 812                    || stack[1] == (unsigned) &ret_from_except_full
 813                    || stack[1] == (unsigned) &ret_from_syscall) {
 814                        if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
 815                                break;
 816                        printf("exception:%x [%x] %x\n", regs.trap, sp+16,
 817                               regs.nip);
 818                        sp = regs.gpr[1];
 819                        if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 820                                break;
 821                }
 822        }
 823}
 824
 825int
 826getsp(void)
 827{
 828    int x;
 829
 830    asm("mr %0,1" : "=r" (x) :);
 831    return x;
 832}
 833
 834void
 835excprint(struct pt_regs *fp)
 836{
 837        int trap;
 838
 839#ifdef CONFIG_SMP
 840        printf("cpu %d: ", smp_processor_id());
 841#endif /* CONFIG_SMP */
 842        printf("vector: %x at pc=", fp->trap);
 843        xmon_print_symbol(fp->nip, ": ", ", lr=");
 844        xmon_print_symbol(fp->link, ": ", "\n");
 845        printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
 846        trap = TRAP(fp);
 847        if (trap == 0x300 || trap == 0x600)
 848                printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
 849        if (current)
 850                printf("current = %x, pid = %d, comm = %s\n",
 851                       current, current->pid, current->comm);
 852}
 853
 854void
 855prregs(struct pt_regs *fp)
 856{
 857        int n;
 858        unsigned base;
 859
 860        if (scanhex(&base))
 861                fp = (struct pt_regs *) base;
 862        for (n = 0; n < 32; ++n) {
 863                printf("R%.2d = %.8x%s", n, fp->gpr[n],
 864                       (n & 3) == 3? "\n": "   ");
 865                if (n == 12 && !FULL_REGS(fp)) {
 866                        printf("\n");
 867                        break;
 868                }
 869        }
 870        printf("pc  = %.8x   msr = %.8x   lr  = %.8x   cr  = %.8x\n",
 871               fp->nip, fp->msr, fp->link, fp->ccr);
 872        printf("ctr = %.8x   xer = %.8x   trap = %4x\n",
 873               fp->ctr, fp->xer, fp->trap);
 874}
 875
 876void
 877cacheflush(void)
 878{
 879        int cmd;
 880        unsigned nflush;
 881
 882        cmd = inchar();
 883        if (cmd != 'i')
 884                termch = cmd;
 885        scanhex(&adrs);
 886        if (termch != '\n')
 887                termch = 0;
 888        nflush = 1;
 889        scanhex(&nflush);
 890        nflush = (nflush + 31) / 32;
 891        if (cmd != 'i') {
 892                for (; nflush > 0; --nflush, adrs += 0x20)
 893                        cflush((void *) adrs);
 894        } else {
 895                for (; nflush > 0; --nflush, adrs += 0x20)
 896                        cinval((void *) adrs);
 897        }
 898}
 899
 900unsigned int
 901read_spr(int n)
 902{
 903    unsigned int instrs[2];
 904    int (*code)(void);
 905
 906    instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
 907    instrs[1] = 0x4e800020;
 908    store_inst(instrs);
 909    store_inst(instrs+1);
 910    code = (int (*)(void)) instrs;
 911    return code();
 912}
 913
 914void
 915write_spr(int n, unsigned int val)
 916{
 917    unsigned int instrs[2];
 918    int (*code)(unsigned int);
 919
 920    instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
 921    instrs[1] = 0x4e800020;
 922    store_inst(instrs);
 923    store_inst(instrs+1);
 924    code = (int (*)(unsigned int)) instrs;
 925    code(val);
 926}
 927
 928static unsigned int regno;
 929extern char exc_prolog;
 930extern char dec_exc;
 931
 932void
 933super_regs(void)
 934{
 935        int i, cmd;
 936        unsigned val;
 937
 938        cmd = skipbl();
 939        if (cmd == '\n') {
 940                printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
 941                printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
 942                       get_sprg2(), get_sprg3());
 943                printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
 944#ifdef CONFIG_PPC_STD_MMU
 945                printf("sr0-15 =");
 946                for (i = 0; i < 16; ++i)
 947                        printf(" %x", get_sr(i));
 948                printf("\n");
 949#endif
 950                asm("mr %0,1" : "=r" (i) :);
 951                printf("sp = %x ", i);
 952                asm("mr %0,2" : "=r" (i) :);
 953                printf("toc = %x\n", i);
 954                return;
 955        }
 956
 957        scanhex(&regno);
 958        switch (cmd) {
 959        case 'w':
 960                val = read_spr(regno);
 961                scanhex(&val);
 962                write_spr(regno, val);
 963                /* fall through */
 964        case 'r':
 965                printf("spr %x = %x\n", regno, read_spr(regno));
 966                break;
 967        case 's':
 968                val = get_sr(regno);
 969                scanhex(&val);
 970                set_sr(regno, val);
 971                break;
 972        case 'm':
 973                val = get_msr();
 974                scanhex(&val);
 975                set_msr(val);
 976                break;
 977        }
 978        scannl();
 979}
 980
 981#ifndef CONFIG_PPC_STD_MMU
 982static void
 983dump_hash_table(void)
 984{
 985        printf("This CPU doesn't have a hash table.\n");
 986}
 987#else
 988
 989static void
 990dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
 991{
 992        extern void *Hash;
 993        extern unsigned long Hash_size;
 994        unsigned *htab = Hash;
 995        unsigned hsize = Hash_size;
 996        unsigned v, hmask, va, last_va = 0;
 997        int found, last_found, i;
 998        unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
 999
1000        last_found = 0;
1001        hmask = hsize / 64 - 1;
1002        va = start;
1003        start = (start >> 12) & 0xffff;
1004        end = (end >> 12) & 0xffff;
1005        for (v = start; v < end; ++v) {
1006                found = 0;
1007                hg = htab + (((v ^ seg) & hmask) * 16);
1008                w1 = 0x80000000 | (seg << 7) | (v >> 10);
1009                for (i = 0; i < 8; ++i, hg += 2) {
1010                        if (*hg == w1) {
1011                                found = 1;
1012                                break;
1013                        }
1014                }
1015                if (!found) {
1016                        w1 ^= 0x40;
1017                        hg = htab + ((~(v ^ seg) & hmask) * 16);
1018                        for (i = 0; i < 8; ++i, hg += 2) {
1019                                if (*hg == w1) {
1020                                        found = 1;
1021                                        break;
1022                                }
1023                        }
1024                }
1025                if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1026                        if (last_found) {
1027                                if (last_va != last_va0)
1028                                        printf(" ... %x", last_va);
1029                                printf("\n");
1030                        }
1031                        if (found) {
1032                                printf("%x to %x", va, hg[1]);
1033                                last_va0 = va;
1034                        }
1035                        last_found = found;
1036                }
1037                if (found) {
1038                        last_w2 = hg[1] & ~0x180;
1039                        last_va = va;
1040                }
1041                va += 4096;
1042        }
1043        if (last_found)
1044                printf(" ... %x\n", last_va);
1045}
1046
1047static unsigned hash_ctx;
1048static unsigned hash_start;
1049static unsigned hash_end;
1050
1051static void
1052dump_hash_table(void)
1053{
1054        int seg;
1055        unsigned seg_start, seg_end;
1056
1057        hash_ctx = 0;
1058        hash_start = 0;
1059        hash_end = 0xfffff000;
1060        scanhex(&hash_ctx);
1061        scanhex(&hash_start);
1062        scanhex(&hash_end);
1063        printf("Mappings for context %x\n", hash_ctx);
1064        seg_start = hash_start;
1065        for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1066                seg_end = (seg << 28) | 0x0ffff000;
1067                if (seg_end > hash_end)
1068                        seg_end = hash_end;
1069                dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1070                                    seg_start, seg_end);
1071                seg_start = seg_end + 0x1000;
1072        }
1073}
1074#endif /* CONFIG_PPC_STD_MMU */
1075
1076/*
1077 * Stuff for reading and writing memory safely
1078 */
1079
1080int
1081mread(unsigned adrs, void *buf, int size)
1082{
1083        volatile int n;
1084        char *p, *q;
1085
1086        n = 0;
1087        if( setjmp(bus_error_jmp) == 0 ){
1088                debugger_fault_handler = handle_fault;
1089                sync();
1090                p = (char *) adrs;
1091                q = (char *) buf;
1092                switch (size) {
1093                case 2: *(short *)q = *(short *)p;      break;
1094                case 4: *(int *)q = *(int *)p;          break;
1095                default:
1096                        for( ; n < size; ++n ) {
1097                                *q++ = *p++;
1098                                sync();
1099                        }
1100                }
1101                sync();
1102                /* wait a little while to see if we get a machine check */
1103                __delay(200);
1104                n = size;
1105        }
1106        debugger_fault_handler = NULL;
1107        return n;
1108}
1109
1110int
1111mwrite(unsigned adrs, void *buf, int size)
1112{
1113        volatile int n;
1114        char *p, *q;
1115
1116        n = 0;
1117        if( setjmp(bus_error_jmp) == 0 ){
1118                debugger_fault_handler = handle_fault;
1119                sync();
1120                p = (char *) adrs;
1121                q = (char *) buf;
1122                switch (size) {
1123                case 2: *(short *)p = *(short *)q;      break;
1124                case 4: *(int *)p = *(int *)q;          break;
1125                default:
1126                        for( ; n < size; ++n ) {
1127                                *p++ = *q++;
1128                                sync();
1129                        }
1130                }
1131                sync();
1132                n = size;
1133        } else {
1134                printf("*** Error writing address %x\n", adrs + n);
1135        }
1136        debugger_fault_handler = NULL;
1137        return n;
1138}
1139
1140static int fault_type;
1141static int fault_except;
1142static char *fault_chars[] = { "--", "**", "##" };
1143
1144static void
1145handle_fault(struct pt_regs *regs)
1146{
1147        fault_except = TRAP(regs);
1148        fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1149        longjmp(bus_error_jmp, 1);
1150}
1151
1152#define SWAP(a, b, t)   ((t) = (a), (a) = (b), (b) = (t))
1153
1154void
1155byterev(unsigned char *val, int size)
1156{
1157        int t;
1158        
1159        switch (size) {
1160        case 2:
1161                SWAP(val[0], val[1], t);
1162                break;
1163        case 4:
1164                SWAP(val[0], val[3], t);
1165                SWAP(val[1], val[2], t);
1166                break;
1167        }
1168}
1169
1170static int brev;
1171static int mnoread;
1172
1173void
1174memex(void)
1175{
1176    int cmd, inc, i, nslash;
1177    unsigned n;
1178    unsigned char val[4];
1179
1180    last_cmd = "m\n";
1181    scanhex(&adrs);
1182    while ((cmd = skipbl()) != '\n') {
1183        switch( cmd ){
1184        case 'b':       size = 1;       break;
1185        case 'w':       size = 2;       break;
1186        case 'l':       size = 4;       break;
1187        case 'r':       brev = !brev;   break;
1188        case 'n':       mnoread = 1;    break;
1189        case '.':       mnoread = 0;    break;
1190        }
1191    }
1192    if( size <= 0 )
1193        size = 1;
1194    else if( size > 4 )
1195        size = 4;
1196    for(;;){
1197        if (!mnoread)
1198            n = mread(adrs, val, size);
1199        printf("%.8x%c", adrs, brev? 'r': ' ');
1200        if (!mnoread) {
1201            if (brev)
1202                byterev(val, size);
1203            putchar(' ');
1204            for (i = 0; i < n; ++i)
1205                printf("%.2x", val[i]);
1206            for (; i < size; ++i)
1207                printf("%s", fault_chars[fault_type]);
1208        }
1209        putchar(' ');
1210        inc = size;
1211        nslash = 0;
1212        for(;;){
1213            if( scanhex(&n) ){
1214                for (i = 0; i < size; ++i)
1215                    val[i] = n >> (i * 8);
1216                if (!brev)
1217                    byterev(val, size);
1218                mwrite(adrs, val, size);
1219                inc = size;
1220            }
1221            cmd = skipbl();
1222            if (cmd == '\n')
1223                break;
1224            inc = 0;
1225            switch (cmd) {
1226            case '\'':
1227                for(;;){
1228                    n = inchar();
1229                    if( n == '\\' )
1230                        n = bsesc();
1231                    else if( n == '\'' )
1232                        break;
1233                    for (i = 0; i < size; ++i)
1234                        val[i] = n >> (i * 8);
1235                    if (!brev)
1236                        byterev(val, size);
1237                    mwrite(adrs, val, size);
1238                    adrs += size;
1239                }
1240                adrs -= size;
1241                inc = size;
1242                break;
1243            case ',':
1244                adrs += size;
1245                break;
1246            case '.':
1247                mnoread = 0;
1248                break;
1249            case ';':
1250                break;
1251            case 'x':
1252            case EOF:
1253                scannl();
1254                return;
1255            case 'b':
1256            case 'v':
1257                size = 1;
1258                break;
1259            case 'w':
1260                size = 2;
1261                break;
1262            case 'l':
1263                size = 4;
1264                break;
1265            case '^':
1266                adrs -= size;
1267                break;
1268                break;
1269            case '/':
1270                if (nslash > 0)
1271                    adrs -= 1 << nslash;
1272                else
1273                    nslash = 0;
1274                nslash += 4;
1275                adrs += 1 << nslash;
1276                break;
1277            case '\\':
1278                if (nslash < 0)
1279                    adrs += 1 << -nslash;
1280                else
1281                    nslash = 0;
1282                nslash -= 4;
1283                adrs -= 1 << -nslash;
1284                break;
1285            case 'm':
1286                scanhex(&adrs);
1287                break;
1288            case 'n':
1289                mnoread = 1;
1290                break;
1291            case 'r':
1292                brev = !brev;
1293                break;
1294            case '<':
1295                n = size;
1296                scanhex(&n);
1297                adrs -= n;
1298                break;
1299            case '>':
1300                n = size;
1301                scanhex(&n);
1302                adrs += n;
1303                break;
1304            }
1305        }
1306        adrs += inc;
1307    }
1308}
1309
1310int
1311bsesc(void)
1312{
1313        int c;
1314
1315        c = inchar();
1316        switch( c ){
1317        case 'n':       c = '\n';       break;
1318        case 'r':       c = '\r';       break;
1319        case 'b':       c = '\b';       break;
1320        case 't':       c = '\t';       break;
1321        }
1322        return c;
1323}
1324
1325void
1326dump(void)
1327{
1328        int c;
1329
1330        c = inchar();
1331        if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1332                termch = c;
1333        scanhex(&adrs);
1334        if( termch != '\n')
1335                termch = 0;
1336        if( c == 'i' ){
1337                scanhex(&nidump);
1338                if( nidump == 0 )
1339                        nidump = 16;
1340                adrs += ppc_inst_dump(adrs, nidump);
1341                last_cmd = "di\n";
1342        } else {
1343                scanhex(&ndump);
1344                if( ndump == 0 )
1345                        ndump = 64;
1346                prdump(adrs, ndump);
1347                adrs += ndump;
1348                last_cmd = "d\n";
1349        }
1350}
1351
1352void
1353prdump(unsigned adrs, int ndump)
1354{
1355        register int n, m, c, r, nr;
1356        unsigned char temp[16];
1357
1358        for( n = ndump; n > 0; ){
1359                printf("%.8x", adrs);
1360                putchar(' ');
1361                r = n < 16? n: 16;
1362                nr = mread(adrs, temp, r);
1363                adrs += nr;
1364                for( m = 0; m < r; ++m ){
1365                        putchar((m & 3) == 0 && m > 0? '.': ' ');
1366                        if( m < nr )
1367                                printf("%.2x", temp[m]);
1368                        else
1369                                printf("%s", fault_chars[fault_type]);
1370                }
1371                for(; m < 16; ++m )
1372                        printf("   ");
1373                printf("  |");
1374                for( m = 0; m < r; ++m ){
1375                        if( m < nr ){
1376                                c = temp[m];
1377                                putchar(' ' <= c && c <= '~'? c: '.');
1378                        } else
1379                                putchar(' ');
1380                }
1381                n -= r;
1382                for(; m < 16; ++m )
1383                        putchar(' ');
1384                printf("|\n");
1385                if( nr < r )
1386                        break;
1387        }
1388}
1389
1390int
1391ppc_inst_dump(unsigned adr, int count)
1392{
1393        int nr, dotted;
1394        unsigned first_adr;
1395        unsigned long inst, last_inst = 0;
1396        unsigned char val[4];
1397
1398        dotted = 0;
1399        for (first_adr = adr; count > 0; --count, adr += 4){
1400                nr = mread(adr, val, 4);
1401                if( nr == 0 ){
1402                        const char *x = fault_chars[fault_type];
1403                        printf("%.8x  %s%s%s%s\n", adr, x, x, x, x);
1404                        break;
1405                }
1406                inst = GETWORD(val);
1407                if (adr > first_adr && inst == last_inst) {
1408                        if (!dotted) {
1409                                printf(" ...\n");
1410                                dotted = 1;
1411                        }
1412                        continue;
1413                }
1414                dotted = 0;
1415                last_inst = inst;
1416                printf("%.8x  ", adr);
1417                printf("%.8x\t", inst);
1418                print_insn_big_powerpc(stdout, inst, adr);      /* always returns 4 */
1419                printf("\n");
1420        }
1421        return adr - first_adr;
1422}
1423
1424void
1425print_address(unsigned addr)
1426{
1427        printf("0x%x", addr);
1428}
1429
1430/*
1431 * Memory operations - move, set, print differences
1432 */
1433static unsigned mdest;          /* destination address */
1434static unsigned msrc;           /* source address */
1435static unsigned mval;           /* byte value to set memory to */
1436static unsigned mcount;         /* # bytes to affect */
1437static unsigned mdiffs;         /* max # differences to print */
1438
1439void
1440memops(int cmd)
1441{
1442        scanhex(&mdest);
1443        if( termch != '\n' )
1444                termch = 0;
1445        scanhex(cmd == 's'? &mval: &msrc);
1446        if( termch != '\n' )
1447                termch = 0;
1448        scanhex(&mcount);
1449        switch( cmd ){
1450        case 'm':
1451                memmove((void *)mdest, (void *)msrc, mcount);
1452                break;
1453        case 's':
1454                memset((void *)mdest, mval, mcount);
1455                break;
1456        case 'd':
1457                if( termch != '\n' )
1458                        termch = 0;
1459                scanhex(&mdiffs);
1460                memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1461                break;
1462        }
1463}
1464
1465void
1466memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1467{
1468        unsigned n, prt;
1469
1470        prt = 0;
1471        for( n = nb; n > 0; --n )
1472                if( *p1++ != *p2++ )
1473                        if( ++prt <= maxpr )
1474                                printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1475                                        p1[-1], (unsigned)p2 - 1, p2[-1]);
1476        if( prt > maxpr )
1477                printf("Total of %d differences\n", prt);
1478}
1479
1480static unsigned mend;
1481static unsigned mask;
1482
1483void
1484memlocate(void)
1485{
1486        unsigned a, n;
1487        unsigned char val[4];
1488
1489        last_cmd = "ml";
1490        scanhex(&mdest);
1491        if (termch != '\n') {
1492                termch = 0;
1493                scanhex(&mend);
1494                if (termch != '\n') {
1495                        termch = 0;
1496                        scanhex(&mval);
1497                        mask = ~0;
1498                        if (termch != '\n') termch = 0;
1499                        scanhex(&mask);
1500                }
1501        }
1502        n = 0;
1503        for (a = mdest; a < mend; a += 4) {
1504                if (mread(a, val, 4) == 4
1505                        && ((GETWORD(val) ^ mval) & mask) == 0) {
1506                        printf("%.8x:  %.8x\n", a, GETWORD(val));
1507                        if (++n >= 10)
1508                                break;
1509                }
1510        }
1511}
1512
1513static unsigned mskip = 0x1000;
1514static unsigned mlim = 0xffffffff;
1515
1516void
1517memzcan(void)
1518{
1519        unsigned char v;
1520        unsigned a;
1521        int ok, ook;
1522
1523        scanhex(&mdest);
1524        if (termch != '\n') termch = 0;
1525        scanhex(&mskip);
1526        if (termch != '\n') termch = 0;
1527        scanhex(&mlim);
1528        ook = 0;
1529        for (a = mdest; a < mlim; a += mskip) {
1530                ok = mread(a, &v, 1);
1531                if (ok && !ook) {
1532                        printf("%.8x .. ", a);
1533                        fflush(stdout);
1534                } else if (!ok && ook)
1535                        printf("%.8x\n", a - mskip);
1536                ook = ok;
1537                if (a + mskip < a)
1538                        break;
1539        }
1540        if (ook)
1541                printf("%.8x\n", a - mskip);
1542}
1543
1544void proccall(void)
1545{
1546        unsigned int args[8];
1547        unsigned int ret;
1548        int i;
1549        typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1550                        unsigned int, unsigned int, unsigned int,
1551                        unsigned int, unsigned int, unsigned int);
1552        callfunc_t func;
1553
1554        scanhex(&adrs);
1555        if (termch != '\n')
1556                termch = 0;
1557        for (i = 0; i < 8; ++i)
1558                args[i] = 0;
1559        for (i = 0; i < 8; ++i) {
1560                if (!scanhex(&args[i]) || termch == '\n')
1561                        break;
1562                termch = 0;
1563        }
1564        func = (callfunc_t) adrs;
1565        ret = 0;
1566        if (setjmp(bus_error_jmp) == 0) {
1567                debugger_fault_handler = handle_fault;
1568                sync();
1569                ret = func(args[0], args[1], args[2], args[3],
1570                           args[4], args[5], args[6], args[7]);
1571                sync();
1572                printf("return value is %x\n", ret);
1573        } else {
1574                printf("*** %x exception occurred\n", fault_except);
1575        }
1576        debugger_fault_handler = NULL;
1577}
1578
1579/* Input scanning routines */
1580int
1581skipbl(void)
1582{
1583        int c;
1584
1585        if( termch != 0 ){
1586                c = termch;
1587                termch = 0;
1588        } else
1589                c = inchar();
1590        while( c == ' ' || c == '\t' )
1591                c = inchar();
1592        return c;
1593}
1594
1595#define N_PTREGS        44
1596static char *regnames[N_PTREGS] = {
1597        "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1598        "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1599        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1600        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1601        "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1602        "trap", "dar", "dsisr", "res"
1603};
1604
1605int
1606scanhex(unsigned *vp)
1607{
1608        int c, d;
1609        unsigned v;
1610
1611        c = skipbl();
1612        if (c == '%') {
1613                /* parse register name */
1614                char regname[8];
1615                int i;
1616
1617                for (i = 0; i < sizeof(regname) - 1; ++i) {
1618                        c = inchar();
1619                        if (!isalnum(c)) {
1620                                termch = c;
1621                                break;
1622                        }
1623                        regname[i] = c;
1624                }
1625                regname[i] = 0;
1626                for (i = 0; i < N_PTREGS; ++i) {
1627                        if (strcmp(regnames[i], regname) == 0) {
1628                                unsigned *rp = (unsigned *)
1629                                        xmon_regs[smp_processor_id()];
1630                                if (rp == NULL) {
1631                                        printf("regs not available\n");
1632                                        return 0;
1633                                }
1634                                *vp = rp[i];
1635                                return 1;
1636                        }
1637                }
1638                printf("invalid register name '%%%s'\n", regname);
1639                return 0;
1640        } else if (c == '$') {
1641                static char symname[128];
1642                int i;
1643                for (i=0; i<63; i++) {
1644                        c = inchar();
1645                        if (isspace(c)) {
1646                                termch = c;
1647                                break;
1648                        }
1649                        symname[i] = c;
1650                }
1651                symname[i++] = 0;
1652                *vp = 0;
1653                if (setjmp(bus_error_jmp) == 0) {
1654                        debugger_fault_handler = handle_fault;
1655                        sync();
1656                        *vp = kallsyms_lookup_name(symname);
1657                        sync();
1658                }
1659                debugger_fault_handler = NULL;
1660                if (!(*vp)) {
1661                        printf("unknown symbol\n");
1662                        return 0;
1663                }
1664                return 1;
1665        }
1666
1667        d = hexdigit(c);
1668        if( d == EOF ){
1669                termch = c;
1670                return 0;
1671        }
1672        v = 0;
1673        do {
1674                v = (v << 4) + d;
1675                c = inchar();
1676                d = hexdigit(c);
1677        } while( d != EOF );
1678        termch = c;
1679        *vp = v;
1680        return 1;
1681}
1682
1683void
1684scannl(void)
1685{
1686        int c;
1687
1688        c = termch;
1689        termch = 0;
1690        while( c != '\n' )
1691                c = inchar();
1692}
1693
1694int hexdigit(int c)
1695{
1696        if( '0' <= c && c <= '9' )
1697                return c - '0';
1698        if( 'A' <= c && c <= 'F' )
1699                return c - ('A' - 10);
1700        if( 'a' <= c && c <= 'f' )
1701                return c - ('a' - 10);
1702        return EOF;
1703}
1704
1705void
1706getstring(char *s, int size)
1707{
1708        int c;
1709
1710        c = skipbl();
1711        do {
1712                if( size > 1 ){
1713                        *s++ = c;
1714                        --size;
1715                }
1716                c = inchar();
1717        } while( c != ' ' && c != '\t' && c != '\n' );
1718        termch = c;
1719        *s = 0;
1720}
1721
1722static char line[256];
1723static char *lineptr;
1724
1725void
1726flush_input(void)
1727{
1728        lineptr = NULL;
1729}
1730
1731int
1732inchar(void)
1733{
1734        if (lineptr == NULL || *lineptr == 0) {
1735                if (fgets(line, sizeof(line), stdin) == NULL) {
1736                        lineptr = NULL;
1737                        return EOF;
1738                }
1739                lineptr = line;
1740        }
1741        return *lineptr++;
1742}
1743
1744void
1745take_input(char *str)
1746{
1747        lineptr = str;
1748}
1749
1750static void
1751symbol_lookup(void)
1752{
1753        int type = inchar();
1754        unsigned addr;
1755        static char tmp[128];
1756
1757        switch (type) {
1758        case 'a':
1759                if (scanhex(&addr))
1760                        xmon_print_symbol(addr, ": ", "\n");
1761                termch = 0;
1762                break;
1763        case 's':
1764                getstring(tmp, 64);
1765                if (setjmp(bus_error_jmp) == 0) {
1766                        debugger_fault_handler = handle_fault;
1767                        sync();
1768                        addr = kallsyms_lookup_name(tmp);
1769                        if (addr)
1770                                printf("%s: %lx\n", tmp, addr);
1771                        else
1772                                printf("Symbol '%s' not found.\n", tmp);
1773                        sync();
1774                }
1775                debugger_fault_handler = NULL;
1776                termch = 0;
1777                break;
1778        }
1779}
1780
1781
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.