2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996-2005 Paul Mackerras.
5 * Copyright (C) 2001 PPC64 Team, IBM Corp
6 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
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.
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/smp.h>
17 #include <linux/reboot.h>
18 #include <linux/delay.h>
19 #include <linux/kallsyms.h>
20 #include <linux/kmsg_dump.h>
21 #include <linux/cpumask.h>
22 #include <linux/export.h>
23 #include <linux/sysrq.h>
24 #include <linux/interrupt.h>
25 #include <linux/irq.h>
26 #include <linux/bug.h>
28 #include <asm/ptrace.h>
29 #include <asm/string.h>
31 #include <asm/machdep.h>
33 #include <asm/processor.h>
34 #include <asm/pgtable.h>
36 #include <asm/mmu_context.h>
37 #include <asm/cputable.h>
39 #include <asm/sstep.h>
40 #include <asm/irq_regs.h>
42 #include <asm/spu_priv1.h>
43 #include <asm/setjmp.h>
45 #include <asm/debug.h>
46 #include <asm/hw_breakpoint.h>
49 #include <asm/hvcall.h>
57 static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
58 static unsigned long xmon_taken = 1;
59 static int xmon_owner;
63 #endif /* CONFIG_SMP */
65 static unsigned long in_xmon __read_mostly = 0;
67 static unsigned long adrs;
69 #define MAX_DUMP (128 * 1024)
70 static unsigned long ndump = 64;
71 static unsigned long nidump = 16;
72 static unsigned long ncsum = 4096;
74 static char tmpstr[128];
76 static long bus_error_jmp[JMP_BUF_LEN];
77 static int catch_memory_errors;
78 static long *xmon_fault_jmp[NR_CPUS];
80 /* Breakpoint stuff */
82 unsigned long address;
83 unsigned int instr[2];
89 /* Bits in bpt.enabled */
90 #define BP_IABR_TE 1 /* IABR translation enabled */
96 static struct bpt bpts[NBPTS];
97 static struct bpt dabr;
98 static struct bpt *iabr;
99 static unsigned bpinstr = 0x7fe00008; /* trap */
101 #define BP_NUM(bp) ((bp) - bpts + 1)
104 static int cmds(struct pt_regs *);
105 static int mread(unsigned long, void *, int);
106 static int mwrite(unsigned long, void *, int);
107 static int handle_fault(struct pt_regs *);
108 static void byterev(unsigned char *, int);
109 static void memex(void);
110 static int bsesc(void);
111 static void dump(void);
112 static void prdump(unsigned long, long);
113 static int ppc_inst_dump(unsigned long, long, int);
114 static void dump_log_buf(void);
115 static void backtrace(struct pt_regs *);
116 static void excprint(struct pt_regs *);
117 static void prregs(struct pt_regs *);
118 static void memops(int);
119 static void memlocate(void);
120 static void memzcan(void);
121 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
123 int scanhex(unsigned long *valp);
124 static void scannl(void);
125 static int hexdigit(int);
126 void getstring(char *, int);
127 static void flush_input(void);
128 static int inchar(void);
129 static void take_input(char *);
130 static unsigned long read_spr(int);
131 static void write_spr(int, unsigned long);
132 static void super_regs(void);
133 static void remove_bpts(void);
134 static void insert_bpts(void);
135 static void remove_cpu_bpts(void);
136 static void insert_cpu_bpts(void);
137 static struct bpt *at_breakpoint(unsigned long pc);
138 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
139 static int do_step(struct pt_regs *);
140 static void bpt_cmds(void);
141 static void cacheflush(void);
142 static int cpu_cmd(void);
143 static void csum(void);
144 static void bootcmds(void);
145 static void proccall(void);
146 void dump_segments(void);
147 static void symbol_lookup(void);
148 static void xmon_show_stack(unsigned long sp, unsigned long lr,
150 static void xmon_print_symbol(unsigned long address, const char *mid,
152 static const char *getvecname(unsigned long vec);
154 static int do_spu_cmd(void);
157 static void dump_tlb_44x(void);
159 #ifdef CONFIG_PPC_BOOK3E
160 static void dump_tlb_book3e(void);
163 static int xmon_no_auto_backtrace;
165 extern void xmon_enter(void);
166 extern void xmon_leave(void);
174 #ifdef __LITTLE_ENDIAN__
175 #define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
177 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
180 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
181 || ('a' <= (c) && (c) <= 'f') \
182 || ('A' <= (c) && (c) <= 'F'))
183 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
184 || ('a' <= (c) && (c) <= 'z') \
185 || ('A' <= (c) && (c) <= 'Z'))
186 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
188 static char *help_string = "\
190 b show breakpoints\n\
191 bd set data breakpoint\n\
192 bi set instruction breakpoint\n\
193 bc clear breakpoint\n"
196 c print cpus stopped in xmon\n\
197 c# try to switch to cpu number h (in hex)\n"
202 di dump instructions\n\
203 df dump float values\n\
204 dd dump double values\n\
205 dl dump the kernel log buffer\n"
208 dp[#] dump paca for current cpu, or cpu #\n\
209 dpa dump paca for all possible cpus\n"
212 dr dump stream of raw bytes\n\
213 e print exception information\n\
215 la lookup symbol+offset of specified address\n\
216 ls lookup address of specified symbol\n\
217 m examine/change memory\n\
218 mm move a block of memory\n\
219 ms set a block of memory\n\
220 md compare two blocks of memory\n\
221 ml locate a block of memory\n\
222 mz zero a block of memory\n\
223 mi show information about memory allocation\n\
224 p call a procedure\n\
227 #ifdef CONFIG_SPU_BASE
228 " ss stop execution on all spus\n\
229 sr restore execution on stopped spus\n\
230 sf # dump spu fields for spu # (in hex)\n\
231 sd # dump spu local store for spu # (in hex)\n\
232 sdi # disassemble spu local store for spu # (in hex)\n"
234 " S print special registers\n\
236 x exit monitor and recover\n\
237 X exit monitor and dont recover\n"
238 #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
239 " u dump segment table or SLB\n"
240 #elif defined(CONFIG_PPC_STD_MMU_32)
241 " u dump segment registers\n"
242 #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
250 static struct pt_regs *xmon_regs;
252 static inline void sync(void)
254 asm volatile("sync; isync");
257 static inline void store_inst(void *p)
259 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
262 static inline void cflush(void *p)
264 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
267 static inline void cinval(void *p)
269 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
273 * Disable surveillance (the service processor watchdog function)
274 * while we are in xmon.
275 * XXX we should re-enable it when we leave. :)
277 #define SURVEILLANCE_TOKEN 9000
279 static inline void disable_surveillance(void)
281 #ifdef CONFIG_PPC_PSERIES
282 /* Since this can't be a module, args should end up below 4GB. */
283 static struct rtas_args args;
286 * At this point we have got all the cpus we can into
287 * xmon, so there is hopefully no other cpu calling RTAS
288 * at the moment, even though we don't take rtas.lock.
289 * If we did try to take rtas.lock there would be a
290 * real possibility of deadlock.
292 args.token = rtas_token("set-indicator");
293 if (args.token == RTAS_UNKNOWN_SERVICE)
297 args.rets = &args.args[3];
298 args.args[0] = SURVEILLANCE_TOKEN;
301 enter_rtas(__pa(&args));
302 #endif /* CONFIG_PPC_PSERIES */
306 static int xmon_speaker;
308 static void get_output_lock(void)
310 int me = smp_processor_id() + 0x100;
311 int last_speaker = 0, prev;
314 if (xmon_speaker == me)
318 last_speaker = cmpxchg(&xmon_speaker, 0, me);
319 if (last_speaker == 0)
323 * Wait a full second for the lock, we might be on a slow
324 * console, but check every 100us.
327 while (xmon_speaker == last_speaker) {
333 /* hostile takeover */
334 prev = cmpxchg(&xmon_speaker, last_speaker, me);
335 if (prev == last_speaker)
342 static void release_output_lock(void)
347 int cpus_are_in_xmon(void)
349 return !cpumask_empty(&cpus_in_xmon);
353 static inline int unrecoverable_excp(struct pt_regs *regs)
355 #if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
356 /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
359 return ((regs->msr & MSR_RI) == 0);
363 static int xmon_core(struct pt_regs *regs, int fromipi)
367 long recurse_jmp[JMP_BUF_LEN];
368 unsigned long offset;
373 unsigned long timeout;
376 local_irq_save(flags);
378 bp = in_breakpoint_table(regs->nip, &offset);
380 regs->nip = bp->address + offset;
381 atomic_dec(&bp->ref_count);
387 cpu = smp_processor_id();
388 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
391 printf("cpu 0x%x: Exception %lx %s in xmon, "
392 "returning to main loop\n",
393 cpu, regs->trap, getvecname(TRAP(regs)));
394 release_output_lock();
395 longjmp(xmon_fault_jmp[cpu], 1);
398 if (setjmp(recurse_jmp) != 0) {
399 if (!in_xmon || !xmon_gate) {
401 printf("xmon: WARNING: bad recursive fault "
402 "on cpu 0x%x\n", cpu);
403 release_output_lock();
406 secondary = !(xmon_taken && cpu == xmon_owner);
410 xmon_fault_jmp[cpu] = recurse_jmp;
413 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
414 bp = at_breakpoint(regs->nip);
415 if (bp || unrecoverable_excp(regs))
422 printf("cpu 0x%x stopped at breakpoint 0x%lx (",
424 xmon_print_symbol(regs->nip, " ", ")\n");
426 if (unrecoverable_excp(regs))
427 printf("WARNING: exception is not recoverable, "
429 release_output_lock();
432 cpumask_set_cpu(cpu, &cpus_in_xmon);
436 while (secondary && !xmon_gate) {
440 secondary = test_and_set_bit(0, &in_xmon);
445 if (!secondary && !xmon_gate) {
446 /* we are the first cpu to come in */
447 /* interrupt other cpu(s) */
448 int ncpus = num_online_cpus();
453 smp_send_debugger_break();
454 /* wait for other cpus to come in */
455 for (timeout = 100000000; timeout != 0; --timeout) {
456 if (cpumask_weight(&cpus_in_xmon) >= ncpus)
462 disable_surveillance();
463 /* for breakpoint or single step, print the current instr. */
464 if (bp || TRAP(regs) == 0xd00)
465 ppc_inst_dump(regs->nip, 1, 0);
466 printf("enter ? for help\n");
475 if (cpu == xmon_owner) {
476 if (!test_and_set_bit(0, &xmon_taken)) {
481 while (cpu == xmon_owner)
495 /* have switched to some other cpu */
500 cpumask_clear_cpu(cpu, &cpus_in_xmon);
501 xmon_fault_jmp[cpu] = NULL;
503 /* UP is simple... */
505 printf("Exception %lx %s in xmon, returning to main loop\n",
506 regs->trap, getvecname(TRAP(regs)));
507 longjmp(xmon_fault_jmp[0], 1);
509 if (setjmp(recurse_jmp) == 0) {
510 xmon_fault_jmp[0] = recurse_jmp;
514 bp = at_breakpoint(regs->nip);
516 printf("Stopped at breakpoint %lx (", BP_NUM(bp));
517 xmon_print_symbol(regs->nip, " ", ")\n");
519 if (unrecoverable_excp(regs))
520 printf("WARNING: exception is not recoverable, "
523 disable_surveillance();
524 /* for breakpoint or single step, print the current instr. */
525 if (bp || TRAP(regs) == 0xd00)
526 ppc_inst_dump(regs->nip, 1, 0);
527 printf("enter ? for help\n");
537 if (regs->msr & MSR_DE) {
538 bp = at_breakpoint(regs->nip);
540 regs->nip = (unsigned long) &bp->instr[0];
541 atomic_inc(&bp->ref_count);
545 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
546 bp = at_breakpoint(regs->nip);
548 int stepped = emulate_step(regs, bp->instr[0]);
550 regs->nip = (unsigned long) &bp->instr[0];
551 atomic_inc(&bp->ref_count);
552 } else if (stepped < 0) {
553 printf("Couldn't single-step %s instruction\n",
554 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
561 local_irq_restore(flags);
563 return cmd != 'X' && cmd != EOF;
566 int xmon(struct pt_regs *excp)
571 ppc_save_regs(®s);
575 return xmon_core(excp, 0);
579 irqreturn_t xmon_irq(int irq, void *d)
582 local_irq_save(flags);
583 printf("Keyboard interrupt\n");
584 xmon(get_irq_regs());
585 local_irq_restore(flags);
589 static int xmon_bpt(struct pt_regs *regs)
592 unsigned long offset;
594 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
597 /* Are we at the trap at bp->instr[1] for some bp? */
598 bp = in_breakpoint_table(regs->nip, &offset);
599 if (bp != NULL && offset == 4) {
600 regs->nip = bp->address + 4;
601 atomic_dec(&bp->ref_count);
605 /* Are we at a breakpoint? */
606 bp = at_breakpoint(regs->nip);
615 static int xmon_sstep(struct pt_regs *regs)
623 static int xmon_break_match(struct pt_regs *regs)
625 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
627 if (dabr.enabled == 0)
633 static int xmon_iabr_match(struct pt_regs *regs)
635 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
643 static int xmon_ipi(struct pt_regs *regs)
646 if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
652 static int xmon_fault_handler(struct pt_regs *regs)
655 unsigned long offset;
657 if (in_xmon && catch_memory_errors)
658 handle_fault(regs); /* doesn't return */
660 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
661 bp = in_breakpoint_table(regs->nip, &offset);
663 regs->nip = bp->address + offset;
664 atomic_dec(&bp->ref_count);
671 static struct bpt *at_breakpoint(unsigned long pc)
677 for (i = 0; i < NBPTS; ++i, ++bp)
678 if (bp->enabled && pc == bp->address)
683 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
687 off = nip - (unsigned long) bpts;
688 if (off >= sizeof(bpts))
690 off %= sizeof(struct bpt);
691 if (off != offsetof(struct bpt, instr[0])
692 && off != offsetof(struct bpt, instr[1]))
694 *offp = off - offsetof(struct bpt, instr[0]);
695 return (struct bpt *) (nip - off);
698 static struct bpt *new_breakpoint(unsigned long a)
703 bp = at_breakpoint(a);
707 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
708 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
710 bp->instr[1] = bpinstr;
711 store_inst(&bp->instr[1]);
716 printf("Sorry, no free breakpoints. Please clear one first.\n");
720 static void insert_bpts(void)
726 for (i = 0; i < NBPTS; ++i, ++bp) {
727 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
729 if (mread(bp->address, &bp->instr[0], 4) != 4) {
730 printf("Couldn't read instruction at %lx, "
731 "disabling breakpoint there\n", bp->address);
735 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
736 printf("Breakpoint at %lx is on an mtmsrd or rfid "
737 "instruction, disabling it\n", bp->address);
741 store_inst(&bp->instr[0]);
742 if (bp->enabled & BP_IABR)
744 if (mwrite(bp->address, &bpinstr, 4) != 4) {
745 printf("Couldn't write instruction at %lx, "
746 "disabling breakpoint there\n", bp->address);
747 bp->enabled &= ~BP_TRAP;
750 store_inst((void *)bp->address);
754 static void insert_cpu_bpts(void)
756 struct arch_hw_breakpoint brk;
759 brk.address = dabr.address;
760 brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
762 __set_breakpoint(&brk);
764 if (iabr && cpu_has_feature(CPU_FTR_IABR))
765 mtspr(SPRN_IABR, iabr->address
766 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
769 static void remove_bpts(void)
776 for (i = 0; i < NBPTS; ++i, ++bp) {
777 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
779 if (mread(bp->address, &instr, 4) == 4
781 && mwrite(bp->address, &bp->instr, 4) != 4)
782 printf("Couldn't remove breakpoint at %lx\n",
785 store_inst((void *)bp->address);
789 static void remove_cpu_bpts(void)
791 hw_breakpoint_disable();
792 if (cpu_has_feature(CPU_FTR_IABR))
796 /* Command interpreting routine */
797 static char *last_cmd;
800 cmds(struct pt_regs *excp)
807 if (!xmon_no_auto_backtrace) {
808 xmon_no_auto_backtrace = 1;
809 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
814 printf("%x:", smp_processor_id());
815 #endif /* CONFIG_SMP */
821 if (last_cmd == NULL)
823 take_input(last_cmd);
857 prregs(excp); /* print regs */
872 if (do_spu_cmd() == 0)
881 printf(" <no input ...>\n");
885 xmon_puts(help_string);
903 #ifdef CONFIG_PPC_STD_MMU
907 #elif defined(CONFIG_4xx)
911 #elif defined(CONFIG_PPC_BOOK3E)
917 printf("Unrecognized command: ");
919 if (' ' < cmd && cmd <= '~')
922 printf("\\x%x", cmd);
924 } while (cmd != '\n');
925 printf(" (type ? for help)\n");
932 static int do_step(struct pt_regs *regs)
935 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
940 * Step a single instruction.
941 * Some instructions we emulate, others we execute with MSR_SE set.
943 static int do_step(struct pt_regs *regs)
948 /* check we are in 64-bit kernel mode, translation enabled */
949 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
950 if (mread(regs->nip, &instr, 4) == 4) {
951 stepped = emulate_step(regs, instr);
953 printf("Couldn't single-step %s instruction\n",
954 (IS_RFID(instr)? "rfid": "mtmsrd"));
958 regs->trap = 0xd00 | (regs->trap & 1);
959 printf("stepped to ");
960 xmon_print_symbol(regs->nip, " ", "\n");
961 ppc_inst_dump(regs->nip, 1, 0);
971 static void bootcmds(void)
977 ppc_md.restart(NULL);
984 static int cpu_cmd(void)
987 unsigned long cpu, first_cpu, last_cpu;
990 if (!scanhex(&cpu)) {
991 /* print cpus waiting or in xmon */
992 printf("cpus stopped:");
993 last_cpu = first_cpu = NR_CPUS;
994 for_each_possible_cpu(cpu) {
995 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
996 if (cpu == last_cpu + 1) {
999 if (last_cpu != first_cpu)
1000 printf("-0x%lx", last_cpu);
1001 last_cpu = first_cpu = cpu;
1002 printf(" 0x%lx", cpu);
1006 if (last_cpu != first_cpu)
1007 printf("-0x%lx", last_cpu);
1011 /* try to switch to cpu specified */
1012 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1013 printf("cpu 0x%x isn't in xmon\n", cpu);
1020 while (!xmon_taken) {
1021 if (--timeout == 0) {
1022 if (test_and_set_bit(0, &xmon_taken))
1024 /* take control back */
1026 xmon_owner = smp_processor_id();
1027 printf("cpu 0x%x didn't take control\n", cpu);
1035 #endif /* CONFIG_SMP */
1038 static unsigned short fcstab[256] = {
1039 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1040 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1041 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1042 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1043 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1044 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1045 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1046 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1047 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1048 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1049 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1050 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1051 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1052 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1053 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1054 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1055 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1056 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1057 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1058 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1059 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1060 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1061 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1062 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1063 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1064 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1065 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1066 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1067 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1068 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1069 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1070 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1073 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1082 if (!scanhex(&adrs))
1084 if (!scanhex(&ncsum))
1087 for (i = 0; i < ncsum; ++i) {
1088 if (mread(adrs+i, &v, 1) == 0) {
1089 printf("csum stopped at "REG"\n", adrs+i);
1094 printf("%x\n", fcs);
1098 * Check if this is a suitable place to put a breakpoint.
1100 static long check_bp_loc(unsigned long addr)
1105 if (!is_kernel_addr(addr)) {
1106 printf("Breakpoints may only be placed at kernel addresses\n");
1109 if (!mread(addr, &instr, sizeof(instr))) {
1110 printf("Can't read instruction at address %lx\n", addr);
1113 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1114 printf("Breakpoints may not be placed on mtmsrd or rfid "
1121 static char *breakpoint_help_string =
1122 "Breakpoint command usage:\n"
1123 "b show breakpoints\n"
1124 "b <addr> [cnt] set breakpoint at given instr addr\n"
1125 "bc clear all breakpoints\n"
1126 "bc <n/addr> clear breakpoint number n or at addr\n"
1127 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1128 "bd <addr> [cnt] set hardware data breakpoint\n"
1138 const char badaddr[] = "Only kernel addresses are permitted "
1139 "for breakpoints\n";
1144 case 'd': /* bd - hardware data breakpoint */
1149 else if (cmd == 'w')
1155 if (scanhex(&dabr.address)) {
1156 if (!is_kernel_addr(dabr.address)) {
1160 dabr.address &= ~HW_BRK_TYPE_DABR;
1161 dabr.enabled = mode | BP_DABR;
1165 case 'i': /* bi - hardware instr breakpoint */
1166 if (!cpu_has_feature(CPU_FTR_IABR)) {
1167 printf("Hardware instruction breakpoint "
1168 "not supported on this cpu\n");
1172 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1177 if (!check_bp_loc(a))
1179 bp = new_breakpoint(a);
1181 bp->enabled |= BP_IABR | BP_IABR_TE;
1189 /* clear all breakpoints */
1190 for (i = 0; i < NBPTS; ++i)
1191 bpts[i].enabled = 0;
1194 printf("All breakpoints cleared\n");
1198 if (a <= NBPTS && a >= 1) {
1199 /* assume a breakpoint number */
1200 bp = &bpts[a-1]; /* bp nums are 1 based */
1202 /* assume a breakpoint address */
1203 bp = at_breakpoint(a);
1205 printf("No breakpoint at %lx\n", a);
1210 printf("Cleared breakpoint %lx (", BP_NUM(bp));
1211 xmon_print_symbol(bp->address, " ", ")\n");
1219 printf(breakpoint_help_string);
1224 /* print all breakpoints */
1225 printf(" type address\n");
1227 printf(" data "REG" [", dabr.address);
1228 if (dabr.enabled & 1)
1230 if (dabr.enabled & 2)
1234 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1237 printf("%2x %s ", BP_NUM(bp),
1238 (bp->enabled & BP_IABR)? "inst": "trap");
1239 xmon_print_symbol(bp->address, " ", "\n");
1244 if (!check_bp_loc(a))
1246 bp = new_breakpoint(a);
1248 bp->enabled |= BP_TRAP;
1253 /* Very cheap human name for vector lookup. */
1255 const char *getvecname(unsigned long vec)
1260 case 0x100: ret = "(System Reset)"; break;
1261 case 0x200: ret = "(Machine Check)"; break;
1262 case 0x300: ret = "(Data Access)"; break;
1263 case 0x380: ret = "(Data SLB Access)"; break;
1264 case 0x400: ret = "(Instruction Access)"; break;
1265 case 0x480: ret = "(Instruction SLB Access)"; break;
1266 case 0x500: ret = "(Hardware Interrupt)"; break;
1267 case 0x600: ret = "(Alignment)"; break;
1268 case 0x700: ret = "(Program Check)"; break;
1269 case 0x800: ret = "(FPU Unavailable)"; break;
1270 case 0x900: ret = "(Decrementer)"; break;
1271 case 0x980: ret = "(Hypervisor Decrementer)"; break;
1272 case 0xa00: ret = "(Doorbell)"; break;
1273 case 0xc00: ret = "(System Call)"; break;
1274 case 0xd00: ret = "(Single Step)"; break;
1275 case 0xe40: ret = "(Emulation Assist)"; break;
1276 case 0xe60: ret = "(HMI)"; break;
1277 case 0xe80: ret = "(Hypervisor Doorbell)"; break;
1278 case 0xf00: ret = "(Performance Monitor)"; break;
1279 case 0xf20: ret = "(Altivec Unavailable)"; break;
1280 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1281 case 0x1500: ret = "(Denormalisation)"; break;
1282 case 0x1700: ret = "(Altivec Assist)"; break;
1288 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1289 unsigned long *endp)
1291 unsigned long size, offset;
1294 *startp = *endp = 0;
1297 if (setjmp(bus_error_jmp) == 0) {
1298 catch_memory_errors = 1;
1300 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1302 *startp = pc - offset;
1303 *endp = pc - offset + size;
1307 catch_memory_errors = 0;
1310 #define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1311 #define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1313 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1316 int max_to_print = 64;
1318 unsigned long newsp;
1319 unsigned long marker;
1320 struct pt_regs regs;
1322 while (max_to_print--) {
1323 if (sp < PAGE_OFFSET) {
1325 printf("SP (%lx) is in userspace\n", sp);
1329 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1330 || !mread(sp, &newsp, sizeof(unsigned long))) {
1331 printf("Couldn't read stack frame at %lx\n", sp);
1336 * For the first stack frame, try to work out if
1337 * LR and/or the saved LR value in the bottommost
1338 * stack frame are valid.
1340 if ((pc | lr) != 0) {
1341 unsigned long fnstart, fnend;
1342 unsigned long nextip;
1345 get_function_bounds(pc, &fnstart, &fnend);
1348 mread(newsp + LRSAVE_OFFSET, &nextip,
1349 sizeof(unsigned long));
1351 if (lr < PAGE_OFFSET
1352 || (fnstart <= lr && lr < fnend))
1354 } else if (lr == nextip) {
1356 } else if (lr >= PAGE_OFFSET
1357 && !(fnstart <= lr && lr < fnend)) {
1358 printf("[link register ] ");
1359 xmon_print_symbol(lr, " ", "\n");
1362 printf("["REG"] ", sp);
1363 xmon_print_symbol(ip, " ", " (unreliable)\n");
1368 printf("["REG"] ", sp);
1369 xmon_print_symbol(ip, " ", "\n");
1372 /* Look for "regshere" marker to see if this is
1373 an exception frame. */
1374 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1375 && marker == STACK_FRAME_REGS_MARKER) {
1376 if (mread(sp + STACK_FRAME_OVERHEAD, ®s, sizeof(regs))
1378 printf("Couldn't read registers at %lx\n",
1379 sp + STACK_FRAME_OVERHEAD);
1382 printf("--- Exception: %lx %s at ", regs.trap,
1383 getvecname(TRAP(®s)));
1386 xmon_print_symbol(pc, " ", "\n");
1396 static void backtrace(struct pt_regs *excp)
1401 xmon_show_stack(sp, 0, 0);
1403 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1407 static void print_bug_trap(struct pt_regs *regs)
1410 const struct bug_entry *bug;
1413 if (regs->msr & MSR_PR)
1414 return; /* not in kernel */
1415 addr = regs->nip; /* address of trap instruction */
1416 if (addr < PAGE_OFFSET)
1418 bug = find_bug(regs->nip);
1421 if (is_warning_bug(bug))
1424 #ifdef CONFIG_DEBUG_BUGVERBOSE
1425 printf("kernel BUG at %s:%u!\n",
1426 bug->file, bug->line);
1428 printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
1430 #endif /* CONFIG_BUG */
1433 static void excprint(struct pt_regs *fp)
1438 printf("cpu 0x%x: ", smp_processor_id());
1439 #endif /* CONFIG_SMP */
1442 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1444 xmon_print_symbol(fp->nip, ": ", "\n");
1446 printf(" lr: ", fp->link);
1447 xmon_print_symbol(fp->link, ": ", "\n");
1449 printf(" sp: %lx\n", fp->gpr[1]);
1450 printf(" msr: %lx\n", fp->msr);
1452 if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
1453 printf(" dar: %lx\n", fp->dar);
1455 printf(" dsisr: %lx\n", fp->dsisr);
1458 printf(" current = 0x%lx\n", current);
1460 printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
1461 local_paca, local_paca->soft_enabled, local_paca->irq_happened);
1464 printf(" pid = %ld, comm = %s\n",
1465 current->pid, current->comm);
1472 static void prregs(struct pt_regs *fp)
1476 struct pt_regs regs;
1478 if (scanhex(&base)) {
1479 if (setjmp(bus_error_jmp) == 0) {
1480 catch_memory_errors = 1;
1482 regs = *(struct pt_regs *)base;
1486 catch_memory_errors = 0;
1487 printf("*** Error reading registers from "REG"\n",
1491 catch_memory_errors = 0;
1496 if (FULL_REGS(fp)) {
1497 for (n = 0; n < 16; ++n)
1498 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1499 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1501 for (n = 0; n < 7; ++n)
1502 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1503 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1506 for (n = 0; n < 32; ++n) {
1507 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1508 (n & 3) == 3? "\n": " ");
1509 if (n == 12 && !FULL_REGS(fp)) {
1516 xmon_print_symbol(fp->nip, " ", "\n");
1517 if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1519 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1522 xmon_print_symbol(fp->link, " ", "\n");
1523 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1524 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1525 fp->ctr, fp->xer, fp->trap);
1527 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1528 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1531 static void cacheflush(void)
1534 unsigned long nflush;
1539 scanhex((void *)&adrs);
1544 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1545 if (setjmp(bus_error_jmp) == 0) {
1546 catch_memory_errors = 1;
1550 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1551 cflush((void *) adrs);
1553 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1554 cinval((void *) adrs);
1557 /* wait a little while to see if we get a machine check */
1560 catch_memory_errors = 0;
1563 static unsigned long
1566 unsigned int instrs[2];
1567 unsigned long (*code)(void);
1568 unsigned long ret = -1UL;
1570 unsigned long opd[3];
1572 opd[0] = (unsigned long)instrs;
1575 code = (unsigned long (*)(void)) opd;
1577 code = (unsigned long (*)(void)) instrs;
1580 /* mfspr r3,n; blr */
1581 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1582 instrs[1] = 0x4e800020;
1584 store_inst(instrs+1);
1586 if (setjmp(bus_error_jmp) == 0) {
1587 catch_memory_errors = 1;
1593 /* wait a little while to see if we get a machine check */
1602 write_spr(int n, unsigned long val)
1604 unsigned int instrs[2];
1605 unsigned long (*code)(unsigned long);
1607 unsigned long opd[3];
1609 opd[0] = (unsigned long)instrs;
1612 code = (unsigned long (*)(unsigned long)) opd;
1614 code = (unsigned long (*)(unsigned long)) instrs;
1617 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1618 instrs[1] = 0x4e800020;
1620 store_inst(instrs+1);
1622 if (setjmp(bus_error_jmp) == 0) {
1623 catch_memory_errors = 1;
1629 /* wait a little while to see if we get a machine check */
1635 static unsigned long regno;
1636 extern char exc_prolog;
1637 extern char dec_exc;
1639 static void super_regs(void)
1646 unsigned long sp, toc;
1647 asm("mr %0,1" : "=r" (sp) :);
1648 asm("mr %0,2" : "=r" (toc) :);
1650 printf("msr = "REG" sprg0= "REG"\n",
1651 mfmsr(), mfspr(SPRN_SPRG0));
1652 printf("pvr = "REG" sprg1= "REG"\n",
1653 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1654 printf("dec = "REG" sprg2= "REG"\n",
1655 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1656 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1657 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1665 val = read_spr(regno);
1667 write_spr(regno, val);
1670 printf("spr %lx = %lx\n", regno, read_spr(regno));
1677 * Stuff for reading and writing memory safely
1680 mread(unsigned long adrs, void *buf, int size)
1686 if (setjmp(bus_error_jmp) == 0) {
1687 catch_memory_errors = 1;
1693 *(u16 *)q = *(u16 *)p;
1696 *(u32 *)q = *(u32 *)p;
1699 *(u64 *)q = *(u64 *)p;
1702 for( ; n < size; ++n) {
1708 /* wait a little while to see if we get a machine check */
1712 catch_memory_errors = 0;
1717 mwrite(unsigned long adrs, void *buf, int size)
1723 if (setjmp(bus_error_jmp) == 0) {
1724 catch_memory_errors = 1;
1730 *(u16 *)p = *(u16 *)q;
1733 *(u32 *)p = *(u32 *)q;
1736 *(u64 *)p = *(u64 *)q;
1739 for ( ; n < size; ++n) {
1745 /* wait a little while to see if we get a machine check */
1749 printf("*** Error writing address "REG"\n", adrs + n);
1751 catch_memory_errors = 0;
1755 static int fault_type;
1756 static int fault_except;
1757 static char *fault_chars[] = { "--", "**", "##" };
1759 static int handle_fault(struct pt_regs *regs)
1761 fault_except = TRAP(regs);
1762 switch (TRAP(regs)) {
1774 longjmp(bus_error_jmp, 1);
1779 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1782 byterev(unsigned char *val, int size)
1788 SWAP(val[0], val[1], t);
1791 SWAP(val[0], val[3], t);
1792 SWAP(val[1], val[2], t);
1794 case 8: /* is there really any use for this? */
1795 SWAP(val[0], val[7], t);
1796 SWAP(val[1], val[6], t);
1797 SWAP(val[2], val[5], t);
1798 SWAP(val[3], val[4], t);
1806 static char *memex_help_string =
1807 "Memory examine command usage:\n"
1808 "m [addr] [flags] examine/change memory\n"
1809 " addr is optional. will start where left off.\n"
1810 " flags may include chars from this set:\n"
1811 " b modify by bytes (default)\n"
1812 " w modify by words (2 byte)\n"
1813 " l modify by longs (4 byte)\n"
1814 " d modify by doubleword (8 byte)\n"
1815 " r toggle reverse byte order mode\n"
1816 " n do not read memory (for i/o spaces)\n"
1817 " . ok to read (default)\n"
1818 "NOTE: flags are saved as defaults\n"
1821 static char *memex_subcmd_help_string =
1822 "Memory examine subcommands:\n"
1823 " hexval write this val to current location\n"
1824 " 'string' write chars from string to this location\n"
1825 " ' increment address\n"
1826 " ^ decrement address\n"
1827 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1828 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1829 " ` clear no-read flag\n"
1830 " ; stay at this addr\n"
1831 " v change to byte mode\n"
1832 " w change to word (2 byte) mode\n"
1833 " l change to long (4 byte) mode\n"
1834 " u change to doubleword (8 byte) mode\n"
1835 " m addr change current addr\n"
1836 " n toggle no-read flag\n"
1837 " r toggle byte reverse flag\n"
1838 " < count back up count bytes\n"
1839 " > count skip forward count bytes\n"
1840 " x exit this mode\n"
1846 int cmd, inc, i, nslash;
1848 unsigned char val[16];
1850 scanhex((void *)&adrs);
1853 printf(memex_help_string);
1859 while ((cmd = skipbl()) != '\n') {
1861 case 'b': size = 1; break;
1862 case 'w': size = 2; break;
1863 case 'l': size = 4; break;
1864 case 'd': size = 8; break;
1865 case 'r': brev = !brev; break;
1866 case 'n': mnoread = 1; break;
1867 case '.': mnoread = 0; break;
1876 n = mread(adrs, val, size);
1877 printf(REG"%c", adrs, brev? 'r': ' ');
1882 for (i = 0; i < n; ++i)
1883 printf("%.2x", val[i]);
1884 for (; i < size; ++i)
1885 printf("%s", fault_chars[fault_type]);
1892 for (i = 0; i < size; ++i)
1893 val[i] = n >> (i * 8);
1896 mwrite(adrs, val, size);
1909 else if( n == '\'' )
1911 for (i = 0; i < size; ++i)
1912 val[i] = n >> (i * 8);
1915 mwrite(adrs, val, size);
1952 adrs -= 1 << nslash;
1956 adrs += 1 << nslash;
1960 adrs += 1 << -nslash;
1964 adrs -= 1 << -nslash;
1967 scanhex((void *)&adrs);
1986 printf(memex_subcmd_help_string);
2001 case 'n': c = '\n'; break;
2002 case 'r': c = '\r'; break;
2003 case 'b': c = '\b'; break;
2004 case 't': c = '\t'; break;
2009 static void xmon_rawdump (unsigned long adrs, long ndump)
2012 unsigned char temp[16];
2014 for (n = ndump; n > 0;) {
2016 nr = mread(adrs, temp, r);
2018 for (m = 0; m < r; ++m) {
2020 printf("%.2x", temp[m]);
2022 printf("%s", fault_chars[fault_type]);
2032 static void dump_one_paca(int cpu)
2034 struct paca_struct *p;
2036 if (setjmp(bus_error_jmp) != 0) {
2037 printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
2041 catch_memory_errors = 1;
2046 printf("paca for cpu 0x%x @ %p:\n", cpu, p);
2048 printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
2049 printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
2050 printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
2052 #define DUMP(paca, name, format) \
2053 printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
2054 offsetof(struct paca_struct, name));
2056 DUMP(p, lock_token, "x");
2057 DUMP(p, paca_index, "x");
2058 DUMP(p, kernel_toc, "lx");
2059 DUMP(p, kernelbase, "lx");
2060 DUMP(p, kernel_msr, "lx");
2061 #ifdef CONFIG_PPC_STD_MMU_64
2062 DUMP(p, stab_real, "lx");
2063 DUMP(p, stab_addr, "lx");
2065 DUMP(p, emergency_sp, "p");
2066 #ifdef CONFIG_PPC_BOOK3S_64
2067 DUMP(p, mc_emergency_sp, "p");
2068 DUMP(p, in_mce, "x");
2070 DUMP(p, data_offset, "lx");
2071 DUMP(p, hw_cpu_id, "x");
2072 DUMP(p, cpu_start, "x");
2073 DUMP(p, kexec_state, "x");
2074 DUMP(p, __current, "p");
2075 DUMP(p, kstack, "lx");
2076 DUMP(p, stab_rr, "lx");
2077 DUMP(p, saved_r1, "lx");
2078 DUMP(p, trap_save, "x");
2079 DUMP(p, soft_enabled, "x");
2080 DUMP(p, irq_happened, "x");
2081 DUMP(p, io_sync, "x");
2082 DUMP(p, irq_work_pending, "x");
2083 DUMP(p, nap_state_lost, "x");
2087 catch_memory_errors = 0;
2091 static void dump_all_pacas(void)
2095 if (num_possible_cpus() == 0) {
2096 printf("No possible cpus, use 'dp #' to dump individual cpus\n");
2100 for_each_possible_cpu(cpu)
2104 static void dump_pacas(void)
2115 termch = c; /* Put c back, it wasn't 'a' */
2120 dump_one_paca(xmon_owner);
2124 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
2125 || ('a' <= (c) && (c) <= 'f') \
2126 || ('A' <= (c) && (c) <= 'F'))
2141 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2143 scanhex((void *)&adrs);
2150 else if (nidump > MAX_DUMP)
2152 adrs += ppc_inst_dump(adrs, nidump, 1);
2154 } else if (c == 'l') {
2156 } else if (c == 'r') {
2160 xmon_rawdump(adrs, ndump);
2167 else if (ndump > MAX_DUMP)
2169 prdump(adrs, ndump);
2176 prdump(unsigned long adrs, long ndump)
2178 long n, m, c, r, nr;
2179 unsigned char temp[16];
2181 for (n = ndump; n > 0;) {
2185 nr = mread(adrs, temp, r);
2187 for (m = 0; m < r; ++m) {
2188 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2191 printf("%.2x", temp[m]);
2193 printf("%s", fault_chars[fault_type]);
2195 for (; m < 16; ++m) {
2196 if ((m & (sizeof(long) - 1)) == 0)
2201 for (m = 0; m < r; ++m) {
2204 putchar(' ' <= c && c <= '~'? c: '.');
2217 typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2220 generic_inst_dump(unsigned long adr, long count, int praddr,
2221 instruction_dump_func dump_func)
2224 unsigned long first_adr;
2225 unsigned long inst, last_inst = 0;
2226 unsigned char val[4];
2229 for (first_adr = adr; count > 0; --count, adr += 4) {
2230 nr = mread(adr, val, 4);
2233 const char *x = fault_chars[fault_type];
2234 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2238 inst = GETWORD(val);
2239 if (adr > first_adr && inst == last_inst) {
2249 printf(REG" %.8x", adr, inst);
2251 dump_func(inst, adr);
2254 return adr - first_adr;
2258 ppc_inst_dump(unsigned long adr, long count, int praddr)
2260 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2264 print_address(unsigned long addr)
2266 xmon_print_symbol(addr, "\t# ", "");
2272 struct kmsg_dumper dumper = { .active = 1 };
2273 unsigned char buf[128];
2276 if (setjmp(bus_error_jmp) != 0) {
2277 printf("Error dumping printk buffer!\n");
2281 catch_memory_errors = 1;
2284 kmsg_dump_rewind_nolock(&dumper);
2285 while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
2291 /* wait a little while to see if we get a machine check */
2293 catch_memory_errors = 0;
2297 * Memory operations - move, set, print differences
2299 static unsigned long mdest; /* destination address */
2300 static unsigned long msrc; /* source address */
2301 static unsigned long mval; /* byte value to set memory to */
2302 static unsigned long mcount; /* # bytes to affect */
2303 static unsigned long mdiffs; /* max # differences to print */
2308 scanhex((void *)&mdest);
2309 if( termch != '\n' )
2311 scanhex((void *)(cmd == 's'? &mval: &msrc));
2312 if( termch != '\n' )
2314 scanhex((void *)&mcount);
2317 memmove((void *)mdest, (void *)msrc, mcount);
2320 memset((void *)mdest, mval, mcount);
2323 if( termch != '\n' )
2325 scanhex((void *)&mdiffs);
2326 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2332 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2337 for( n = nb; n > 0; --n )
2338 if( *p1++ != *p2++ )
2339 if( ++prt <= maxpr )
2340 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2341 p1[-1], p2 - 1, p2[-1]);
2343 printf("Total of %d differences\n", prt);
2346 static unsigned mend;
2347 static unsigned mask;
2353 unsigned char val[4];
2356 scanhex((void *)&mdest);
2357 if (termch != '\n') {
2359 scanhex((void *)&mend);
2360 if (termch != '\n') {
2362 scanhex((void *)&mval);
2364 if (termch != '\n') termch = 0;
2365 scanhex((void *)&mask);
2369 for (a = mdest; a < mend; a += 4) {
2370 if (mread(a, val, 4) == 4
2371 && ((GETWORD(val) ^ mval) & mask) == 0) {
2372 printf("%.16x: %.16x\n", a, GETWORD(val));
2379 static unsigned long mskip = 0x1000;
2380 static unsigned long mlim = 0xffffffff;
2390 if (termch != '\n') termch = 0;
2392 if (termch != '\n') termch = 0;
2395 for (a = mdest; a < mlim; a += mskip) {
2396 ok = mread(a, &v, 1);
2398 printf("%.8x .. ", a);
2399 } else if (!ok && ook)
2400 printf("%.8x\n", a - mskip);
2406 printf("%.8x\n", a - mskip);
2409 static void proccall(void)
2411 unsigned long args[8];
2414 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2415 unsigned long, unsigned long, unsigned long,
2416 unsigned long, unsigned long, unsigned long);
2419 if (!scanhex(&adrs))
2423 for (i = 0; i < 8; ++i)
2425 for (i = 0; i < 8; ++i) {
2426 if (!scanhex(&args[i]) || termch == '\n')
2430 func = (callfunc_t) adrs;
2432 if (setjmp(bus_error_jmp) == 0) {
2433 catch_memory_errors = 1;
2435 ret = func(args[0], args[1], args[2], args[3],
2436 args[4], args[5], args[6], args[7]);
2438 printf("return value is 0x%lx\n", ret);
2440 printf("*** %x exception occurred\n", fault_except);
2442 catch_memory_errors = 0;
2445 /* Input scanning routines */
2456 while( c == ' ' || c == '\t' )
2462 static char *regnames[N_PTREGS] = {
2463 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2464 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2465 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2466 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2467 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2473 "trap", "dar", "dsisr", "res"
2477 scanhex(unsigned long *vp)
2484 /* parse register name */
2488 for (i = 0; i < sizeof(regname) - 1; ++i) {
2497 for (i = 0; i < N_PTREGS; ++i) {
2498 if (strcmp(regnames[i], regname) == 0) {
2499 if (xmon_regs == NULL) {
2500 printf("regs not available\n");
2503 *vp = ((unsigned long *)xmon_regs)[i];
2507 printf("invalid register name '%%%s'\n", regname);
2511 /* skip leading "0x" if any */
2525 } else if (c == '$') {
2527 for (i=0; i<63; i++) {
2537 if (setjmp(bus_error_jmp) == 0) {
2538 catch_memory_errors = 1;
2540 *vp = kallsyms_lookup_name(tmpstr);
2543 catch_memory_errors = 0;
2545 printf("unknown symbol '%s'\n", tmpstr);
2578 static int hexdigit(int c)
2580 if( '0' <= c && c <= '9' )
2582 if( 'A' <= c && c <= 'F' )
2583 return c - ('A' - 10);
2584 if( 'a' <= c && c <= 'f' )
2585 return c - ('a' - 10);
2590 getstring(char *s, int size)
2601 } while( c != ' ' && c != '\t' && c != '\n' );
2606 static char line[256];
2607 static char *lineptr;
2618 if (lineptr == NULL || *lineptr == 0) {
2619 if (xmon_gets(line, sizeof(line)) == NULL) {
2629 take_input(char *str)
2638 int type = inchar();
2640 static char tmp[64];
2645 xmon_print_symbol(addr, ": ", "\n");
2650 if (setjmp(bus_error_jmp) == 0) {
2651 catch_memory_errors = 1;
2653 addr = kallsyms_lookup_name(tmp);
2655 printf("%s: %lx\n", tmp, addr);
2657 printf("Symbol '%s' not found.\n", tmp);
2660 catch_memory_errors = 0;
2667 /* Print an address in numeric and symbolic form (if possible) */
2668 static void xmon_print_symbol(unsigned long address, const char *mid,
2672 const char *name = NULL;
2673 unsigned long offset, size;
2675 printf(REG, address);
2676 if (setjmp(bus_error_jmp) == 0) {
2677 catch_memory_errors = 1;
2679 name = kallsyms_lookup(address, &size, &offset, &modname,
2682 /* wait a little while to see if we get a machine check */
2686 catch_memory_errors = 0;
2689 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2691 printf(" [%s]", modname);
2693 printf("%s", after);
2696 #ifdef CONFIG_PPC_BOOK3S_64
2697 static void dump_slb(void)
2700 unsigned long esid,vsid,valid;
2703 printf("SLB contents of cpu 0x%x\n", smp_processor_id());
2705 for (i = 0; i < mmu_slb_size; i++) {
2706 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
2707 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
2708 valid = (esid & SLB_ESID_V);
2709 if (valid | esid | vsid) {
2710 printf("%02d %016lx %016lx", i, esid, vsid);
2712 llp = vsid & SLB_VSID_LLP;
2713 if (vsid & SLB_VSID_B_1T) {
2714 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
2716 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2719 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
2721 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2730 static void dump_stab(void)
2733 unsigned long *tmp = (unsigned long *)local_paca->stab_addr;
2735 printf("Segment table contents of cpu 0x%x\n", smp_processor_id());
2737 for (i = 0; i < PAGE_SIZE/16; i++) {
2744 printf("%03d %016lx ", i, a);
2745 printf("%016lx\n", b);
2750 void dump_segments(void)
2752 if (mmu_has_feature(MMU_FTR_SLB))
2759 #ifdef CONFIG_PPC_STD_MMU_32
2760 void dump_segments(void)
2765 for (i = 0; i < 16; ++i)
2766 printf(" %x", mfsrin(i));
2772 static void dump_tlb_44x(void)
2776 for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2777 unsigned long w0,w1,w2;
2778 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
2779 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
2780 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
2781 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2782 if (w0 & PPC44x_TLB_VALID) {
2783 printf("V %08x -> %01x%08x %c%c%c%c%c",
2784 w0 & PPC44x_TLB_EPN_MASK,
2785 w1 & PPC44x_TLB_ERPN_MASK,
2786 w1 & PPC44x_TLB_RPN_MASK,
2787 (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2788 (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2789 (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2790 (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2791 (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2796 #endif /* CONFIG_44x */
2798 #ifdef CONFIG_PPC_BOOK3E
2799 static void dump_tlb_book3e(void)
2801 u32 mmucfg, pidmask, lpidmask;
2803 int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
2805 static const char *pgsz_names[] = {
2840 /* Gather some infos about the MMU */
2841 mmucfg = mfspr(SPRN_MMUCFG);
2842 mmu_version = (mmucfg & 3) + 1;
2843 ntlbs = ((mmucfg >> 2) & 3) + 1;
2844 pidsz = ((mmucfg >> 6) & 0x1f) + 1;
2845 lpidsz = (mmucfg >> 24) & 0xf;
2846 rasz = (mmucfg >> 16) & 0x7f;
2847 if ((mmu_version > 1) && (mmucfg & 0x10000))
2849 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
2850 mmu_version, ntlbs, pidsz, lpidsz, rasz);
2851 pidmask = (1ul << pidsz) - 1;
2852 lpidmask = (1ul << lpidsz) - 1;
2853 ramask = (1ull << rasz) - 1;
2855 for (tlb = 0; tlb < ntlbs; tlb++) {
2857 int nent, assoc, new_cc = 1;
2858 printf("TLB %d:\n------\n", tlb);
2861 tlbcfg = mfspr(SPRN_TLB0CFG);
2864 tlbcfg = mfspr(SPRN_TLB1CFG);
2867 tlbcfg = mfspr(SPRN_TLB2CFG);
2870 tlbcfg = mfspr(SPRN_TLB3CFG);
2873 printf("Unsupported TLB number !\n");
2876 nent = tlbcfg & 0xfff;
2877 assoc = (tlbcfg >> 24) & 0xff;
2878 for (i = 0; i < nent; i++) {
2879 u32 mas0 = MAS0_TLBSEL(tlb);
2880 u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
2883 int esel = i, cc = i;
2891 mas0 |= MAS0_ESEL(esel);
2892 mtspr(SPRN_MAS0, mas0);
2893 mtspr(SPRN_MAS1, mas1);
2894 mtspr(SPRN_MAS2, mas2);
2895 asm volatile("tlbre 0,0,0" : : : "memory");
2896 mas1 = mfspr(SPRN_MAS1);
2897 mas2 = mfspr(SPRN_MAS2);
2898 mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
2899 if (assoc && (i % assoc) == 0)
2901 if (!(mas1 & MAS1_VALID))
2904 printf("%04x- ", i);
2906 printf("%04x-%c", cc, 'A' + esel);
2908 printf(" |%c", 'A' + esel);
2910 printf(" %016llx %04x %s %c%c AS%c",
2912 (mas1 >> 16) & 0x3fff,
2913 pgsz_names[(mas1 >> 7) & 0x1f],
2914 mas1 & MAS1_IND ? 'I' : ' ',
2915 mas1 & MAS1_IPROT ? 'P' : ' ',
2916 mas1 & MAS1_TS ? '1' : '0');
2917 printf(" %c%c%c%c%c%c%c",
2918 mas2 & MAS2_X0 ? 'a' : ' ',
2919 mas2 & MAS2_X1 ? 'v' : ' ',
2920 mas2 & MAS2_W ? 'w' : ' ',
2921 mas2 & MAS2_I ? 'i' : ' ',
2922 mas2 & MAS2_M ? 'm' : ' ',
2923 mas2 & MAS2_G ? 'g' : ' ',
2924 mas2 & MAS2_E ? 'e' : ' ');
2925 printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
2926 if (mas1 & MAS1_IND)
2928 pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
2930 printf(" U%c%c%c S%c%c%c\n",
2931 mas7_mas3 & MAS3_UX ? 'x' : ' ',
2932 mas7_mas3 & MAS3_UW ? 'w' : ' ',
2933 mas7_mas3 & MAS3_UR ? 'r' : ' ',
2934 mas7_mas3 & MAS3_SX ? 'x' : ' ',
2935 mas7_mas3 & MAS3_SW ? 'w' : ' ',
2936 mas7_mas3 & MAS3_SR ? 'r' : ' ');
2940 #endif /* CONFIG_PPC_BOOK3E */
2942 static void xmon_init(int enable)
2946 __debugger_ipi = xmon_ipi;
2947 __debugger_bpt = xmon_bpt;
2948 __debugger_sstep = xmon_sstep;
2949 __debugger_iabr_match = xmon_iabr_match;
2950 __debugger_break_match = xmon_break_match;
2951 __debugger_fault_handler = xmon_fault_handler;
2954 __debugger_ipi = NULL;
2955 __debugger_bpt = NULL;
2956 __debugger_sstep = NULL;
2957 __debugger_iabr_match = NULL;
2958 __debugger_break_match = NULL;
2959 __debugger_fault_handler = NULL;
2963 #ifdef CONFIG_MAGIC_SYSRQ
2964 static void sysrq_handle_xmon(int key)
2966 /* ensure xmon is enabled */
2968 debugger(get_irq_regs());
2971 static struct sysrq_key_op sysrq_xmon_op = {
2972 .handler = sysrq_handle_xmon,
2973 .help_msg = "xmon(x)",
2974 .action_msg = "Entering xmon",
2977 static int __init setup_xmon_sysrq(void)
2979 register_sysrq_key('x', &sysrq_xmon_op);
2982 __initcall(setup_xmon_sysrq);
2983 #endif /* CONFIG_MAGIC_SYSRQ */
2985 static int __initdata xmon_early, xmon_off;
2987 static int __init early_parse_xmon(char *p)
2989 if (!p || strncmp(p, "early", 5) == 0) {
2990 /* just "xmon" is equivalent to "xmon=early" */
2993 } else if (strncmp(p, "on", 2) == 0)
2995 else if (strncmp(p, "off", 3) == 0)
2997 else if (strncmp(p, "nobt", 4) == 0)
2998 xmon_no_auto_backtrace = 1;
3004 early_param("xmon", early_parse_xmon);
3006 void __init xmon_setup(void)
3008 #ifdef CONFIG_XMON_DEFAULT
3016 #ifdef CONFIG_SPU_BASE
3020 u64 saved_mfc_sr1_RW;
3021 u32 saved_spu_runcntl_RW;
3022 unsigned long dump_addr;
3026 #define XMON_NUM_SPUS 16 /* Enough for current hardware */
3028 static struct spu_info spu_info[XMON_NUM_SPUS];
3030 void xmon_register_spus(struct list_head *list)
3034 list_for_each_entry(spu, list, full_list) {
3035 if (spu->number >= XMON_NUM_SPUS) {
3040 spu_info[spu->number].spu = spu;
3041 spu_info[spu->number].stopped_ok = 0;
3042 spu_info[spu->number].dump_addr = (unsigned long)
3043 spu_info[spu->number].spu->local_store;
3047 static void stop_spus(void)
3053 for (i = 0; i < XMON_NUM_SPUS; i++) {
3054 if (!spu_info[i].spu)
3057 if (setjmp(bus_error_jmp) == 0) {
3058 catch_memory_errors = 1;
3061 spu = spu_info[i].spu;
3063 spu_info[i].saved_spu_runcntl_RW =
3064 in_be32(&spu->problem->spu_runcntl_RW);
3066 tmp = spu_mfc_sr1_get(spu);
3067 spu_info[i].saved_mfc_sr1_RW = tmp;
3069 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
3070 spu_mfc_sr1_set(spu, tmp);
3075 spu_info[i].stopped_ok = 1;
3077 printf("Stopped spu %.2d (was %s)\n", i,
3078 spu_info[i].saved_spu_runcntl_RW ?
3079 "running" : "stopped");
3081 catch_memory_errors = 0;
3082 printf("*** Error stopping spu %.2d\n", i);
3084 catch_memory_errors = 0;
3088 static void restart_spus(void)
3093 for (i = 0; i < XMON_NUM_SPUS; i++) {
3094 if (!spu_info[i].spu)
3097 if (!spu_info[i].stopped_ok) {
3098 printf("*** Error, spu %d was not successfully stopped"
3099 ", not restarting\n", i);
3103 if (setjmp(bus_error_jmp) == 0) {
3104 catch_memory_errors = 1;
3107 spu = spu_info[i].spu;
3108 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3109 out_be32(&spu->problem->spu_runcntl_RW,
3110 spu_info[i].saved_spu_runcntl_RW);
3115 printf("Restarted spu %.2d\n", i);
3117 catch_memory_errors = 0;
3118 printf("*** Error restarting spu %.2d\n", i);
3120 catch_memory_errors = 0;
3124 #define DUMP_WIDTH 23
3125 #define DUMP_VALUE(format, field, value) \
3127 if (setjmp(bus_error_jmp) == 0) { \
3128 catch_memory_errors = 1; \
3130 printf(" %-*s = "format"\n", DUMP_WIDTH, \
3135 catch_memory_errors = 0; \
3136 printf(" %-*s = *** Error reading field.\n", \
3137 DUMP_WIDTH, #field); \
3139 catch_memory_errors = 0; \
3142 #define DUMP_FIELD(obj, format, field) \
3143 DUMP_VALUE(format, field, obj->field)
3145 static void dump_spu_fields(struct spu *spu)
3147 printf("Dumping spu fields at address %p:\n", spu);
3149 DUMP_FIELD(spu, "0x%x", number);
3150 DUMP_FIELD(spu, "%s", name);
3151 DUMP_FIELD(spu, "0x%lx", local_store_phys);
3152 DUMP_FIELD(spu, "0x%p", local_store);
3153 DUMP_FIELD(spu, "0x%lx", ls_size);
3154 DUMP_FIELD(spu, "0x%x", node);
3155 DUMP_FIELD(spu, "0x%lx", flags);
3156 DUMP_FIELD(spu, "%d", class_0_pending);
3157 DUMP_FIELD(spu, "0x%lx", class_0_dar);
3158 DUMP_FIELD(spu, "0x%lx", class_1_dar);
3159 DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
3160 DUMP_FIELD(spu, "0x%lx", irqs[0]);
3161 DUMP_FIELD(spu, "0x%lx", irqs[1]);
3162 DUMP_FIELD(spu, "0x%lx", irqs[2]);
3163 DUMP_FIELD(spu, "0x%x", slb_replace);
3164 DUMP_FIELD(spu, "%d", pid);
3165 DUMP_FIELD(spu, "0x%p", mm);
3166 DUMP_FIELD(spu, "0x%p", ctx);
3167 DUMP_FIELD(spu, "0x%p", rq);
3168 DUMP_FIELD(spu, "0x%p", timestamp);
3169 DUMP_FIELD(spu, "0x%lx", problem_phys);
3170 DUMP_FIELD(spu, "0x%p", problem);
3171 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3172 in_be32(&spu->problem->spu_runcntl_RW));
3173 DUMP_VALUE("0x%x", problem->spu_status_R,
3174 in_be32(&spu->problem->spu_status_R));
3175 DUMP_VALUE("0x%x", problem->spu_npc_RW,
3176 in_be32(&spu->problem->spu_npc_RW));
3177 DUMP_FIELD(spu, "0x%p", priv2);
3178 DUMP_FIELD(spu, "0x%p", pdata);
3182 spu_inst_dump(unsigned long adr, long count, int praddr)
3184 return generic_inst_dump(adr, count, praddr, print_insn_spu);
3187 static void dump_spu_ls(unsigned long num, int subcmd)
3189 unsigned long offset, addr, ls_addr;
3191 if (setjmp(bus_error_jmp) == 0) {
3192 catch_memory_errors = 1;
3194 ls_addr = (unsigned long)spu_info[num].spu->local_store;
3198 catch_memory_errors = 0;
3199 printf("*** Error: accessing spu info for spu %d\n", num);
3202 catch_memory_errors = 0;
3204 if (scanhex(&offset))
3205 addr = ls_addr + offset;
3207 addr = spu_info[num].dump_addr;
3209 if (addr >= ls_addr + LS_SIZE) {
3210 printf("*** Error: address outside of local store\n");
3216 addr += spu_inst_dump(addr, 16, 1);
3226 spu_info[num].dump_addr = addr;
3229 static int do_spu_cmd(void)
3231 static unsigned long num = 0;
3232 int cmd, subcmd = 0;
3244 if (isxdigit(subcmd) || subcmd == '\n')
3248 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
3249 printf("*** Error: invalid spu number\n");
3255 dump_spu_fields(spu_info[num].spu);
3258 dump_spu_ls(num, subcmd);
3269 #else /* ! CONFIG_SPU_BASE */
3270 static int do_spu_cmd(void)