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>
27 #include <linux/nmi.h>
29 #include <asm/ptrace.h>
30 #include <asm/string.h>
32 #include <asm/machdep.h>
34 #include <asm/processor.h>
35 #include <asm/pgtable.h>
37 #include <asm/mmu_context.h>
38 #include <asm/cputable.h>
40 #include <asm/sstep.h>
41 #include <asm/irq_regs.h>
43 #include <asm/spu_priv1.h>
44 #include <asm/setjmp.h>
46 #include <asm/debug.h>
47 #include <asm/hw_breakpoint.h>
50 #include <asm/hvcall.h>
54 #if defined(CONFIG_PPC_SPLPAR)
55 #include <asm/plpar_wrappers.h>
57 static inline long plapr_set_ciabr(unsigned long ciabr) {return 0; };
64 static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
65 static unsigned long xmon_taken = 1;
66 static int xmon_owner;
70 #endif /* CONFIG_SMP */
72 static unsigned long in_xmon __read_mostly = 0;
74 static unsigned long adrs;
76 #define MAX_DUMP (128 * 1024)
77 static unsigned long ndump = 64;
78 static unsigned long nidump = 16;
79 static unsigned long ncsum = 4096;
81 static char tmpstr[128];
83 static long bus_error_jmp[JMP_BUF_LEN];
84 static int catch_memory_errors;
85 static long *xmon_fault_jmp[NR_CPUS];
87 /* Breakpoint stuff */
89 unsigned long address;
90 unsigned int instr[2];
96 /* Bits in bpt.enabled */
102 static struct bpt bpts[NBPTS];
103 static struct bpt dabr;
104 static struct bpt *iabr;
105 static unsigned bpinstr = 0x7fe00008; /* trap */
107 #define BP_NUM(bp) ((bp) - bpts + 1)
110 static int cmds(struct pt_regs *);
111 static int mread(unsigned long, void *, int);
112 static int mwrite(unsigned long, void *, int);
113 static int handle_fault(struct pt_regs *);
114 static void byterev(unsigned char *, int);
115 static void memex(void);
116 static int bsesc(void);
117 static void dump(void);
118 static void prdump(unsigned long, long);
119 static int ppc_inst_dump(unsigned long, long, int);
120 static void dump_log_buf(void);
121 static void backtrace(struct pt_regs *);
122 static void excprint(struct pt_regs *);
123 static void prregs(struct pt_regs *);
124 static void memops(int);
125 static void memlocate(void);
126 static void memzcan(void);
127 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
129 int scanhex(unsigned long *valp);
130 static void scannl(void);
131 static int hexdigit(int);
132 void getstring(char *, int);
133 static void flush_input(void);
134 static int inchar(void);
135 static void take_input(char *);
136 static unsigned long read_spr(int);
137 static void write_spr(int, unsigned long);
138 static void super_regs(void);
139 static void remove_bpts(void);
140 static void insert_bpts(void);
141 static void remove_cpu_bpts(void);
142 static void insert_cpu_bpts(void);
143 static struct bpt *at_breakpoint(unsigned long pc);
144 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
145 static int do_step(struct pt_regs *);
146 static void bpt_cmds(void);
147 static void cacheflush(void);
148 static int cpu_cmd(void);
149 static void csum(void);
150 static void bootcmds(void);
151 static void proccall(void);
152 void dump_segments(void);
153 static void symbol_lookup(void);
154 static void xmon_show_stack(unsigned long sp, unsigned long lr,
156 static void xmon_print_symbol(unsigned long address, const char *mid,
158 static const char *getvecname(unsigned long vec);
160 static int do_spu_cmd(void);
163 static void dump_tlb_44x(void);
165 #ifdef CONFIG_PPC_BOOK3E
166 static void dump_tlb_book3e(void);
169 static int xmon_no_auto_backtrace;
171 extern void xmon_enter(void);
172 extern void xmon_leave(void);
180 #ifdef __LITTLE_ENDIAN__
181 #define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
183 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
186 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
187 || ('a' <= (c) && (c) <= 'f') \
188 || ('A' <= (c) && (c) <= 'F'))
189 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
190 || ('a' <= (c) && (c) <= 'z') \
191 || ('A' <= (c) && (c) <= 'Z'))
192 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
194 static char *help_string = "\
196 b show breakpoints\n\
197 bd set data breakpoint\n\
198 bi set instruction breakpoint\n\
199 bc clear breakpoint\n"
202 c print cpus stopped in xmon\n\
203 c# try to switch to cpu number h (in hex)\n"
208 di dump instructions\n\
209 df dump float values\n\
210 dd dump double values\n\
211 dl dump the kernel log buffer\n"
214 dp[#] dump paca for current cpu, or cpu #\n\
215 dpa dump paca for all possible cpus\n"
218 dr dump stream of raw bytes\n\
219 e print exception information\n\
221 la lookup symbol+offset of specified address\n\
222 ls lookup address of specified symbol\n\
223 m examine/change memory\n\
224 mm move a block of memory\n\
225 ms set a block of memory\n\
226 md compare two blocks of memory\n\
227 ml locate a block of memory\n\
228 mz zero a block of memory\n\
229 mi show information about memory allocation\n\
230 p call a procedure\n\
233 #ifdef CONFIG_SPU_BASE
234 " ss stop execution on all spus\n\
235 sr restore execution on stopped spus\n\
236 sf # dump spu fields for spu # (in hex)\n\
237 sd # dump spu local store for spu # (in hex)\n\
238 sdi # disassemble spu local store for spu # (in hex)\n"
240 " S print special registers\n\
242 x exit monitor and recover\n\
243 X exit monitor and dont recover\n"
244 #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
245 " u dump segment table or SLB\n"
246 #elif defined(CONFIG_PPC_STD_MMU_32)
247 " u dump segment registers\n"
248 #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
256 static struct pt_regs *xmon_regs;
258 static inline void sync(void)
260 asm volatile("sync; isync");
263 static inline void store_inst(void *p)
265 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
268 static inline void cflush(void *p)
270 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
273 static inline void cinval(void *p)
275 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
279 * write_ciabr() - write the CIABR SPR
280 * @ciabr: The value to write.
282 * This function writes a value to the CIARB register either directly
283 * through mtspr instruction if the kernel is in HV privilege mode or
284 * call a hypervisor function to achieve the same in case the kernel
285 * is in supervisor privilege mode.
287 static void write_ciabr(unsigned long ciabr)
289 if (!cpu_has_feature(CPU_FTR_ARCH_207S))
292 if (cpu_has_feature(CPU_FTR_HVMODE)) {
293 mtspr(SPRN_CIABR, ciabr);
296 plapr_set_ciabr(ciabr);
300 * set_ciabr() - set the CIABR
301 * @addr: The value to set.
303 * This function sets the correct privilege value into the the HW
304 * breakpoint address before writing it up in the CIABR register.
306 static void set_ciabr(unsigned long addr)
310 if (cpu_has_feature(CPU_FTR_HVMODE))
311 addr |= CIABR_PRIV_HYPER;
313 addr |= CIABR_PRIV_SUPER;
318 * Disable surveillance (the service processor watchdog function)
319 * while we are in xmon.
320 * XXX we should re-enable it when we leave. :)
322 #define SURVEILLANCE_TOKEN 9000
324 static inline void disable_surveillance(void)
326 #ifdef CONFIG_PPC_PSERIES
327 /* Since this can't be a module, args should end up below 4GB. */
328 static struct rtas_args args;
331 * At this point we have got all the cpus we can into
332 * xmon, so there is hopefully no other cpu calling RTAS
333 * at the moment, even though we don't take rtas.lock.
334 * If we did try to take rtas.lock there would be a
335 * real possibility of deadlock.
337 args.token = rtas_token("set-indicator");
338 if (args.token == RTAS_UNKNOWN_SERVICE)
340 args.nargs = cpu_to_be32(3);
341 args.nret = cpu_to_be32(1);
342 args.rets = &args.args[3];
343 args.args[0] = cpu_to_be32(SURVEILLANCE_TOKEN);
346 enter_rtas(__pa(&args));
347 #endif /* CONFIG_PPC_PSERIES */
351 static int xmon_speaker;
353 static void get_output_lock(void)
355 int me = smp_processor_id() + 0x100;
356 int last_speaker = 0, prev;
359 if (xmon_speaker == me)
363 last_speaker = cmpxchg(&xmon_speaker, 0, me);
364 if (last_speaker == 0)
368 * Wait a full second for the lock, we might be on a slow
369 * console, but check every 100us.
372 while (xmon_speaker == last_speaker) {
378 /* hostile takeover */
379 prev = cmpxchg(&xmon_speaker, last_speaker, me);
380 if (prev == last_speaker)
387 static void release_output_lock(void)
392 int cpus_are_in_xmon(void)
394 return !cpumask_empty(&cpus_in_xmon);
398 static inline int unrecoverable_excp(struct pt_regs *regs)
400 #if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
401 /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
404 return ((regs->msr & MSR_RI) == 0);
408 static int xmon_core(struct pt_regs *regs, int fromipi)
412 long recurse_jmp[JMP_BUF_LEN];
413 unsigned long offset;
418 unsigned long timeout;
421 local_irq_save(flags);
424 bp = in_breakpoint_table(regs->nip, &offset);
426 regs->nip = bp->address + offset;
427 atomic_dec(&bp->ref_count);
433 cpu = smp_processor_id();
434 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
437 printf("cpu 0x%x: Exception %lx %s in xmon, "
438 "returning to main loop\n",
439 cpu, regs->trap, getvecname(TRAP(regs)));
440 release_output_lock();
441 longjmp(xmon_fault_jmp[cpu], 1);
444 if (setjmp(recurse_jmp) != 0) {
445 if (!in_xmon || !xmon_gate) {
447 printf("xmon: WARNING: bad recursive fault "
448 "on cpu 0x%x\n", cpu);
449 release_output_lock();
452 secondary = !(xmon_taken && cpu == xmon_owner);
456 xmon_fault_jmp[cpu] = recurse_jmp;
459 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
460 bp = at_breakpoint(regs->nip);
461 if (bp || unrecoverable_excp(regs))
468 printf("cpu 0x%x stopped at breakpoint 0x%lx (",
470 xmon_print_symbol(regs->nip, " ", ")\n");
472 if (unrecoverable_excp(regs))
473 printf("WARNING: exception is not recoverable, "
475 release_output_lock();
478 cpumask_set_cpu(cpu, &cpus_in_xmon);
482 while (secondary && !xmon_gate) {
486 secondary = test_and_set_bit(0, &in_xmon);
491 if (!secondary && !xmon_gate) {
492 /* we are the first cpu to come in */
493 /* interrupt other cpu(s) */
494 int ncpus = num_online_cpus();
499 smp_send_debugger_break();
500 /* wait for other cpus to come in */
501 for (timeout = 100000000; timeout != 0; --timeout) {
502 if (cpumask_weight(&cpus_in_xmon) >= ncpus)
508 disable_surveillance();
509 /* for breakpoint or single step, print the current instr. */
510 if (bp || TRAP(regs) == 0xd00)
511 ppc_inst_dump(regs->nip, 1, 0);
512 printf("enter ? for help\n");
521 if (cpu == xmon_owner) {
522 if (!test_and_set_bit(0, &xmon_taken)) {
527 while (cpu == xmon_owner)
541 /* have switched to some other cpu */
546 cpumask_clear_cpu(cpu, &cpus_in_xmon);
547 xmon_fault_jmp[cpu] = NULL;
549 /* UP is simple... */
551 printf("Exception %lx %s in xmon, returning to main loop\n",
552 regs->trap, getvecname(TRAP(regs)));
553 longjmp(xmon_fault_jmp[0], 1);
555 if (setjmp(recurse_jmp) == 0) {
556 xmon_fault_jmp[0] = recurse_jmp;
560 bp = at_breakpoint(regs->nip);
562 printf("Stopped at breakpoint %lx (", BP_NUM(bp));
563 xmon_print_symbol(regs->nip, " ", ")\n");
565 if (unrecoverable_excp(regs))
566 printf("WARNING: exception is not recoverable, "
569 disable_surveillance();
570 /* for breakpoint or single step, print the current instr. */
571 if (bp || TRAP(regs) == 0xd00)
572 ppc_inst_dump(regs->nip, 1, 0);
573 printf("enter ? for help\n");
583 if (regs->msr & MSR_DE) {
584 bp = at_breakpoint(regs->nip);
586 regs->nip = (unsigned long) &bp->instr[0];
587 atomic_inc(&bp->ref_count);
591 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
592 bp = at_breakpoint(regs->nip);
594 int stepped = emulate_step(regs, bp->instr[0]);
596 regs->nip = (unsigned long) &bp->instr[0];
597 atomic_inc(&bp->ref_count);
598 } else if (stepped < 0) {
599 printf("Couldn't single-step %s instruction\n",
600 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
607 touch_nmi_watchdog();
608 local_irq_restore(flags);
610 return cmd != 'X' && cmd != EOF;
613 int xmon(struct pt_regs *excp)
618 ppc_save_regs(®s);
622 return xmon_core(excp, 0);
626 irqreturn_t xmon_irq(int irq, void *d)
629 local_irq_save(flags);
630 printf("Keyboard interrupt\n");
631 xmon(get_irq_regs());
632 local_irq_restore(flags);
636 static int xmon_bpt(struct pt_regs *regs)
639 unsigned long offset;
641 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
644 /* Are we at the trap at bp->instr[1] for some bp? */
645 bp = in_breakpoint_table(regs->nip, &offset);
646 if (bp != NULL && offset == 4) {
647 regs->nip = bp->address + 4;
648 atomic_dec(&bp->ref_count);
652 /* Are we at a breakpoint? */
653 bp = at_breakpoint(regs->nip);
662 static int xmon_sstep(struct pt_regs *regs)
670 static int xmon_break_match(struct pt_regs *regs)
672 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
674 if (dabr.enabled == 0)
680 static int xmon_iabr_match(struct pt_regs *regs)
682 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
690 static int xmon_ipi(struct pt_regs *regs)
693 if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
699 static int xmon_fault_handler(struct pt_regs *regs)
702 unsigned long offset;
704 if (in_xmon && catch_memory_errors)
705 handle_fault(regs); /* doesn't return */
707 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
708 bp = in_breakpoint_table(regs->nip, &offset);
710 regs->nip = bp->address + offset;
711 atomic_dec(&bp->ref_count);
718 static struct bpt *at_breakpoint(unsigned long pc)
724 for (i = 0; i < NBPTS; ++i, ++bp)
725 if (bp->enabled && pc == bp->address)
730 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
734 off = nip - (unsigned long) bpts;
735 if (off >= sizeof(bpts))
737 off %= sizeof(struct bpt);
738 if (off != offsetof(struct bpt, instr[0])
739 && off != offsetof(struct bpt, instr[1]))
741 *offp = off - offsetof(struct bpt, instr[0]);
742 return (struct bpt *) (nip - off);
745 static struct bpt *new_breakpoint(unsigned long a)
750 bp = at_breakpoint(a);
754 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
755 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
757 bp->instr[1] = bpinstr;
758 store_inst(&bp->instr[1]);
763 printf("Sorry, no free breakpoints. Please clear one first.\n");
767 static void insert_bpts(void)
773 for (i = 0; i < NBPTS; ++i, ++bp) {
774 if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
776 if (mread(bp->address, &bp->instr[0], 4) != 4) {
777 printf("Couldn't read instruction at %lx, "
778 "disabling breakpoint there\n", bp->address);
782 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
783 printf("Breakpoint at %lx is on an mtmsrd or rfid "
784 "instruction, disabling it\n", bp->address);
788 store_inst(&bp->instr[0]);
789 if (bp->enabled & BP_CIABR)
791 if (mwrite(bp->address, &bpinstr, 4) != 4) {
792 printf("Couldn't write instruction at %lx, "
793 "disabling breakpoint there\n", bp->address);
794 bp->enabled &= ~BP_TRAP;
797 store_inst((void *)bp->address);
801 static void insert_cpu_bpts(void)
803 struct arch_hw_breakpoint brk;
806 brk.address = dabr.address;
807 brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
809 __set_breakpoint(&brk);
813 set_ciabr(iabr->address);
816 static void remove_bpts(void)
823 for (i = 0; i < NBPTS; ++i, ++bp) {
824 if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
826 if (mread(bp->address, &instr, 4) == 4
828 && mwrite(bp->address, &bp->instr, 4) != 4)
829 printf("Couldn't remove breakpoint at %lx\n",
832 store_inst((void *)bp->address);
836 static void remove_cpu_bpts(void)
838 hw_breakpoint_disable();
842 /* Command interpreting routine */
843 static char *last_cmd;
846 cmds(struct pt_regs *excp)
853 if (!xmon_no_auto_backtrace) {
854 xmon_no_auto_backtrace = 1;
855 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
860 printf("%x:", smp_processor_id());
861 #endif /* CONFIG_SMP */
867 if (last_cmd == NULL)
869 take_input(last_cmd);
903 prregs(excp); /* print regs */
918 if (do_spu_cmd() == 0)
927 printf(" <no input ...>\n");
931 xmon_puts(help_string);
949 #ifdef CONFIG_PPC_STD_MMU
953 #elif defined(CONFIG_44x)
957 #elif defined(CONFIG_PPC_BOOK3E)
963 printf("Unrecognized command: ");
965 if (' ' < cmd && cmd <= '~')
968 printf("\\x%x", cmd);
970 } while (cmd != '\n');
971 printf(" (type ? for help)\n");
978 static int do_step(struct pt_regs *regs)
981 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
986 * Step a single instruction.
987 * Some instructions we emulate, others we execute with MSR_SE set.
989 static int do_step(struct pt_regs *regs)
994 /* check we are in 64-bit kernel mode, translation enabled */
995 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
996 if (mread(regs->nip, &instr, 4) == 4) {
997 stepped = emulate_step(regs, instr);
999 printf("Couldn't single-step %s instruction\n",
1000 (IS_RFID(instr)? "rfid": "mtmsrd"));
1004 regs->trap = 0xd00 | (regs->trap & 1);
1005 printf("stepped to ");
1006 xmon_print_symbol(regs->nip, " ", "\n");
1007 ppc_inst_dump(regs->nip, 1, 0);
1012 regs->msr |= MSR_SE;
1017 static void bootcmds(void)
1023 ppc_md.restart(NULL);
1024 else if (cmd == 'h')
1026 else if (cmd == 'p')
1031 static int cpu_cmd(void)
1034 unsigned long cpu, first_cpu, last_cpu;
1037 if (!scanhex(&cpu)) {
1038 /* print cpus waiting or in xmon */
1039 printf("cpus stopped:");
1040 last_cpu = first_cpu = NR_CPUS;
1041 for_each_possible_cpu(cpu) {
1042 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1043 if (cpu == last_cpu + 1) {
1046 if (last_cpu != first_cpu)
1047 printf("-0x%lx", last_cpu);
1048 last_cpu = first_cpu = cpu;
1049 printf(" 0x%lx", cpu);
1053 if (last_cpu != first_cpu)
1054 printf("-0x%lx", last_cpu);
1058 /* try to switch to cpu specified */
1059 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1060 printf("cpu 0x%x isn't in xmon\n", cpu);
1067 while (!xmon_taken) {
1068 if (--timeout == 0) {
1069 if (test_and_set_bit(0, &xmon_taken))
1071 /* take control back */
1073 xmon_owner = smp_processor_id();
1074 printf("cpu 0x%x didn't take control\n", cpu);
1082 #endif /* CONFIG_SMP */
1085 static unsigned short fcstab[256] = {
1086 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1087 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1088 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1089 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1090 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1091 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1092 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1093 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1094 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1095 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1096 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1097 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1098 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1099 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1100 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1101 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1102 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1103 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1104 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1105 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1106 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1107 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1108 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1109 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1110 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1111 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1112 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1113 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1114 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1115 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1116 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1117 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1120 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1129 if (!scanhex(&adrs))
1131 if (!scanhex(&ncsum))
1134 for (i = 0; i < ncsum; ++i) {
1135 if (mread(adrs+i, &v, 1) == 0) {
1136 printf("csum stopped at "REG"\n", adrs+i);
1141 printf("%x\n", fcs);
1145 * Check if this is a suitable place to put a breakpoint.
1147 static long check_bp_loc(unsigned long addr)
1152 if (!is_kernel_addr(addr)) {
1153 printf("Breakpoints may only be placed at kernel addresses\n");
1156 if (!mread(addr, &instr, sizeof(instr))) {
1157 printf("Can't read instruction at address %lx\n", addr);
1160 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1161 printf("Breakpoints may not be placed on mtmsrd or rfid "
1168 static char *breakpoint_help_string =
1169 "Breakpoint command usage:\n"
1170 "b show breakpoints\n"
1171 "b <addr> [cnt] set breakpoint at given instr addr\n"
1172 "bc clear all breakpoints\n"
1173 "bc <n/addr> clear breakpoint number n or at addr\n"
1174 "bi <addr> [cnt] set hardware instr breakpoint (POWER8 only)\n"
1175 "bd <addr> [cnt] set hardware data breakpoint\n"
1185 const char badaddr[] = "Only kernel addresses are permitted "
1186 "for breakpoints\n";
1191 case 'd': /* bd - hardware data breakpoint */
1196 else if (cmd == 'w')
1202 if (scanhex(&dabr.address)) {
1203 if (!is_kernel_addr(dabr.address)) {
1207 dabr.address &= ~HW_BRK_TYPE_DABR;
1208 dabr.enabled = mode | BP_DABR;
1212 case 'i': /* bi - hardware instr breakpoint */
1213 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) {
1214 printf("Hardware instruction breakpoint "
1215 "not supported on this cpu\n");
1219 iabr->enabled &= ~BP_CIABR;
1224 if (!check_bp_loc(a))
1226 bp = new_breakpoint(a);
1228 bp->enabled |= BP_CIABR;
1236 /* clear all breakpoints */
1237 for (i = 0; i < NBPTS; ++i)
1238 bpts[i].enabled = 0;
1241 printf("All breakpoints cleared\n");
1245 if (a <= NBPTS && a >= 1) {
1246 /* assume a breakpoint number */
1247 bp = &bpts[a-1]; /* bp nums are 1 based */
1249 /* assume a breakpoint address */
1250 bp = at_breakpoint(a);
1252 printf("No breakpoint at %lx\n", a);
1257 printf("Cleared breakpoint %lx (", BP_NUM(bp));
1258 xmon_print_symbol(bp->address, " ", ")\n");
1266 printf(breakpoint_help_string);
1271 /* print all breakpoints */
1272 printf(" type address\n");
1274 printf(" data "REG" [", dabr.address);
1275 if (dabr.enabled & 1)
1277 if (dabr.enabled & 2)
1281 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1284 printf("%2x %s ", BP_NUM(bp),
1285 (bp->enabled & BP_CIABR) ? "inst": "trap");
1286 xmon_print_symbol(bp->address, " ", "\n");
1291 if (!check_bp_loc(a))
1293 bp = new_breakpoint(a);
1295 bp->enabled |= BP_TRAP;
1300 /* Very cheap human name for vector lookup. */
1302 const char *getvecname(unsigned long vec)
1307 case 0x100: ret = "(System Reset)"; break;
1308 case 0x200: ret = "(Machine Check)"; break;
1309 case 0x300: ret = "(Data Access)"; break;
1310 case 0x380: ret = "(Data SLB Access)"; break;
1311 case 0x400: ret = "(Instruction Access)"; break;
1312 case 0x480: ret = "(Instruction SLB Access)"; break;
1313 case 0x500: ret = "(Hardware Interrupt)"; break;
1314 case 0x600: ret = "(Alignment)"; break;
1315 case 0x700: ret = "(Program Check)"; break;
1316 case 0x800: ret = "(FPU Unavailable)"; break;
1317 case 0x900: ret = "(Decrementer)"; break;
1318 case 0x980: ret = "(Hypervisor Decrementer)"; break;
1319 case 0xa00: ret = "(Doorbell)"; break;
1320 case 0xc00: ret = "(System Call)"; break;
1321 case 0xd00: ret = "(Single Step)"; break;
1322 case 0xe40: ret = "(Emulation Assist)"; break;
1323 case 0xe60: ret = "(HMI)"; break;
1324 case 0xe80: ret = "(Hypervisor Doorbell)"; break;
1325 case 0xf00: ret = "(Performance Monitor)"; break;
1326 case 0xf20: ret = "(Altivec Unavailable)"; break;
1327 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1328 case 0x1500: ret = "(Denormalisation)"; break;
1329 case 0x1700: ret = "(Altivec Assist)"; break;
1335 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1336 unsigned long *endp)
1338 unsigned long size, offset;
1341 *startp = *endp = 0;
1344 if (setjmp(bus_error_jmp) == 0) {
1345 catch_memory_errors = 1;
1347 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1349 *startp = pc - offset;
1350 *endp = pc - offset + size;
1354 catch_memory_errors = 0;
1357 #define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1358 #define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1360 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1363 int max_to_print = 64;
1365 unsigned long newsp;
1366 unsigned long marker;
1367 struct pt_regs regs;
1369 while (max_to_print--) {
1370 if (sp < PAGE_OFFSET) {
1372 printf("SP (%lx) is in userspace\n", sp);
1376 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1377 || !mread(sp, &newsp, sizeof(unsigned long))) {
1378 printf("Couldn't read stack frame at %lx\n", sp);
1383 * For the first stack frame, try to work out if
1384 * LR and/or the saved LR value in the bottommost
1385 * stack frame are valid.
1387 if ((pc | lr) != 0) {
1388 unsigned long fnstart, fnend;
1389 unsigned long nextip;
1392 get_function_bounds(pc, &fnstart, &fnend);
1395 mread(newsp + LRSAVE_OFFSET, &nextip,
1396 sizeof(unsigned long));
1398 if (lr < PAGE_OFFSET
1399 || (fnstart <= lr && lr < fnend))
1401 } else if (lr == nextip) {
1403 } else if (lr >= PAGE_OFFSET
1404 && !(fnstart <= lr && lr < fnend)) {
1405 printf("[link register ] ");
1406 xmon_print_symbol(lr, " ", "\n");
1409 printf("["REG"] ", sp);
1410 xmon_print_symbol(ip, " ", " (unreliable)\n");
1415 printf("["REG"] ", sp);
1416 xmon_print_symbol(ip, " ", "\n");
1419 /* Look for "regshere" marker to see if this is
1420 an exception frame. */
1421 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1422 && marker == STACK_FRAME_REGS_MARKER) {
1423 if (mread(sp + STACK_FRAME_OVERHEAD, ®s, sizeof(regs))
1425 printf("Couldn't read registers at %lx\n",
1426 sp + STACK_FRAME_OVERHEAD);
1429 printf("--- Exception: %lx %s at ", regs.trap,
1430 getvecname(TRAP(®s)));
1433 xmon_print_symbol(pc, " ", "\n");
1443 static void backtrace(struct pt_regs *excp)
1448 xmon_show_stack(sp, 0, 0);
1450 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1454 static void print_bug_trap(struct pt_regs *regs)
1457 const struct bug_entry *bug;
1460 if (regs->msr & MSR_PR)
1461 return; /* not in kernel */
1462 addr = regs->nip; /* address of trap instruction */
1463 if (addr < PAGE_OFFSET)
1465 bug = find_bug(regs->nip);
1468 if (is_warning_bug(bug))
1471 #ifdef CONFIG_DEBUG_BUGVERBOSE
1472 printf("kernel BUG at %s:%u!\n",
1473 bug->file, bug->line);
1475 printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
1477 #endif /* CONFIG_BUG */
1480 static void excprint(struct pt_regs *fp)
1485 printf("cpu 0x%x: ", smp_processor_id());
1486 #endif /* CONFIG_SMP */
1489 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1491 xmon_print_symbol(fp->nip, ": ", "\n");
1493 printf(" lr: ", fp->link);
1494 xmon_print_symbol(fp->link, ": ", "\n");
1496 printf(" sp: %lx\n", fp->gpr[1]);
1497 printf(" msr: %lx\n", fp->msr);
1499 if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
1500 printf(" dar: %lx\n", fp->dar);
1502 printf(" dsisr: %lx\n", fp->dsisr);
1505 printf(" current = 0x%lx\n", current);
1507 printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
1508 local_paca, local_paca->soft_enabled, local_paca->irq_happened);
1511 printf(" pid = %ld, comm = %s\n",
1512 current->pid, current->comm);
1519 static void prregs(struct pt_regs *fp)
1523 struct pt_regs regs;
1525 if (scanhex(&base)) {
1526 if (setjmp(bus_error_jmp) == 0) {
1527 catch_memory_errors = 1;
1529 regs = *(struct pt_regs *)base;
1533 catch_memory_errors = 0;
1534 printf("*** Error reading registers from "REG"\n",
1538 catch_memory_errors = 0;
1543 if (FULL_REGS(fp)) {
1544 for (n = 0; n < 16; ++n)
1545 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1546 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1548 for (n = 0; n < 7; ++n)
1549 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1550 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1553 for (n = 0; n < 32; ++n) {
1554 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1555 (n & 3) == 3? "\n": " ");
1556 if (n == 12 && !FULL_REGS(fp)) {
1563 xmon_print_symbol(fp->nip, " ", "\n");
1564 if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1566 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1569 xmon_print_symbol(fp->link, " ", "\n");
1570 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1571 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1572 fp->ctr, fp->xer, fp->trap);
1574 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1575 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1578 static void cacheflush(void)
1581 unsigned long nflush;
1586 scanhex((void *)&adrs);
1591 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1592 if (setjmp(bus_error_jmp) == 0) {
1593 catch_memory_errors = 1;
1597 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1598 cflush((void *) adrs);
1600 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1601 cinval((void *) adrs);
1604 /* wait a little while to see if we get a machine check */
1607 catch_memory_errors = 0;
1610 static unsigned long
1613 unsigned int instrs[2];
1614 unsigned long (*code)(void);
1615 unsigned long ret = -1UL;
1617 unsigned long opd[3];
1619 opd[0] = (unsigned long)instrs;
1622 code = (unsigned long (*)(void)) opd;
1624 code = (unsigned long (*)(void)) instrs;
1627 /* mfspr r3,n; blr */
1628 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1629 instrs[1] = 0x4e800020;
1631 store_inst(instrs+1);
1633 if (setjmp(bus_error_jmp) == 0) {
1634 catch_memory_errors = 1;
1640 /* wait a little while to see if we get a machine check */
1649 write_spr(int n, unsigned long val)
1651 unsigned int instrs[2];
1652 unsigned long (*code)(unsigned long);
1654 unsigned long opd[3];
1656 opd[0] = (unsigned long)instrs;
1659 code = (unsigned long (*)(unsigned long)) opd;
1661 code = (unsigned long (*)(unsigned long)) instrs;
1664 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1665 instrs[1] = 0x4e800020;
1667 store_inst(instrs+1);
1669 if (setjmp(bus_error_jmp) == 0) {
1670 catch_memory_errors = 1;
1676 /* wait a little while to see if we get a machine check */
1682 static unsigned long regno;
1683 extern char exc_prolog;
1684 extern char dec_exc;
1686 static void super_regs(void)
1693 unsigned long sp, toc;
1694 asm("mr %0,1" : "=r" (sp) :);
1695 asm("mr %0,2" : "=r" (toc) :);
1697 printf("msr = "REG" sprg0= "REG"\n",
1698 mfmsr(), mfspr(SPRN_SPRG0));
1699 printf("pvr = "REG" sprg1= "REG"\n",
1700 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1701 printf("dec = "REG" sprg2= "REG"\n",
1702 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1703 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1704 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1712 val = read_spr(regno);
1714 write_spr(regno, val);
1717 printf("spr %lx = %lx\n", regno, read_spr(regno));
1724 * Stuff for reading and writing memory safely
1727 mread(unsigned long adrs, void *buf, int size)
1733 if (setjmp(bus_error_jmp) == 0) {
1734 catch_memory_errors = 1;
1740 *(u16 *)q = *(u16 *)p;
1743 *(u32 *)q = *(u32 *)p;
1746 *(u64 *)q = *(u64 *)p;
1749 for( ; n < size; ++n) {
1755 /* wait a little while to see if we get a machine check */
1759 catch_memory_errors = 0;
1764 mwrite(unsigned long adrs, void *buf, int size)
1770 if (setjmp(bus_error_jmp) == 0) {
1771 catch_memory_errors = 1;
1777 *(u16 *)p = *(u16 *)q;
1780 *(u32 *)p = *(u32 *)q;
1783 *(u64 *)p = *(u64 *)q;
1786 for ( ; n < size; ++n) {
1792 /* wait a little while to see if we get a machine check */
1796 printf("*** Error writing address "REG"\n", adrs + n);
1798 catch_memory_errors = 0;
1802 static int fault_type;
1803 static int fault_except;
1804 static char *fault_chars[] = { "--", "**", "##" };
1806 static int handle_fault(struct pt_regs *regs)
1808 fault_except = TRAP(regs);
1809 switch (TRAP(regs)) {
1821 longjmp(bus_error_jmp, 1);
1826 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1829 byterev(unsigned char *val, int size)
1835 SWAP(val[0], val[1], t);
1838 SWAP(val[0], val[3], t);
1839 SWAP(val[1], val[2], t);
1841 case 8: /* is there really any use for this? */
1842 SWAP(val[0], val[7], t);
1843 SWAP(val[1], val[6], t);
1844 SWAP(val[2], val[5], t);
1845 SWAP(val[3], val[4], t);
1853 static char *memex_help_string =
1854 "Memory examine command usage:\n"
1855 "m [addr] [flags] examine/change memory\n"
1856 " addr is optional. will start where left off.\n"
1857 " flags may include chars from this set:\n"
1858 " b modify by bytes (default)\n"
1859 " w modify by words (2 byte)\n"
1860 " l modify by longs (4 byte)\n"
1861 " d modify by doubleword (8 byte)\n"
1862 " r toggle reverse byte order mode\n"
1863 " n do not read memory (for i/o spaces)\n"
1864 " . ok to read (default)\n"
1865 "NOTE: flags are saved as defaults\n"
1868 static char *memex_subcmd_help_string =
1869 "Memory examine subcommands:\n"
1870 " hexval write this val to current location\n"
1871 " 'string' write chars from string to this location\n"
1872 " ' increment address\n"
1873 " ^ decrement address\n"
1874 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1875 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1876 " ` clear no-read flag\n"
1877 " ; stay at this addr\n"
1878 " v change to byte mode\n"
1879 " w change to word (2 byte) mode\n"
1880 " l change to long (4 byte) mode\n"
1881 " u change to doubleword (8 byte) mode\n"
1882 " m addr change current addr\n"
1883 " n toggle no-read flag\n"
1884 " r toggle byte reverse flag\n"
1885 " < count back up count bytes\n"
1886 " > count skip forward count bytes\n"
1887 " x exit this mode\n"
1893 int cmd, inc, i, nslash;
1895 unsigned char val[16];
1897 scanhex((void *)&adrs);
1900 printf(memex_help_string);
1906 while ((cmd = skipbl()) != '\n') {
1908 case 'b': size = 1; break;
1909 case 'w': size = 2; break;
1910 case 'l': size = 4; break;
1911 case 'd': size = 8; break;
1912 case 'r': brev = !brev; break;
1913 case 'n': mnoread = 1; break;
1914 case '.': mnoread = 0; break;
1923 n = mread(adrs, val, size);
1924 printf(REG"%c", adrs, brev? 'r': ' ');
1929 for (i = 0; i < n; ++i)
1930 printf("%.2x", val[i]);
1931 for (; i < size; ++i)
1932 printf("%s", fault_chars[fault_type]);
1939 for (i = 0; i < size; ++i)
1940 val[i] = n >> (i * 8);
1943 mwrite(adrs, val, size);
1956 else if( n == '\'' )
1958 for (i = 0; i < size; ++i)
1959 val[i] = n >> (i * 8);
1962 mwrite(adrs, val, size);
1999 adrs -= 1 << nslash;
2003 adrs += 1 << nslash;
2007 adrs += 1 << -nslash;
2011 adrs -= 1 << -nslash;
2014 scanhex((void *)&adrs);
2033 printf(memex_subcmd_help_string);
2048 case 'n': c = '\n'; break;
2049 case 'r': c = '\r'; break;
2050 case 'b': c = '\b'; break;
2051 case 't': c = '\t'; break;
2056 static void xmon_rawdump (unsigned long adrs, long ndump)
2059 unsigned char temp[16];
2061 for (n = ndump; n > 0;) {
2063 nr = mread(adrs, temp, r);
2065 for (m = 0; m < r; ++m) {
2067 printf("%.2x", temp[m]);
2069 printf("%s", fault_chars[fault_type]);
2079 static void dump_one_paca(int cpu)
2081 struct paca_struct *p;
2083 if (setjmp(bus_error_jmp) != 0) {
2084 printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
2088 catch_memory_errors = 1;
2093 printf("paca for cpu 0x%x @ %p:\n", cpu, p);
2095 printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
2096 printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
2097 printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
2099 #define DUMP(paca, name, format) \
2100 printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
2101 offsetof(struct paca_struct, name));
2103 DUMP(p, lock_token, "x");
2104 DUMP(p, paca_index, "x");
2105 DUMP(p, kernel_toc, "lx");
2106 DUMP(p, kernelbase, "lx");
2107 DUMP(p, kernel_msr, "lx");
2108 DUMP(p, emergency_sp, "p");
2109 #ifdef CONFIG_PPC_BOOK3S_64
2110 DUMP(p, mc_emergency_sp, "p");
2111 DUMP(p, in_mce, "x");
2113 DUMP(p, data_offset, "lx");
2114 DUMP(p, hw_cpu_id, "x");
2115 DUMP(p, cpu_start, "x");
2116 DUMP(p, kexec_state, "x");
2117 DUMP(p, __current, "p");
2118 DUMP(p, kstack, "lx");
2119 DUMP(p, stab_rr, "lx");
2120 DUMP(p, saved_r1, "lx");
2121 DUMP(p, trap_save, "x");
2122 DUMP(p, soft_enabled, "x");
2123 DUMP(p, irq_happened, "x");
2124 DUMP(p, io_sync, "x");
2125 DUMP(p, irq_work_pending, "x");
2126 DUMP(p, nap_state_lost, "x");
2130 catch_memory_errors = 0;
2134 static void dump_all_pacas(void)
2138 if (num_possible_cpus() == 0) {
2139 printf("No possible cpus, use 'dp #' to dump individual cpus\n");
2143 for_each_possible_cpu(cpu)
2147 static void dump_pacas(void)
2158 termch = c; /* Put c back, it wasn't 'a' */
2163 dump_one_paca(xmon_owner);
2167 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
2168 || ('a' <= (c) && (c) <= 'f') \
2169 || ('A' <= (c) && (c) <= 'F'))
2184 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2186 scanhex((void *)&adrs);
2193 else if (nidump > MAX_DUMP)
2195 adrs += ppc_inst_dump(adrs, nidump, 1);
2197 } else if (c == 'l') {
2199 } else if (c == 'r') {
2203 xmon_rawdump(adrs, ndump);
2210 else if (ndump > MAX_DUMP)
2212 prdump(adrs, ndump);
2219 prdump(unsigned long adrs, long ndump)
2221 long n, m, c, r, nr;
2222 unsigned char temp[16];
2224 for (n = ndump; n > 0;) {
2228 nr = mread(adrs, temp, r);
2230 for (m = 0; m < r; ++m) {
2231 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2234 printf("%.2x", temp[m]);
2236 printf("%s", fault_chars[fault_type]);
2238 for (; m < 16; ++m) {
2239 if ((m & (sizeof(long) - 1)) == 0)
2244 for (m = 0; m < r; ++m) {
2247 putchar(' ' <= c && c <= '~'? c: '.');
2260 typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2263 generic_inst_dump(unsigned long adr, long count, int praddr,
2264 instruction_dump_func dump_func)
2267 unsigned long first_adr;
2268 unsigned long inst, last_inst = 0;
2269 unsigned char val[4];
2272 for (first_adr = adr; count > 0; --count, adr += 4) {
2273 nr = mread(adr, val, 4);
2276 const char *x = fault_chars[fault_type];
2277 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2281 inst = GETWORD(val);
2282 if (adr > first_adr && inst == last_inst) {
2292 printf(REG" %.8x", adr, inst);
2294 dump_func(inst, adr);
2297 return adr - first_adr;
2301 ppc_inst_dump(unsigned long adr, long count, int praddr)
2303 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2307 print_address(unsigned long addr)
2309 xmon_print_symbol(addr, "\t# ", "");
2315 struct kmsg_dumper dumper = { .active = 1 };
2316 unsigned char buf[128];
2319 if (setjmp(bus_error_jmp) != 0) {
2320 printf("Error dumping printk buffer!\n");
2324 catch_memory_errors = 1;
2327 kmsg_dump_rewind_nolock(&dumper);
2328 while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
2334 /* wait a little while to see if we get a machine check */
2336 catch_memory_errors = 0;
2340 * Memory operations - move, set, print differences
2342 static unsigned long mdest; /* destination address */
2343 static unsigned long msrc; /* source address */
2344 static unsigned long mval; /* byte value to set memory to */
2345 static unsigned long mcount; /* # bytes to affect */
2346 static unsigned long mdiffs; /* max # differences to print */
2351 scanhex((void *)&mdest);
2352 if( termch != '\n' )
2354 scanhex((void *)(cmd == 's'? &mval: &msrc));
2355 if( termch != '\n' )
2357 scanhex((void *)&mcount);
2360 memmove((void *)mdest, (void *)msrc, mcount);
2363 memset((void *)mdest, mval, mcount);
2366 if( termch != '\n' )
2368 scanhex((void *)&mdiffs);
2369 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2375 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2380 for( n = nb; n > 0; --n )
2381 if( *p1++ != *p2++ )
2382 if( ++prt <= maxpr )
2383 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2384 p1[-1], p2 - 1, p2[-1]);
2386 printf("Total of %d differences\n", prt);
2389 static unsigned mend;
2390 static unsigned mask;
2396 unsigned char val[4];
2399 scanhex((void *)&mdest);
2400 if (termch != '\n') {
2402 scanhex((void *)&mend);
2403 if (termch != '\n') {
2405 scanhex((void *)&mval);
2407 if (termch != '\n') termch = 0;
2408 scanhex((void *)&mask);
2412 for (a = mdest; a < mend; a += 4) {
2413 if (mread(a, val, 4) == 4
2414 && ((GETWORD(val) ^ mval) & mask) == 0) {
2415 printf("%.16x: %.16x\n", a, GETWORD(val));
2422 static unsigned long mskip = 0x1000;
2423 static unsigned long mlim = 0xffffffff;
2433 if (termch != '\n') termch = 0;
2435 if (termch != '\n') termch = 0;
2438 for (a = mdest; a < mlim; a += mskip) {
2439 ok = mread(a, &v, 1);
2441 printf("%.8x .. ", a);
2442 } else if (!ok && ook)
2443 printf("%.8x\n", a - mskip);
2449 printf("%.8x\n", a - mskip);
2452 static void proccall(void)
2454 unsigned long args[8];
2457 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2458 unsigned long, unsigned long, unsigned long,
2459 unsigned long, unsigned long, unsigned long);
2462 if (!scanhex(&adrs))
2466 for (i = 0; i < 8; ++i)
2468 for (i = 0; i < 8; ++i) {
2469 if (!scanhex(&args[i]) || termch == '\n')
2473 func = (callfunc_t) adrs;
2475 if (setjmp(bus_error_jmp) == 0) {
2476 catch_memory_errors = 1;
2478 ret = func(args[0], args[1], args[2], args[3],
2479 args[4], args[5], args[6], args[7]);
2481 printf("return value is 0x%lx\n", ret);
2483 printf("*** %x exception occurred\n", fault_except);
2485 catch_memory_errors = 0;
2488 /* Input scanning routines */
2499 while( c == ' ' || c == '\t' )
2505 static char *regnames[N_PTREGS] = {
2506 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2507 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2508 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2509 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2510 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2516 "trap", "dar", "dsisr", "res"
2520 scanhex(unsigned long *vp)
2527 /* parse register name */
2531 for (i = 0; i < sizeof(regname) - 1; ++i) {
2540 for (i = 0; i < N_PTREGS; ++i) {
2541 if (strcmp(regnames[i], regname) == 0) {
2542 if (xmon_regs == NULL) {
2543 printf("regs not available\n");
2546 *vp = ((unsigned long *)xmon_regs)[i];
2550 printf("invalid register name '%%%s'\n", regname);
2554 /* skip leading "0x" if any */
2568 } else if (c == '$') {
2570 for (i=0; i<63; i++) {
2580 if (setjmp(bus_error_jmp) == 0) {
2581 catch_memory_errors = 1;
2583 *vp = kallsyms_lookup_name(tmpstr);
2586 catch_memory_errors = 0;
2588 printf("unknown symbol '%s'\n", tmpstr);
2621 static int hexdigit(int c)
2623 if( '0' <= c && c <= '9' )
2625 if( 'A' <= c && c <= 'F' )
2626 return c - ('A' - 10);
2627 if( 'a' <= c && c <= 'f' )
2628 return c - ('a' - 10);
2633 getstring(char *s, int size)
2644 } while( c != ' ' && c != '\t' && c != '\n' );
2649 static char line[256];
2650 static char *lineptr;
2661 if (lineptr == NULL || *lineptr == 0) {
2662 if (xmon_gets(line, sizeof(line)) == NULL) {
2672 take_input(char *str)
2681 int type = inchar();
2683 static char tmp[64];
2688 xmon_print_symbol(addr, ": ", "\n");
2693 if (setjmp(bus_error_jmp) == 0) {
2694 catch_memory_errors = 1;
2696 addr = kallsyms_lookup_name(tmp);
2698 printf("%s: %lx\n", tmp, addr);
2700 printf("Symbol '%s' not found.\n", tmp);
2703 catch_memory_errors = 0;
2710 /* Print an address in numeric and symbolic form (if possible) */
2711 static void xmon_print_symbol(unsigned long address, const char *mid,
2715 const char *name = NULL;
2716 unsigned long offset, size;
2718 printf(REG, address);
2719 if (setjmp(bus_error_jmp) == 0) {
2720 catch_memory_errors = 1;
2722 name = kallsyms_lookup(address, &size, &offset, &modname,
2725 /* wait a little while to see if we get a machine check */
2729 catch_memory_errors = 0;
2732 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2734 printf(" [%s]", modname);
2736 printf("%s", after);
2739 #ifdef CONFIG_PPC_BOOK3S_64
2740 void dump_segments(void)
2743 unsigned long esid,vsid,valid;
2746 printf("SLB contents of cpu 0x%x\n", smp_processor_id());
2748 for (i = 0; i < mmu_slb_size; i++) {
2749 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
2750 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
2751 valid = (esid & SLB_ESID_V);
2752 if (valid | esid | vsid) {
2753 printf("%02d %016lx %016lx", i, esid, vsid);
2755 llp = vsid & SLB_VSID_LLP;
2756 if (vsid & SLB_VSID_B_1T) {
2757 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
2759 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2762 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
2764 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2774 #ifdef CONFIG_PPC_STD_MMU_32
2775 void dump_segments(void)
2780 for (i = 0; i < 16; ++i)
2781 printf(" %x", mfsrin(i));
2787 static void dump_tlb_44x(void)
2791 for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2792 unsigned long w0,w1,w2;
2793 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
2794 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
2795 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
2796 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2797 if (w0 & PPC44x_TLB_VALID) {
2798 printf("V %08x -> %01x%08x %c%c%c%c%c",
2799 w0 & PPC44x_TLB_EPN_MASK,
2800 w1 & PPC44x_TLB_ERPN_MASK,
2801 w1 & PPC44x_TLB_RPN_MASK,
2802 (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2803 (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2804 (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2805 (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2806 (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2811 #endif /* CONFIG_44x */
2813 #ifdef CONFIG_PPC_BOOK3E
2814 static void dump_tlb_book3e(void)
2816 u32 mmucfg, pidmask, lpidmask;
2818 int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
2820 static const char *pgsz_names[] = {
2855 /* Gather some infos about the MMU */
2856 mmucfg = mfspr(SPRN_MMUCFG);
2857 mmu_version = (mmucfg & 3) + 1;
2858 ntlbs = ((mmucfg >> 2) & 3) + 1;
2859 pidsz = ((mmucfg >> 6) & 0x1f) + 1;
2860 lpidsz = (mmucfg >> 24) & 0xf;
2861 rasz = (mmucfg >> 16) & 0x7f;
2862 if ((mmu_version > 1) && (mmucfg & 0x10000))
2864 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
2865 mmu_version, ntlbs, pidsz, lpidsz, rasz);
2866 pidmask = (1ul << pidsz) - 1;
2867 lpidmask = (1ul << lpidsz) - 1;
2868 ramask = (1ull << rasz) - 1;
2870 for (tlb = 0; tlb < ntlbs; tlb++) {
2872 int nent, assoc, new_cc = 1;
2873 printf("TLB %d:\n------\n", tlb);
2876 tlbcfg = mfspr(SPRN_TLB0CFG);
2879 tlbcfg = mfspr(SPRN_TLB1CFG);
2882 tlbcfg = mfspr(SPRN_TLB2CFG);
2885 tlbcfg = mfspr(SPRN_TLB3CFG);
2888 printf("Unsupported TLB number !\n");
2891 nent = tlbcfg & 0xfff;
2892 assoc = (tlbcfg >> 24) & 0xff;
2893 for (i = 0; i < nent; i++) {
2894 u32 mas0 = MAS0_TLBSEL(tlb);
2895 u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
2898 int esel = i, cc = i;
2906 mas0 |= MAS0_ESEL(esel);
2907 mtspr(SPRN_MAS0, mas0);
2908 mtspr(SPRN_MAS1, mas1);
2909 mtspr(SPRN_MAS2, mas2);
2910 asm volatile("tlbre 0,0,0" : : : "memory");
2911 mas1 = mfspr(SPRN_MAS1);
2912 mas2 = mfspr(SPRN_MAS2);
2913 mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
2914 if (assoc && (i % assoc) == 0)
2916 if (!(mas1 & MAS1_VALID))
2919 printf("%04x- ", i);
2921 printf("%04x-%c", cc, 'A' + esel);
2923 printf(" |%c", 'A' + esel);
2925 printf(" %016llx %04x %s %c%c AS%c",
2927 (mas1 >> 16) & 0x3fff,
2928 pgsz_names[(mas1 >> 7) & 0x1f],
2929 mas1 & MAS1_IND ? 'I' : ' ',
2930 mas1 & MAS1_IPROT ? 'P' : ' ',
2931 mas1 & MAS1_TS ? '1' : '0');
2932 printf(" %c%c%c%c%c%c%c",
2933 mas2 & MAS2_X0 ? 'a' : ' ',
2934 mas2 & MAS2_X1 ? 'v' : ' ',
2935 mas2 & MAS2_W ? 'w' : ' ',
2936 mas2 & MAS2_I ? 'i' : ' ',
2937 mas2 & MAS2_M ? 'm' : ' ',
2938 mas2 & MAS2_G ? 'g' : ' ',
2939 mas2 & MAS2_E ? 'e' : ' ');
2940 printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
2941 if (mas1 & MAS1_IND)
2943 pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
2945 printf(" U%c%c%c S%c%c%c\n",
2946 mas7_mas3 & MAS3_UX ? 'x' : ' ',
2947 mas7_mas3 & MAS3_UW ? 'w' : ' ',
2948 mas7_mas3 & MAS3_UR ? 'r' : ' ',
2949 mas7_mas3 & MAS3_SX ? 'x' : ' ',
2950 mas7_mas3 & MAS3_SW ? 'w' : ' ',
2951 mas7_mas3 & MAS3_SR ? 'r' : ' ');
2955 #endif /* CONFIG_PPC_BOOK3E */
2957 static void xmon_init(int enable)
2961 __debugger_ipi = xmon_ipi;
2962 __debugger_bpt = xmon_bpt;
2963 __debugger_sstep = xmon_sstep;
2964 __debugger_iabr_match = xmon_iabr_match;
2965 __debugger_break_match = xmon_break_match;
2966 __debugger_fault_handler = xmon_fault_handler;
2969 __debugger_ipi = NULL;
2970 __debugger_bpt = NULL;
2971 __debugger_sstep = NULL;
2972 __debugger_iabr_match = NULL;
2973 __debugger_break_match = NULL;
2974 __debugger_fault_handler = NULL;
2978 #ifdef CONFIG_MAGIC_SYSRQ
2979 static void sysrq_handle_xmon(int key)
2981 /* ensure xmon is enabled */
2983 debugger(get_irq_regs());
2986 static struct sysrq_key_op sysrq_xmon_op = {
2987 .handler = sysrq_handle_xmon,
2988 .help_msg = "xmon(x)",
2989 .action_msg = "Entering xmon",
2992 static int __init setup_xmon_sysrq(void)
2994 register_sysrq_key('x', &sysrq_xmon_op);
2997 __initcall(setup_xmon_sysrq);
2998 #endif /* CONFIG_MAGIC_SYSRQ */
3000 static int __initdata xmon_early, xmon_off;
3002 static int __init early_parse_xmon(char *p)
3004 if (!p || strncmp(p, "early", 5) == 0) {
3005 /* just "xmon" is equivalent to "xmon=early" */
3008 } else if (strncmp(p, "on", 2) == 0)
3010 else if (strncmp(p, "off", 3) == 0)
3012 else if (strncmp(p, "nobt", 4) == 0)
3013 xmon_no_auto_backtrace = 1;
3019 early_param("xmon", early_parse_xmon);
3021 void __init xmon_setup(void)
3023 #ifdef CONFIG_XMON_DEFAULT
3031 #ifdef CONFIG_SPU_BASE
3035 u64 saved_mfc_sr1_RW;
3036 u32 saved_spu_runcntl_RW;
3037 unsigned long dump_addr;
3041 #define XMON_NUM_SPUS 16 /* Enough for current hardware */
3043 static struct spu_info spu_info[XMON_NUM_SPUS];
3045 void xmon_register_spus(struct list_head *list)
3049 list_for_each_entry(spu, list, full_list) {
3050 if (spu->number >= XMON_NUM_SPUS) {
3055 spu_info[spu->number].spu = spu;
3056 spu_info[spu->number].stopped_ok = 0;
3057 spu_info[spu->number].dump_addr = (unsigned long)
3058 spu_info[spu->number].spu->local_store;
3062 static void stop_spus(void)
3068 for (i = 0; i < XMON_NUM_SPUS; i++) {
3069 if (!spu_info[i].spu)
3072 if (setjmp(bus_error_jmp) == 0) {
3073 catch_memory_errors = 1;
3076 spu = spu_info[i].spu;
3078 spu_info[i].saved_spu_runcntl_RW =
3079 in_be32(&spu->problem->spu_runcntl_RW);
3081 tmp = spu_mfc_sr1_get(spu);
3082 spu_info[i].saved_mfc_sr1_RW = tmp;
3084 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
3085 spu_mfc_sr1_set(spu, tmp);
3090 spu_info[i].stopped_ok = 1;
3092 printf("Stopped spu %.2d (was %s)\n", i,
3093 spu_info[i].saved_spu_runcntl_RW ?
3094 "running" : "stopped");
3096 catch_memory_errors = 0;
3097 printf("*** Error stopping spu %.2d\n", i);
3099 catch_memory_errors = 0;
3103 static void restart_spus(void)
3108 for (i = 0; i < XMON_NUM_SPUS; i++) {
3109 if (!spu_info[i].spu)
3112 if (!spu_info[i].stopped_ok) {
3113 printf("*** Error, spu %d was not successfully stopped"
3114 ", not restarting\n", i);
3118 if (setjmp(bus_error_jmp) == 0) {
3119 catch_memory_errors = 1;
3122 spu = spu_info[i].spu;
3123 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3124 out_be32(&spu->problem->spu_runcntl_RW,
3125 spu_info[i].saved_spu_runcntl_RW);
3130 printf("Restarted spu %.2d\n", i);
3132 catch_memory_errors = 0;
3133 printf("*** Error restarting spu %.2d\n", i);
3135 catch_memory_errors = 0;
3139 #define DUMP_WIDTH 23
3140 #define DUMP_VALUE(format, field, value) \
3142 if (setjmp(bus_error_jmp) == 0) { \
3143 catch_memory_errors = 1; \
3145 printf(" %-*s = "format"\n", DUMP_WIDTH, \
3150 catch_memory_errors = 0; \
3151 printf(" %-*s = *** Error reading field.\n", \
3152 DUMP_WIDTH, #field); \
3154 catch_memory_errors = 0; \
3157 #define DUMP_FIELD(obj, format, field) \
3158 DUMP_VALUE(format, field, obj->field)
3160 static void dump_spu_fields(struct spu *spu)
3162 printf("Dumping spu fields at address %p:\n", spu);
3164 DUMP_FIELD(spu, "0x%x", number);
3165 DUMP_FIELD(spu, "%s", name);
3166 DUMP_FIELD(spu, "0x%lx", local_store_phys);
3167 DUMP_FIELD(spu, "0x%p", local_store);
3168 DUMP_FIELD(spu, "0x%lx", ls_size);
3169 DUMP_FIELD(spu, "0x%x", node);
3170 DUMP_FIELD(spu, "0x%lx", flags);
3171 DUMP_FIELD(spu, "%d", class_0_pending);
3172 DUMP_FIELD(spu, "0x%lx", class_0_dar);
3173 DUMP_FIELD(spu, "0x%lx", class_1_dar);
3174 DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
3175 DUMP_FIELD(spu, "0x%lx", irqs[0]);
3176 DUMP_FIELD(spu, "0x%lx", irqs[1]);
3177 DUMP_FIELD(spu, "0x%lx", irqs[2]);
3178 DUMP_FIELD(spu, "0x%x", slb_replace);
3179 DUMP_FIELD(spu, "%d", pid);
3180 DUMP_FIELD(spu, "0x%p", mm);
3181 DUMP_FIELD(spu, "0x%p", ctx);
3182 DUMP_FIELD(spu, "0x%p", rq);
3183 DUMP_FIELD(spu, "0x%p", timestamp);
3184 DUMP_FIELD(spu, "0x%lx", problem_phys);
3185 DUMP_FIELD(spu, "0x%p", problem);
3186 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3187 in_be32(&spu->problem->spu_runcntl_RW));
3188 DUMP_VALUE("0x%x", problem->spu_status_R,
3189 in_be32(&spu->problem->spu_status_R));
3190 DUMP_VALUE("0x%x", problem->spu_npc_RW,
3191 in_be32(&spu->problem->spu_npc_RW));
3192 DUMP_FIELD(spu, "0x%p", priv2);
3193 DUMP_FIELD(spu, "0x%p", pdata);
3197 spu_inst_dump(unsigned long adr, long count, int praddr)
3199 return generic_inst_dump(adr, count, praddr, print_insn_spu);
3202 static void dump_spu_ls(unsigned long num, int subcmd)
3204 unsigned long offset, addr, ls_addr;
3206 if (setjmp(bus_error_jmp) == 0) {
3207 catch_memory_errors = 1;
3209 ls_addr = (unsigned long)spu_info[num].spu->local_store;
3213 catch_memory_errors = 0;
3214 printf("*** Error: accessing spu info for spu %d\n", num);
3217 catch_memory_errors = 0;
3219 if (scanhex(&offset))
3220 addr = ls_addr + offset;
3222 addr = spu_info[num].dump_addr;
3224 if (addr >= ls_addr + LS_SIZE) {
3225 printf("*** Error: address outside of local store\n");
3231 addr += spu_inst_dump(addr, 16, 1);
3241 spu_info[num].dump_addr = addr;
3244 static int do_spu_cmd(void)
3246 static unsigned long num = 0;
3247 int cmd, subcmd = 0;
3259 if (isxdigit(subcmd) || subcmd == '\n')
3263 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
3264 printf("*** Error: invalid spu number\n");
3270 dump_spu_fields(spu_info[num].spu);
3273 dump_spu_ls(num, subcmd);
3284 #else /* ! CONFIG_SPU_BASE */
3285 static int do_spu_cmd(void)