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