[PATCH] powerpc: xmon namespace cleanups
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / powerpc / xmon / xmon.c
blob7d02fa2a899029d3df4023ef804f4b14588b539c
1 /*
2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996-2005 Paul Mackerras.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
11 #include <linux/config.h>
12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/smp.h>
15 #include <linux/mm.h>
16 #include <linux/reboot.h>
17 #include <linux/delay.h>
18 #include <linux/kallsyms.h>
19 #include <linux/cpumask.h>
20 #include <linux/module.h>
21 #include <linux/sysrq.h>
22 #include <linux/interrupt.h>
24 #include <asm/ptrace.h>
25 #include <asm/string.h>
26 #include <asm/prom.h>
27 #include <asm/machdep.h>
28 #include <asm/xmon.h>
29 #ifdef CONFIG_PMAC_BACKLIGHT
30 #include <asm/backlight.h>
31 #endif
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/bug.h>
41 #ifdef CONFIG_PPC64
42 #include <asm/hvcall.h>
43 #include <asm/paca.h>
44 #endif
46 #include "nonstdio.h"
48 #define scanhex xmon_scanhex
49 #define skipbl xmon_skipbl
51 #ifdef CONFIG_SMP
52 cpumask_t cpus_in_xmon = CPU_MASK_NONE;
53 static unsigned long xmon_taken = 1;
54 static int xmon_owner;
55 static int xmon_gate;
56 #endif /* CONFIG_SMP */
58 static unsigned long in_xmon = 0;
60 static unsigned long adrs;
61 static int size = 1;
62 #define MAX_DUMP (128 * 1024)
63 static unsigned long ndump = 64;
64 static unsigned long nidump = 16;
65 static unsigned long ncsum = 4096;
66 static int termch;
67 static char tmpstr[128];
69 #define JMP_BUF_LEN 23
70 static long bus_error_jmp[JMP_BUF_LEN];
71 static int catch_memory_errors;
72 static long *xmon_fault_jmp[NR_CPUS];
73 #define setjmp xmon_setjmp
74 #define longjmp xmon_longjmp
76 /* Breakpoint stuff */
77 struct bpt {
78 unsigned long address;
79 unsigned int instr[2];
80 atomic_t ref_count;
81 int enabled;
82 unsigned long pad;
85 /* Bits in bpt.enabled */
86 #define BP_IABR_TE 1 /* IABR translation enabled */
87 #define BP_IABR 2
88 #define BP_TRAP 8
89 #define BP_DABR 0x10
91 #define NBPTS 256
92 static struct bpt bpts[NBPTS];
93 static struct bpt dabr;
94 static struct bpt *iabr;
95 static unsigned bpinstr = 0x7fe00008; /* trap */
97 #define BP_NUM(bp) ((bp) - bpts + 1)
99 /* Prototypes */
100 static int cmds(struct pt_regs *);
101 static int mread(unsigned long, void *, int);
102 static int mwrite(unsigned long, void *, int);
103 static int handle_fault(struct pt_regs *);
104 static void byterev(unsigned char *, int);
105 static void memex(void);
106 static int bsesc(void);
107 static void dump(void);
108 static void prdump(unsigned long, long);
109 static int ppc_inst_dump(unsigned long, long, int);
110 void print_address(unsigned long);
111 static void backtrace(struct pt_regs *);
112 static void excprint(struct pt_regs *);
113 static void prregs(struct pt_regs *);
114 static void memops(int);
115 static void memlocate(void);
116 static void memzcan(void);
117 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
118 int skipbl(void);
119 int scanhex(unsigned long *valp);
120 static void scannl(void);
121 static int hexdigit(int);
122 void getstring(char *, int);
123 static void flush_input(void);
124 static int inchar(void);
125 static void take_input(char *);
126 static unsigned long read_spr(int);
127 static void write_spr(int, unsigned long);
128 static void super_regs(void);
129 static void remove_bpts(void);
130 static void insert_bpts(void);
131 static void remove_cpu_bpts(void);
132 static void insert_cpu_bpts(void);
133 static struct bpt *at_breakpoint(unsigned long pc);
134 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
135 static int do_step(struct pt_regs *);
136 static void bpt_cmds(void);
137 static void cacheflush(void);
138 static int cpu_cmd(void);
139 static void csum(void);
140 static void bootcmds(void);
141 static void proccall(void);
142 void dump_segments(void);
143 static void symbol_lookup(void);
144 static void xmon_print_symbol(unsigned long address, const char *mid,
145 const char *after);
146 static const char *getvecname(unsigned long vec);
148 extern int print_insn_powerpc(unsigned long, unsigned long, int);
150 extern void xmon_enter(void);
151 extern void xmon_leave(void);
153 extern long setjmp(long *);
154 extern void longjmp(long *, long);
155 extern void xmon_save_regs(struct pt_regs *);
157 #ifdef CONFIG_PPC64
158 #define REG "%.16lx"
159 #define REGS_PER_LINE 4
160 #define LAST_VOLATILE 13
161 #else
162 #define REG "%.8lx"
163 #define REGS_PER_LINE 8
164 #define LAST_VOLATILE 12
165 #endif
167 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
169 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
170 || ('a' <= (c) && (c) <= 'f') \
171 || ('A' <= (c) && (c) <= 'F'))
172 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
173 || ('a' <= (c) && (c) <= 'z') \
174 || ('A' <= (c) && (c) <= 'Z'))
175 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
177 static char *help_string = "\
178 Commands:\n\
179 b show breakpoints\n\
180 bd set data breakpoint\n\
181 bi set instruction breakpoint\n\
182 bc clear breakpoint\n"
183 #ifdef CONFIG_SMP
185 c print cpus stopped in xmon\n\
186 c# try to switch to cpu number h (in hex)\n"
187 #endif
189 C checksum\n\
190 d dump bytes\n\
191 di dump instructions\n\
192 df dump float values\n\
193 dd dump double values\n\
194 e print exception information\n\
195 f flush cache\n\
196 la lookup symbol+offset of specified address\n\
197 ls lookup address of specified symbol\n\
198 m examine/change memory\n\
199 mm move a block of memory\n\
200 ms set a block of memory\n\
201 md compare two blocks of memory\n\
202 ml locate a block of memory\n\
203 mz zero a block of memory\n\
204 mi show information about memory allocation\n\
205 p call a procedure\n\
206 r print registers\n\
207 s single step\n\
208 S print special registers\n\
209 t print backtrace\n\
210 x exit monitor and recover\n\
211 X exit monitor and dont recover\n"
212 #ifdef CONFIG_PPC64
213 " u dump segment table or SLB\n"
214 #endif
215 #ifdef CONFIG_PPC_STD_MMU_32
216 " u dump segment registers\n"
217 #endif
218 " ? help\n"
219 " zr reboot\n\
220 zh halt\n"
223 static struct pt_regs *xmon_regs;
225 static inline void sync(void)
227 asm volatile("sync; isync");
230 static inline void store_inst(void *p)
232 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
235 static inline void cflush(void *p)
237 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
240 static inline void cinval(void *p)
242 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
246 * Disable surveillance (the service processor watchdog function)
247 * while we are in xmon.
248 * XXX we should re-enable it when we leave. :)
250 #define SURVEILLANCE_TOKEN 9000
252 static inline void disable_surveillance(void)
254 #ifdef CONFIG_PPC_PSERIES
255 /* Since this can't be a module, args should end up below 4GB. */
256 static struct rtas_args args;
259 * At this point we have got all the cpus we can into
260 * xmon, so there is hopefully no other cpu calling RTAS
261 * at the moment, even though we don't take rtas.lock.
262 * If we did try to take rtas.lock there would be a
263 * real possibility of deadlock.
265 args.token = rtas_token("set-indicator");
266 if (args.token == RTAS_UNKNOWN_SERVICE)
267 return;
268 args.nargs = 3;
269 args.nret = 1;
270 args.rets = &args.args[3];
271 args.args[0] = SURVEILLANCE_TOKEN;
272 args.args[1] = 0;
273 args.args[2] = 0;
274 enter_rtas(__pa(&args));
275 #endif /* CONFIG_PPC_PSERIES */
278 #ifdef CONFIG_SMP
279 static int xmon_speaker;
281 static void get_output_lock(void)
283 int me = smp_processor_id() + 0x100;
284 int last_speaker = 0, prev;
285 long timeout;
287 if (xmon_speaker == me)
288 return;
289 for (;;) {
290 if (xmon_speaker == 0) {
291 last_speaker = cmpxchg(&xmon_speaker, 0, me);
292 if (last_speaker == 0)
293 return;
295 timeout = 10000000;
296 while (xmon_speaker == last_speaker) {
297 if (--timeout > 0)
298 continue;
299 /* hostile takeover */
300 prev = cmpxchg(&xmon_speaker, last_speaker, me);
301 if (prev == last_speaker)
302 return;
303 break;
308 static void release_output_lock(void)
310 xmon_speaker = 0;
312 #endif
314 static int xmon_core(struct pt_regs *regs, int fromipi)
316 int cmd = 0;
317 unsigned long msr;
318 struct bpt *bp;
319 long recurse_jmp[JMP_BUF_LEN];
320 unsigned long offset;
321 #ifdef CONFIG_SMP
322 int cpu;
323 int secondary;
324 unsigned long timeout;
325 #endif
327 msr = mfmsr();
328 mtmsr(msr & ~MSR_EE); /* disable interrupts */
330 bp = in_breakpoint_table(regs->nip, &offset);
331 if (bp != NULL) {
332 regs->nip = bp->address + offset;
333 atomic_dec(&bp->ref_count);
336 remove_cpu_bpts();
338 #ifdef CONFIG_SMP
339 cpu = smp_processor_id();
340 if (cpu_isset(cpu, cpus_in_xmon)) {
341 get_output_lock();
342 excprint(regs);
343 printf("cpu 0x%x: Exception %lx %s in xmon, "
344 "returning to main loop\n",
345 cpu, regs->trap, getvecname(TRAP(regs)));
346 release_output_lock();
347 longjmp(xmon_fault_jmp[cpu], 1);
350 if (setjmp(recurse_jmp) != 0) {
351 if (!in_xmon || !xmon_gate) {
352 get_output_lock();
353 printf("xmon: WARNING: bad recursive fault "
354 "on cpu 0x%x\n", cpu);
355 release_output_lock();
356 goto waiting;
358 secondary = !(xmon_taken && cpu == xmon_owner);
359 goto cmdloop;
362 xmon_fault_jmp[cpu] = recurse_jmp;
363 cpu_set(cpu, cpus_in_xmon);
365 bp = NULL;
366 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
367 bp = at_breakpoint(regs->nip);
368 if (bp || (regs->msr & MSR_RI) == 0)
369 fromipi = 0;
371 if (!fromipi) {
372 get_output_lock();
373 excprint(regs);
374 if (bp) {
375 printf("cpu 0x%x stopped at breakpoint 0x%x (",
376 cpu, BP_NUM(bp));
377 xmon_print_symbol(regs->nip, " ", ")\n");
379 if ((regs->msr & MSR_RI) == 0)
380 printf("WARNING: exception is not recoverable, "
381 "can't continue\n");
382 release_output_lock();
385 waiting:
386 secondary = 1;
387 while (secondary && !xmon_gate) {
388 if (in_xmon == 0) {
389 if (fromipi)
390 goto leave;
391 secondary = test_and_set_bit(0, &in_xmon);
393 barrier();
396 if (!secondary && !xmon_gate) {
397 /* we are the first cpu to come in */
398 /* interrupt other cpu(s) */
399 int ncpus = num_online_cpus();
401 xmon_owner = cpu;
402 mb();
403 if (ncpus > 1) {
404 smp_send_debugger_break(MSG_ALL_BUT_SELF);
405 /* wait for other cpus to come in */
406 for (timeout = 100000000; timeout != 0; --timeout) {
407 if (cpus_weight(cpus_in_xmon) >= ncpus)
408 break;
409 barrier();
412 remove_bpts();
413 disable_surveillance();
414 /* for breakpoint or single step, print the current instr. */
415 if (bp || TRAP(regs) == 0xd00)
416 ppc_inst_dump(regs->nip, 1, 0);
417 printf("enter ? for help\n");
418 mb();
419 xmon_gate = 1;
420 barrier();
423 cmdloop:
424 while (in_xmon) {
425 if (secondary) {
426 if (cpu == xmon_owner) {
427 if (!test_and_set_bit(0, &xmon_taken)) {
428 secondary = 0;
429 continue;
431 /* missed it */
432 while (cpu == xmon_owner)
433 barrier();
435 barrier();
436 } else {
437 cmd = cmds(regs);
438 if (cmd != 0) {
439 /* exiting xmon */
440 insert_bpts();
441 xmon_gate = 0;
442 wmb();
443 in_xmon = 0;
444 break;
446 /* have switched to some other cpu */
447 secondary = 1;
450 leave:
451 cpu_clear(cpu, cpus_in_xmon);
452 xmon_fault_jmp[cpu] = NULL;
453 #else
454 /* UP is simple... */
455 if (in_xmon) {
456 printf("Exception %lx %s in xmon, returning to main loop\n",
457 regs->trap, getvecname(TRAP(regs)));
458 longjmp(xmon_fault_jmp[0], 1);
460 if (setjmp(recurse_jmp) == 0) {
461 xmon_fault_jmp[0] = recurse_jmp;
462 in_xmon = 1;
464 excprint(regs);
465 bp = at_breakpoint(regs->nip);
466 if (bp) {
467 printf("Stopped at breakpoint %x (", BP_NUM(bp));
468 xmon_print_symbol(regs->nip, " ", ")\n");
470 if ((regs->msr & MSR_RI) == 0)
471 printf("WARNING: exception is not recoverable, "
472 "can't continue\n");
473 remove_bpts();
474 disable_surveillance();
475 /* for breakpoint or single step, print the current instr. */
476 if (bp || TRAP(regs) == 0xd00)
477 ppc_inst_dump(regs->nip, 1, 0);
478 printf("enter ? for help\n");
481 cmd = cmds(regs);
483 insert_bpts();
484 in_xmon = 0;
485 #endif
487 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
488 bp = at_breakpoint(regs->nip);
489 if (bp != NULL) {
490 int stepped = emulate_step(regs, bp->instr[0]);
491 if (stepped == 0) {
492 regs->nip = (unsigned long) &bp->instr[0];
493 atomic_inc(&bp->ref_count);
494 } else if (stepped < 0) {
495 printf("Couldn't single-step %s instruction\n",
496 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
501 insert_cpu_bpts();
503 mtmsr(msr); /* restore interrupt enable */
505 return cmd != 'X';
508 int xmon(struct pt_regs *excp)
510 struct pt_regs regs;
512 if (excp == NULL) {
513 xmon_save_regs(&regs);
514 excp = &regs;
516 return xmon_core(excp, 0);
518 EXPORT_SYMBOL(xmon);
520 irqreturn_t
521 xmon_irq(int irq, void *d, struct pt_regs *regs)
523 unsigned long flags;
524 local_irq_save(flags);
525 printf("Keyboard interrupt\n");
526 xmon(regs);
527 local_irq_restore(flags);
528 return IRQ_HANDLED;
531 static int xmon_bpt(struct pt_regs *regs)
533 struct bpt *bp;
534 unsigned long offset;
536 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
537 return 0;
539 /* Are we at the trap at bp->instr[1] for some bp? */
540 bp = in_breakpoint_table(regs->nip, &offset);
541 if (bp != NULL && offset == 4) {
542 regs->nip = bp->address + 4;
543 atomic_dec(&bp->ref_count);
544 return 1;
547 /* Are we at a breakpoint? */
548 bp = at_breakpoint(regs->nip);
549 if (!bp)
550 return 0;
552 xmon_core(regs, 0);
554 return 1;
557 static int xmon_sstep(struct pt_regs *regs)
559 if (user_mode(regs))
560 return 0;
561 xmon_core(regs, 0);
562 return 1;
565 static int xmon_dabr_match(struct pt_regs *regs)
567 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
568 return 0;
569 if (dabr.enabled == 0)
570 return 0;
571 xmon_core(regs, 0);
572 return 1;
575 static int xmon_iabr_match(struct pt_regs *regs)
577 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
578 return 0;
579 if (iabr == 0)
580 return 0;
581 xmon_core(regs, 0);
582 return 1;
585 static int xmon_ipi(struct pt_regs *regs)
587 #ifdef CONFIG_SMP
588 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
589 xmon_core(regs, 1);
590 #endif
591 return 0;
594 static int xmon_fault_handler(struct pt_regs *regs)
596 struct bpt *bp;
597 unsigned long offset;
599 if (in_xmon && catch_memory_errors)
600 handle_fault(regs); /* doesn't return */
602 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
603 bp = in_breakpoint_table(regs->nip, &offset);
604 if (bp != NULL) {
605 regs->nip = bp->address + offset;
606 atomic_dec(&bp->ref_count);
610 return 0;
613 static struct bpt *at_breakpoint(unsigned long pc)
615 int i;
616 struct bpt *bp;
618 bp = bpts;
619 for (i = 0; i < NBPTS; ++i, ++bp)
620 if (bp->enabled && pc == bp->address)
621 return bp;
622 return NULL;
625 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
627 unsigned long off;
629 off = nip - (unsigned long) bpts;
630 if (off >= sizeof(bpts))
631 return NULL;
632 off %= sizeof(struct bpt);
633 if (off != offsetof(struct bpt, instr[0])
634 && off != offsetof(struct bpt, instr[1]))
635 return NULL;
636 *offp = off - offsetof(struct bpt, instr[0]);
637 return (struct bpt *) (nip - off);
640 static struct bpt *new_breakpoint(unsigned long a)
642 struct bpt *bp;
644 a &= ~3UL;
645 bp = at_breakpoint(a);
646 if (bp)
647 return bp;
649 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
650 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
651 bp->address = a;
652 bp->instr[1] = bpinstr;
653 store_inst(&bp->instr[1]);
654 return bp;
658 printf("Sorry, no free breakpoints. Please clear one first.\n");
659 return NULL;
662 static void insert_bpts(void)
664 int i;
665 struct bpt *bp;
667 bp = bpts;
668 for (i = 0; i < NBPTS; ++i, ++bp) {
669 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
670 continue;
671 if (mread(bp->address, &bp->instr[0], 4) != 4) {
672 printf("Couldn't read instruction at %lx, "
673 "disabling breakpoint there\n", bp->address);
674 bp->enabled = 0;
675 continue;
677 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
678 printf("Breakpoint at %lx is on an mtmsrd or rfid "
679 "instruction, disabling it\n", bp->address);
680 bp->enabled = 0;
681 continue;
683 store_inst(&bp->instr[0]);
684 if (bp->enabled & BP_IABR)
685 continue;
686 if (mwrite(bp->address, &bpinstr, 4) != 4) {
687 printf("Couldn't write instruction at %lx, "
688 "disabling breakpoint there\n", bp->address);
689 bp->enabled &= ~BP_TRAP;
690 continue;
692 store_inst((void *)bp->address);
696 static void insert_cpu_bpts(void)
698 if (dabr.enabled)
699 set_dabr(dabr.address | (dabr.enabled & 7));
700 if (iabr && cpu_has_feature(CPU_FTR_IABR))
701 mtspr(SPRN_IABR, iabr->address
702 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
705 static void remove_bpts(void)
707 int i;
708 struct bpt *bp;
709 unsigned instr;
711 bp = bpts;
712 for (i = 0; i < NBPTS; ++i, ++bp) {
713 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
714 continue;
715 if (mread(bp->address, &instr, 4) == 4
716 && instr == bpinstr
717 && mwrite(bp->address, &bp->instr, 4) != 4)
718 printf("Couldn't remove breakpoint at %lx\n",
719 bp->address);
720 else
721 store_inst((void *)bp->address);
725 static void remove_cpu_bpts(void)
727 set_dabr(0);
728 if (cpu_has_feature(CPU_FTR_IABR))
729 mtspr(SPRN_IABR, 0);
732 /* Command interpreting routine */
733 static char *last_cmd;
735 static int
736 cmds(struct pt_regs *excp)
738 int cmd = 0;
740 last_cmd = NULL;
741 xmon_regs = excp;
742 for(;;) {
743 #ifdef CONFIG_SMP
744 printf("%x:", smp_processor_id());
745 #endif /* CONFIG_SMP */
746 printf("mon> ");
747 flush_input();
748 termch = 0;
749 cmd = skipbl();
750 if( cmd == '\n' ) {
751 if (last_cmd == NULL)
752 continue;
753 take_input(last_cmd);
754 last_cmd = NULL;
755 cmd = inchar();
757 switch (cmd) {
758 case 'm':
759 cmd = inchar();
760 switch (cmd) {
761 case 'm':
762 case 's':
763 case 'd':
764 memops(cmd);
765 break;
766 case 'l':
767 memlocate();
768 break;
769 case 'z':
770 memzcan();
771 break;
772 case 'i':
773 show_mem();
774 break;
775 default:
776 termch = cmd;
777 memex();
779 break;
780 case 'd':
781 dump();
782 break;
783 case 'l':
784 symbol_lookup();
785 break;
786 case 'r':
787 prregs(excp); /* print regs */
788 break;
789 case 'e':
790 excprint(excp);
791 break;
792 case 'S':
793 super_regs();
794 break;
795 case 't':
796 backtrace(excp);
797 break;
798 case 'f':
799 cacheflush();
800 break;
801 case 's':
802 if (do_step(excp))
803 return cmd;
804 break;
805 case 'x':
806 case 'X':
807 return cmd;
808 case EOF:
809 printf(" <no input ...>\n");
810 mdelay(2000);
811 return cmd;
812 case '?':
813 printf(help_string);
814 break;
815 case 'b':
816 bpt_cmds();
817 break;
818 case 'C':
819 csum();
820 break;
821 case 'c':
822 if (cpu_cmd())
823 return 0;
824 break;
825 case 'z':
826 bootcmds();
827 break;
828 case 'p':
829 proccall();
830 break;
831 #ifdef CONFIG_PPC_STD_MMU
832 case 'u':
833 dump_segments();
834 break;
835 #endif
836 default:
837 printf("Unrecognized command: ");
838 do {
839 if (' ' < cmd && cmd <= '~')
840 putchar(cmd);
841 else
842 printf("\\x%x", cmd);
843 cmd = inchar();
844 } while (cmd != '\n');
845 printf(" (type ? for help)\n");
846 break;
852 * Step a single instruction.
853 * Some instructions we emulate, others we execute with MSR_SE set.
855 static int do_step(struct pt_regs *regs)
857 unsigned int instr;
858 int stepped;
860 /* check we are in 64-bit kernel mode, translation enabled */
861 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
862 if (mread(regs->nip, &instr, 4) == 4) {
863 stepped = emulate_step(regs, instr);
864 if (stepped < 0) {
865 printf("Couldn't single-step %s instruction\n",
866 (IS_RFID(instr)? "rfid": "mtmsrd"));
867 return 0;
869 if (stepped > 0) {
870 regs->trap = 0xd00 | (regs->trap & 1);
871 printf("stepped to ");
872 xmon_print_symbol(regs->nip, " ", "\n");
873 ppc_inst_dump(regs->nip, 1, 0);
874 return 0;
878 regs->msr |= MSR_SE;
879 return 1;
882 static void bootcmds(void)
884 int cmd;
886 cmd = inchar();
887 if (cmd == 'r')
888 ppc_md.restart(NULL);
889 else if (cmd == 'h')
890 ppc_md.halt();
891 else if (cmd == 'p')
892 ppc_md.power_off();
895 static int cpu_cmd(void)
897 #ifdef CONFIG_SMP
898 unsigned long cpu;
899 int timeout;
900 int count;
902 if (!scanhex(&cpu)) {
903 /* print cpus waiting or in xmon */
904 printf("cpus stopped:");
905 count = 0;
906 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
907 if (cpu_isset(cpu, cpus_in_xmon)) {
908 if (count == 0)
909 printf(" %x", cpu);
910 ++count;
911 } else {
912 if (count > 1)
913 printf("-%x", cpu - 1);
914 count = 0;
917 if (count > 1)
918 printf("-%x", NR_CPUS - 1);
919 printf("\n");
920 return 0;
922 /* try to switch to cpu specified */
923 if (!cpu_isset(cpu, cpus_in_xmon)) {
924 printf("cpu 0x%x isn't in xmon\n", cpu);
925 return 0;
927 xmon_taken = 0;
928 mb();
929 xmon_owner = cpu;
930 timeout = 10000000;
931 while (!xmon_taken) {
932 if (--timeout == 0) {
933 if (test_and_set_bit(0, &xmon_taken))
934 break;
935 /* take control back */
936 mb();
937 xmon_owner = smp_processor_id();
938 printf("cpu %u didn't take control\n", cpu);
939 return 0;
941 barrier();
943 return 1;
944 #else
945 return 0;
946 #endif /* CONFIG_SMP */
949 static unsigned short fcstab[256] = {
950 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
951 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
952 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
953 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
954 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
955 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
956 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
957 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
958 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
959 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
960 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
961 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
962 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
963 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
964 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
965 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
966 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
967 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
968 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
969 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
970 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
971 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
972 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
973 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
974 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
975 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
976 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
977 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
978 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
979 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
980 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
981 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
984 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
986 static void
987 csum(void)
989 unsigned int i;
990 unsigned short fcs;
991 unsigned char v;
993 if (!scanhex(&adrs))
994 return;
995 if (!scanhex(&ncsum))
996 return;
997 fcs = 0xffff;
998 for (i = 0; i < ncsum; ++i) {
999 if (mread(adrs+i, &v, 1) == 0) {
1000 printf("csum stopped at %x\n", adrs+i);
1001 break;
1003 fcs = FCS(fcs, v);
1005 printf("%x\n", fcs);
1009 * Check if this is a suitable place to put a breakpoint.
1011 static long check_bp_loc(unsigned long addr)
1013 unsigned int instr;
1015 addr &= ~3;
1016 if (!is_kernel_addr(addr)) {
1017 printf("Breakpoints may only be placed at kernel addresses\n");
1018 return 0;
1020 if (!mread(addr, &instr, sizeof(instr))) {
1021 printf("Can't read instruction at address %lx\n", addr);
1022 return 0;
1024 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1025 printf("Breakpoints may not be placed on mtmsrd or rfid "
1026 "instructions\n");
1027 return 0;
1029 return 1;
1032 static char *breakpoint_help_string =
1033 "Breakpoint command usage:\n"
1034 "b show breakpoints\n"
1035 "b <addr> [cnt] set breakpoint at given instr addr\n"
1036 "bc clear all breakpoints\n"
1037 "bc <n/addr> clear breakpoint number n or at addr\n"
1038 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1039 "bd <addr> [cnt] set hardware data breakpoint\n"
1042 static void
1043 bpt_cmds(void)
1045 int cmd;
1046 unsigned long a;
1047 int mode, i;
1048 struct bpt *bp;
1049 const char badaddr[] = "Only kernel addresses are permitted "
1050 "for breakpoints\n";
1052 cmd = inchar();
1053 switch (cmd) {
1054 #ifndef CONFIG_8xx
1055 case 'd': /* bd - hardware data breakpoint */
1056 mode = 7;
1057 cmd = inchar();
1058 if (cmd == 'r')
1059 mode = 5;
1060 else if (cmd == 'w')
1061 mode = 6;
1062 else
1063 termch = cmd;
1064 dabr.address = 0;
1065 dabr.enabled = 0;
1066 if (scanhex(&dabr.address)) {
1067 if (!is_kernel_addr(dabr.address)) {
1068 printf(badaddr);
1069 break;
1071 dabr.address &= ~7;
1072 dabr.enabled = mode | BP_DABR;
1074 break;
1076 case 'i': /* bi - hardware instr breakpoint */
1077 if (!cpu_has_feature(CPU_FTR_IABR)) {
1078 printf("Hardware instruction breakpoint "
1079 "not supported on this cpu\n");
1080 break;
1082 if (iabr) {
1083 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1084 iabr = NULL;
1086 if (!scanhex(&a))
1087 break;
1088 if (!check_bp_loc(a))
1089 break;
1090 bp = new_breakpoint(a);
1091 if (bp != NULL) {
1092 bp->enabled |= BP_IABR | BP_IABR_TE;
1093 iabr = bp;
1095 break;
1096 #endif
1098 case 'c':
1099 if (!scanhex(&a)) {
1100 /* clear all breakpoints */
1101 for (i = 0; i < NBPTS; ++i)
1102 bpts[i].enabled = 0;
1103 iabr = NULL;
1104 dabr.enabled = 0;
1105 printf("All breakpoints cleared\n");
1106 break;
1109 if (a <= NBPTS && a >= 1) {
1110 /* assume a breakpoint number */
1111 bp = &bpts[a-1]; /* bp nums are 1 based */
1112 } else {
1113 /* assume a breakpoint address */
1114 bp = at_breakpoint(a);
1115 if (bp == 0) {
1116 printf("No breakpoint at %x\n", a);
1117 break;
1121 printf("Cleared breakpoint %x (", BP_NUM(bp));
1122 xmon_print_symbol(bp->address, " ", ")\n");
1123 bp->enabled = 0;
1124 break;
1126 default:
1127 termch = cmd;
1128 cmd = skipbl();
1129 if (cmd == '?') {
1130 printf(breakpoint_help_string);
1131 break;
1133 termch = cmd;
1134 if (!scanhex(&a)) {
1135 /* print all breakpoints */
1136 printf(" type address\n");
1137 if (dabr.enabled) {
1138 printf(" data "REG" [", dabr.address);
1139 if (dabr.enabled & 1)
1140 printf("r");
1141 if (dabr.enabled & 2)
1142 printf("w");
1143 printf("]\n");
1145 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1146 if (!bp->enabled)
1147 continue;
1148 printf("%2x %s ", BP_NUM(bp),
1149 (bp->enabled & BP_IABR)? "inst": "trap");
1150 xmon_print_symbol(bp->address, " ", "\n");
1152 break;
1155 if (!check_bp_loc(a))
1156 break;
1157 bp = new_breakpoint(a);
1158 if (bp != NULL)
1159 bp->enabled |= BP_TRAP;
1160 break;
1164 /* Very cheap human name for vector lookup. */
1165 static
1166 const char *getvecname(unsigned long vec)
1168 char *ret;
1170 switch (vec) {
1171 case 0x100: ret = "(System Reset)"; break;
1172 case 0x200: ret = "(Machine Check)"; break;
1173 case 0x300: ret = "(Data Access)"; break;
1174 case 0x380: ret = "(Data SLB Access)"; break;
1175 case 0x400: ret = "(Instruction Access)"; break;
1176 case 0x480: ret = "(Instruction SLB Access)"; break;
1177 case 0x500: ret = "(Hardware Interrupt)"; break;
1178 case 0x600: ret = "(Alignment)"; break;
1179 case 0x700: ret = "(Program Check)"; break;
1180 case 0x800: ret = "(FPU Unavailable)"; break;
1181 case 0x900: ret = "(Decrementer)"; break;
1182 case 0xc00: ret = "(System Call)"; break;
1183 case 0xd00: ret = "(Single Step)"; break;
1184 case 0xf00: ret = "(Performance Monitor)"; break;
1185 case 0xf20: ret = "(Altivec Unavailable)"; break;
1186 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1187 default: ret = "";
1189 return ret;
1192 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1193 unsigned long *endp)
1195 unsigned long size, offset;
1196 const char *name;
1197 char *modname;
1199 *startp = *endp = 0;
1200 if (pc == 0)
1201 return;
1202 if (setjmp(bus_error_jmp) == 0) {
1203 catch_memory_errors = 1;
1204 sync();
1205 name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
1206 if (name != NULL) {
1207 *startp = pc - offset;
1208 *endp = pc - offset + size;
1210 sync();
1212 catch_memory_errors = 0;
1215 static int xmon_depth_to_print = 64;
1217 #ifdef CONFIG_PPC64
1218 #define LRSAVE_OFFSET 0x10
1219 #define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
1220 #define MARKER_OFFSET 0x60
1221 #define REGS_OFFSET 0x70
1222 #else
1223 #define LRSAVE_OFFSET 4
1224 #define REG_FRAME_MARKER 0x72656773
1225 #define MARKER_OFFSET 8
1226 #define REGS_OFFSET 16
1227 #endif
1229 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1230 unsigned long pc)
1232 unsigned long ip;
1233 unsigned long newsp;
1234 unsigned long marker;
1235 int count = 0;
1236 struct pt_regs regs;
1238 do {
1239 if (sp < PAGE_OFFSET) {
1240 if (sp != 0)
1241 printf("SP (%lx) is in userspace\n", sp);
1242 break;
1245 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1246 || !mread(sp, &newsp, sizeof(unsigned long))) {
1247 printf("Couldn't read stack frame at %lx\n", sp);
1248 break;
1252 * For the first stack frame, try to work out if
1253 * LR and/or the saved LR value in the bottommost
1254 * stack frame are valid.
1256 if ((pc | lr) != 0) {
1257 unsigned long fnstart, fnend;
1258 unsigned long nextip;
1259 int printip = 1;
1261 get_function_bounds(pc, &fnstart, &fnend);
1262 nextip = 0;
1263 if (newsp > sp)
1264 mread(newsp + LRSAVE_OFFSET, &nextip,
1265 sizeof(unsigned long));
1266 if (lr == ip) {
1267 if (lr < PAGE_OFFSET
1268 || (fnstart <= lr && lr < fnend))
1269 printip = 0;
1270 } else if (lr == nextip) {
1271 printip = 0;
1272 } else if (lr >= PAGE_OFFSET
1273 && !(fnstart <= lr && lr < fnend)) {
1274 printf("[link register ] ");
1275 xmon_print_symbol(lr, " ", "\n");
1277 if (printip) {
1278 printf("["REG"] ", sp);
1279 xmon_print_symbol(ip, " ", " (unreliable)\n");
1281 pc = lr = 0;
1283 } else {
1284 printf("["REG"] ", sp);
1285 xmon_print_symbol(ip, " ", "\n");
1288 /* Look for "regshere" marker to see if this is
1289 an exception frame. */
1290 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1291 && marker == REG_FRAME_MARKER) {
1292 if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
1293 != sizeof(regs)) {
1294 printf("Couldn't read registers at %lx\n",
1295 sp + REGS_OFFSET);
1296 break;
1298 printf("--- Exception: %lx %s at ", regs.trap,
1299 getvecname(TRAP(&regs)));
1300 pc = regs.nip;
1301 lr = regs.link;
1302 xmon_print_symbol(pc, " ", "\n");
1305 if (newsp == 0)
1306 break;
1308 sp = newsp;
1309 } while (count++ < xmon_depth_to_print);
1312 static void backtrace(struct pt_regs *excp)
1314 unsigned long sp;
1316 if (scanhex(&sp))
1317 xmon_show_stack(sp, 0, 0);
1318 else
1319 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1320 scannl();
1323 static void print_bug_trap(struct pt_regs *regs)
1325 struct bug_entry *bug;
1326 unsigned long addr;
1328 if (regs->msr & MSR_PR)
1329 return; /* not in kernel */
1330 addr = regs->nip; /* address of trap instruction */
1331 if (addr < PAGE_OFFSET)
1332 return;
1333 bug = find_bug(regs->nip);
1334 if (bug == NULL)
1335 return;
1336 if (bug->line & BUG_WARNING_TRAP)
1337 return;
1339 printf("kernel BUG in %s at %s:%d!\n",
1340 bug->function, bug->file, (unsigned int)bug->line);
1343 void excprint(struct pt_regs *fp)
1345 unsigned long trap;
1347 #ifdef CONFIG_SMP
1348 printf("cpu 0x%x: ", smp_processor_id());
1349 #endif /* CONFIG_SMP */
1351 trap = TRAP(fp);
1352 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1353 printf(" pc: ");
1354 xmon_print_symbol(fp->nip, ": ", "\n");
1356 printf(" lr: ", fp->link);
1357 xmon_print_symbol(fp->link, ": ", "\n");
1359 printf(" sp: %lx\n", fp->gpr[1]);
1360 printf(" msr: %lx\n", fp->msr);
1362 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1363 printf(" dar: %lx\n", fp->dar);
1364 if (trap != 0x380)
1365 printf(" dsisr: %lx\n", fp->dsisr);
1368 printf(" current = 0x%lx\n", current);
1369 #ifdef CONFIG_PPC64
1370 printf(" paca = 0x%lx\n", get_paca());
1371 #endif
1372 if (current) {
1373 printf(" pid = %ld, comm = %s\n",
1374 current->pid, current->comm);
1377 if (trap == 0x700)
1378 print_bug_trap(fp);
1381 void prregs(struct pt_regs *fp)
1383 int n, trap;
1384 unsigned long base;
1385 struct pt_regs regs;
1387 if (scanhex(&base)) {
1388 if (setjmp(bus_error_jmp) == 0) {
1389 catch_memory_errors = 1;
1390 sync();
1391 regs = *(struct pt_regs *)base;
1392 sync();
1393 __delay(200);
1394 } else {
1395 catch_memory_errors = 0;
1396 printf("*** Error reading registers from "REG"\n",
1397 base);
1398 return;
1400 catch_memory_errors = 0;
1401 fp = &regs;
1404 #ifdef CONFIG_PPC64
1405 if (FULL_REGS(fp)) {
1406 for (n = 0; n < 16; ++n)
1407 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1408 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1409 } else {
1410 for (n = 0; n < 7; ++n)
1411 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1412 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1414 #else
1415 for (n = 0; n < 32; ++n) {
1416 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1417 (n & 3) == 3? "\n": " ");
1418 if (n == 12 && !FULL_REGS(fp)) {
1419 printf("\n");
1420 break;
1423 #endif
1424 printf("pc = ");
1425 xmon_print_symbol(fp->nip, " ", "\n");
1426 printf("lr = ");
1427 xmon_print_symbol(fp->link, " ", "\n");
1428 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1429 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1430 fp->ctr, fp->xer, fp->trap);
1431 trap = TRAP(fp);
1432 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1433 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1436 void cacheflush(void)
1438 int cmd;
1439 unsigned long nflush;
1441 cmd = inchar();
1442 if (cmd != 'i')
1443 termch = cmd;
1444 scanhex((void *)&adrs);
1445 if (termch != '\n')
1446 termch = 0;
1447 nflush = 1;
1448 scanhex(&nflush);
1449 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1450 if (setjmp(bus_error_jmp) == 0) {
1451 catch_memory_errors = 1;
1452 sync();
1454 if (cmd != 'i') {
1455 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1456 cflush((void *) adrs);
1457 } else {
1458 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1459 cinval((void *) adrs);
1461 sync();
1462 /* wait a little while to see if we get a machine check */
1463 __delay(200);
1465 catch_memory_errors = 0;
1468 unsigned long
1469 read_spr(int n)
1471 unsigned int instrs[2];
1472 unsigned long (*code)(void);
1473 unsigned long ret = -1UL;
1474 #ifdef CONFIG_PPC64
1475 unsigned long opd[3];
1477 opd[0] = (unsigned long)instrs;
1478 opd[1] = 0;
1479 opd[2] = 0;
1480 code = (unsigned long (*)(void)) opd;
1481 #else
1482 code = (unsigned long (*)(void)) instrs;
1483 #endif
1485 /* mfspr r3,n; blr */
1486 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1487 instrs[1] = 0x4e800020;
1488 store_inst(instrs);
1489 store_inst(instrs+1);
1491 if (setjmp(bus_error_jmp) == 0) {
1492 catch_memory_errors = 1;
1493 sync();
1495 ret = code();
1497 sync();
1498 /* wait a little while to see if we get a machine check */
1499 __delay(200);
1500 n = size;
1503 return ret;
1506 void
1507 write_spr(int n, unsigned long val)
1509 unsigned int instrs[2];
1510 unsigned long (*code)(unsigned long);
1511 #ifdef CONFIG_PPC64
1512 unsigned long opd[3];
1514 opd[0] = (unsigned long)instrs;
1515 opd[1] = 0;
1516 opd[2] = 0;
1517 code = (unsigned long (*)(unsigned long)) opd;
1518 #else
1519 code = (unsigned long (*)(unsigned long)) instrs;
1520 #endif
1522 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1523 instrs[1] = 0x4e800020;
1524 store_inst(instrs);
1525 store_inst(instrs+1);
1527 if (setjmp(bus_error_jmp) == 0) {
1528 catch_memory_errors = 1;
1529 sync();
1531 code(val);
1533 sync();
1534 /* wait a little while to see if we get a machine check */
1535 __delay(200);
1536 n = size;
1540 static unsigned long regno;
1541 extern char exc_prolog;
1542 extern char dec_exc;
1544 void super_regs(void)
1546 int cmd;
1547 unsigned long val;
1548 #ifdef CONFIG_PPC_ISERIES
1549 struct paca_struct *ptrPaca = NULL;
1550 struct lppaca *ptrLpPaca = NULL;
1551 struct ItLpRegSave *ptrLpRegSave = NULL;
1552 #endif
1554 cmd = skipbl();
1555 if (cmd == '\n') {
1556 unsigned long sp, toc;
1557 asm("mr %0,1" : "=r" (sp) :);
1558 asm("mr %0,2" : "=r" (toc) :);
1560 printf("msr = "REG" sprg0= "REG"\n",
1561 mfmsr(), mfspr(SPRN_SPRG0));
1562 printf("pvr = "REG" sprg1= "REG"\n",
1563 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1564 printf("dec = "REG" sprg2= "REG"\n",
1565 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1566 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1567 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1568 #ifdef CONFIG_PPC_ISERIES
1569 // Dump out relevant Paca data areas.
1570 printf("Paca: \n");
1571 ptrPaca = get_paca();
1573 printf(" Local Processor Control Area (LpPaca): \n");
1574 ptrLpPaca = ptrPaca->lppaca_ptr;
1575 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1576 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1577 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1578 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1579 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1581 printf(" Local Processor Register Save Area (LpRegSave): \n");
1582 ptrLpRegSave = ptrPaca->reg_save_ptr;
1583 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1584 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1585 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1586 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1587 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1588 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1589 #endif
1591 return;
1594 scanhex(&regno);
1595 switch (cmd) {
1596 case 'w':
1597 val = read_spr(regno);
1598 scanhex(&val);
1599 write_spr(regno, val);
1600 /* fall through */
1601 case 'r':
1602 printf("spr %lx = %lx\n", regno, read_spr(regno));
1603 break;
1605 scannl();
1609 * Stuff for reading and writing memory safely
1612 mread(unsigned long adrs, void *buf, int size)
1614 volatile int n;
1615 char *p, *q;
1617 n = 0;
1618 if (setjmp(bus_error_jmp) == 0) {
1619 catch_memory_errors = 1;
1620 sync();
1621 p = (char *)adrs;
1622 q = (char *)buf;
1623 switch (size) {
1624 case 2:
1625 *(u16 *)q = *(u16 *)p;
1626 break;
1627 case 4:
1628 *(u32 *)q = *(u32 *)p;
1629 break;
1630 case 8:
1631 *(u64 *)q = *(u64 *)p;
1632 break;
1633 default:
1634 for( ; n < size; ++n) {
1635 *q++ = *p++;
1636 sync();
1639 sync();
1640 /* wait a little while to see if we get a machine check */
1641 __delay(200);
1642 n = size;
1644 catch_memory_errors = 0;
1645 return n;
1649 mwrite(unsigned long adrs, void *buf, int size)
1651 volatile int n;
1652 char *p, *q;
1654 n = 0;
1655 if (setjmp(bus_error_jmp) == 0) {
1656 catch_memory_errors = 1;
1657 sync();
1658 p = (char *) adrs;
1659 q = (char *) buf;
1660 switch (size) {
1661 case 2:
1662 *(u16 *)p = *(u16 *)q;
1663 break;
1664 case 4:
1665 *(u32 *)p = *(u32 *)q;
1666 break;
1667 case 8:
1668 *(u64 *)p = *(u64 *)q;
1669 break;
1670 default:
1671 for ( ; n < size; ++n) {
1672 *p++ = *q++;
1673 sync();
1676 sync();
1677 /* wait a little while to see if we get a machine check */
1678 __delay(200);
1679 n = size;
1680 } else {
1681 printf("*** Error writing address %x\n", adrs + n);
1683 catch_memory_errors = 0;
1684 return n;
1687 static int fault_type;
1688 static int fault_except;
1689 static char *fault_chars[] = { "--", "**", "##" };
1691 static int handle_fault(struct pt_regs *regs)
1693 fault_except = TRAP(regs);
1694 switch (TRAP(regs)) {
1695 case 0x200:
1696 fault_type = 0;
1697 break;
1698 case 0x300:
1699 case 0x380:
1700 fault_type = 1;
1701 break;
1702 default:
1703 fault_type = 2;
1706 longjmp(bus_error_jmp, 1);
1708 return 0;
1711 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1713 void
1714 byterev(unsigned char *val, int size)
1716 int t;
1718 switch (size) {
1719 case 2:
1720 SWAP(val[0], val[1], t);
1721 break;
1722 case 4:
1723 SWAP(val[0], val[3], t);
1724 SWAP(val[1], val[2], t);
1725 break;
1726 case 8: /* is there really any use for this? */
1727 SWAP(val[0], val[7], t);
1728 SWAP(val[1], val[6], t);
1729 SWAP(val[2], val[5], t);
1730 SWAP(val[3], val[4], t);
1731 break;
1735 static int brev;
1736 static int mnoread;
1738 static char *memex_help_string =
1739 "Memory examine command usage:\n"
1740 "m [addr] [flags] examine/change memory\n"
1741 " addr is optional. will start where left off.\n"
1742 " flags may include chars from this set:\n"
1743 " b modify by bytes (default)\n"
1744 " w modify by words (2 byte)\n"
1745 " l modify by longs (4 byte)\n"
1746 " d modify by doubleword (8 byte)\n"
1747 " r toggle reverse byte order mode\n"
1748 " n do not read memory (for i/o spaces)\n"
1749 " . ok to read (default)\n"
1750 "NOTE: flags are saved as defaults\n"
1753 static char *memex_subcmd_help_string =
1754 "Memory examine subcommands:\n"
1755 " hexval write this val to current location\n"
1756 " 'string' write chars from string to this location\n"
1757 " ' increment address\n"
1758 " ^ decrement address\n"
1759 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1760 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1761 " ` clear no-read flag\n"
1762 " ; stay at this addr\n"
1763 " v change to byte mode\n"
1764 " w change to word (2 byte) mode\n"
1765 " l change to long (4 byte) mode\n"
1766 " u change to doubleword (8 byte) mode\n"
1767 " m addr change current addr\n"
1768 " n toggle no-read flag\n"
1769 " r toggle byte reverse flag\n"
1770 " < count back up count bytes\n"
1771 " > count skip forward count bytes\n"
1772 " x exit this mode\n"
1775 void
1776 memex(void)
1778 int cmd, inc, i, nslash;
1779 unsigned long n;
1780 unsigned char val[16];
1782 scanhex((void *)&adrs);
1783 cmd = skipbl();
1784 if (cmd == '?') {
1785 printf(memex_help_string);
1786 return;
1787 } else {
1788 termch = cmd;
1790 last_cmd = "m\n";
1791 while ((cmd = skipbl()) != '\n') {
1792 switch( cmd ){
1793 case 'b': size = 1; break;
1794 case 'w': size = 2; break;
1795 case 'l': size = 4; break;
1796 case 'd': size = 8; break;
1797 case 'r': brev = !brev; break;
1798 case 'n': mnoread = 1; break;
1799 case '.': mnoread = 0; break;
1802 if( size <= 0 )
1803 size = 1;
1804 else if( size > 8 )
1805 size = 8;
1806 for(;;){
1807 if (!mnoread)
1808 n = mread(adrs, val, size);
1809 printf(REG"%c", adrs, brev? 'r': ' ');
1810 if (!mnoread) {
1811 if (brev)
1812 byterev(val, size);
1813 putchar(' ');
1814 for (i = 0; i < n; ++i)
1815 printf("%.2x", val[i]);
1816 for (; i < size; ++i)
1817 printf("%s", fault_chars[fault_type]);
1819 putchar(' ');
1820 inc = size;
1821 nslash = 0;
1822 for(;;){
1823 if( scanhex(&n) ){
1824 for (i = 0; i < size; ++i)
1825 val[i] = n >> (i * 8);
1826 if (!brev)
1827 byterev(val, size);
1828 mwrite(adrs, val, size);
1829 inc = size;
1831 cmd = skipbl();
1832 if (cmd == '\n')
1833 break;
1834 inc = 0;
1835 switch (cmd) {
1836 case '\'':
1837 for(;;){
1838 n = inchar();
1839 if( n == '\\' )
1840 n = bsesc();
1841 else if( n == '\'' )
1842 break;
1843 for (i = 0; i < size; ++i)
1844 val[i] = n >> (i * 8);
1845 if (!brev)
1846 byterev(val, size);
1847 mwrite(adrs, val, size);
1848 adrs += size;
1850 adrs -= size;
1851 inc = size;
1852 break;
1853 case ',':
1854 adrs += size;
1855 break;
1856 case '.':
1857 mnoread = 0;
1858 break;
1859 case ';':
1860 break;
1861 case 'x':
1862 case EOF:
1863 scannl();
1864 return;
1865 case 'b':
1866 case 'v':
1867 size = 1;
1868 break;
1869 case 'w':
1870 size = 2;
1871 break;
1872 case 'l':
1873 size = 4;
1874 break;
1875 case 'u':
1876 size = 8;
1877 break;
1878 case '^':
1879 adrs -= size;
1880 break;
1881 break;
1882 case '/':
1883 if (nslash > 0)
1884 adrs -= 1 << nslash;
1885 else
1886 nslash = 0;
1887 nslash += 4;
1888 adrs += 1 << nslash;
1889 break;
1890 case '\\':
1891 if (nslash < 0)
1892 adrs += 1 << -nslash;
1893 else
1894 nslash = 0;
1895 nslash -= 4;
1896 adrs -= 1 << -nslash;
1897 break;
1898 case 'm':
1899 scanhex((void *)&adrs);
1900 break;
1901 case 'n':
1902 mnoread = 1;
1903 break;
1904 case 'r':
1905 brev = !brev;
1906 break;
1907 case '<':
1908 n = size;
1909 scanhex(&n);
1910 adrs -= n;
1911 break;
1912 case '>':
1913 n = size;
1914 scanhex(&n);
1915 adrs += n;
1916 break;
1917 case '?':
1918 printf(memex_subcmd_help_string);
1919 break;
1922 adrs += inc;
1927 bsesc(void)
1929 int c;
1931 c = inchar();
1932 switch( c ){
1933 case 'n': c = '\n'; break;
1934 case 'r': c = '\r'; break;
1935 case 'b': c = '\b'; break;
1936 case 't': c = '\t'; break;
1938 return c;
1941 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1942 || ('a' <= (c) && (c) <= 'f') \
1943 || ('A' <= (c) && (c) <= 'F'))
1944 void
1945 dump(void)
1947 int c;
1949 c = inchar();
1950 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1951 termch = c;
1952 scanhex((void *)&adrs);
1953 if (termch != '\n')
1954 termch = 0;
1955 if (c == 'i') {
1956 scanhex(&nidump);
1957 if (nidump == 0)
1958 nidump = 16;
1959 else if (nidump > MAX_DUMP)
1960 nidump = MAX_DUMP;
1961 adrs += ppc_inst_dump(adrs, nidump, 1);
1962 last_cmd = "di\n";
1963 } else {
1964 scanhex(&ndump);
1965 if (ndump == 0)
1966 ndump = 64;
1967 else if (ndump > MAX_DUMP)
1968 ndump = MAX_DUMP;
1969 prdump(adrs, ndump);
1970 adrs += ndump;
1971 last_cmd = "d\n";
1975 void
1976 prdump(unsigned long adrs, long ndump)
1978 long n, m, c, r, nr;
1979 unsigned char temp[16];
1981 for (n = ndump; n > 0;) {
1982 printf(REG, adrs);
1983 putchar(' ');
1984 r = n < 16? n: 16;
1985 nr = mread(adrs, temp, r);
1986 adrs += nr;
1987 for (m = 0; m < r; ++m) {
1988 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
1989 putchar(' ');
1990 if (m < nr)
1991 printf("%.2x", temp[m]);
1992 else
1993 printf("%s", fault_chars[fault_type]);
1995 for (; m < 16; ++m) {
1996 if ((m & (sizeof(long) - 1)) == 0)
1997 putchar(' ');
1998 printf(" ");
2000 printf(" |");
2001 for (m = 0; m < r; ++m) {
2002 if (m < nr) {
2003 c = temp[m];
2004 putchar(' ' <= c && c <= '~'? c: '.');
2005 } else
2006 putchar(' ');
2008 n -= r;
2009 for (; m < 16; ++m)
2010 putchar(' ');
2011 printf("|\n");
2012 if (nr < r)
2013 break;
2018 ppc_inst_dump(unsigned long adr, long count, int praddr)
2020 int nr, dotted;
2021 unsigned long first_adr;
2022 unsigned long inst, last_inst = 0;
2023 unsigned char val[4];
2025 dotted = 0;
2026 for (first_adr = adr; count > 0; --count, adr += 4) {
2027 nr = mread(adr, val, 4);
2028 if (nr == 0) {
2029 if (praddr) {
2030 const char *x = fault_chars[fault_type];
2031 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2033 break;
2035 inst = GETWORD(val);
2036 if (adr > first_adr && inst == last_inst) {
2037 if (!dotted) {
2038 printf(" ...\n");
2039 dotted = 1;
2041 continue;
2043 dotted = 0;
2044 last_inst = inst;
2045 if (praddr)
2046 printf(REG" %.8x", adr, inst);
2047 printf("\t");
2048 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2049 printf("\n");
2051 return adr - first_adr;
2054 void
2055 print_address(unsigned long addr)
2057 xmon_print_symbol(addr, "\t# ", "");
2062 * Memory operations - move, set, print differences
2064 static unsigned long mdest; /* destination address */
2065 static unsigned long msrc; /* source address */
2066 static unsigned long mval; /* byte value to set memory to */
2067 static unsigned long mcount; /* # bytes to affect */
2068 static unsigned long mdiffs; /* max # differences to print */
2070 void
2071 memops(int cmd)
2073 scanhex((void *)&mdest);
2074 if( termch != '\n' )
2075 termch = 0;
2076 scanhex((void *)(cmd == 's'? &mval: &msrc));
2077 if( termch != '\n' )
2078 termch = 0;
2079 scanhex((void *)&mcount);
2080 switch( cmd ){
2081 case 'm':
2082 memmove((void *)mdest, (void *)msrc, mcount);
2083 break;
2084 case 's':
2085 memset((void *)mdest, mval, mcount);
2086 break;
2087 case 'd':
2088 if( termch != '\n' )
2089 termch = 0;
2090 scanhex((void *)&mdiffs);
2091 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2092 break;
2096 void
2097 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2099 unsigned n, prt;
2101 prt = 0;
2102 for( n = nb; n > 0; --n )
2103 if( *p1++ != *p2++ )
2104 if( ++prt <= maxpr )
2105 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2106 p1[-1], p2 - 1, p2[-1]);
2107 if( prt > maxpr )
2108 printf("Total of %d differences\n", prt);
2111 static unsigned mend;
2112 static unsigned mask;
2114 void
2115 memlocate(void)
2117 unsigned a, n;
2118 unsigned char val[4];
2120 last_cmd = "ml";
2121 scanhex((void *)&mdest);
2122 if (termch != '\n') {
2123 termch = 0;
2124 scanhex((void *)&mend);
2125 if (termch != '\n') {
2126 termch = 0;
2127 scanhex((void *)&mval);
2128 mask = ~0;
2129 if (termch != '\n') termch = 0;
2130 scanhex((void *)&mask);
2133 n = 0;
2134 for (a = mdest; a < mend; a += 4) {
2135 if (mread(a, val, 4) == 4
2136 && ((GETWORD(val) ^ mval) & mask) == 0) {
2137 printf("%.16x: %.16x\n", a, GETWORD(val));
2138 if (++n >= 10)
2139 break;
2144 static unsigned long mskip = 0x1000;
2145 static unsigned long mlim = 0xffffffff;
2147 void
2148 memzcan(void)
2150 unsigned char v;
2151 unsigned a;
2152 int ok, ook;
2154 scanhex(&mdest);
2155 if (termch != '\n') termch = 0;
2156 scanhex(&mskip);
2157 if (termch != '\n') termch = 0;
2158 scanhex(&mlim);
2159 ook = 0;
2160 for (a = mdest; a < mlim; a += mskip) {
2161 ok = mread(a, &v, 1);
2162 if (ok && !ook) {
2163 printf("%.8x .. ", a);
2164 } else if (!ok && ook)
2165 printf("%.8x\n", a - mskip);
2166 ook = ok;
2167 if (a + mskip < a)
2168 break;
2170 if (ook)
2171 printf("%.8x\n", a - mskip);
2174 void proccall(void)
2176 unsigned long args[8];
2177 unsigned long ret;
2178 int i;
2179 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2180 unsigned long, unsigned long, unsigned long,
2181 unsigned long, unsigned long, unsigned long);
2182 callfunc_t func;
2184 if (!scanhex(&adrs))
2185 return;
2186 if (termch != '\n')
2187 termch = 0;
2188 for (i = 0; i < 8; ++i)
2189 args[i] = 0;
2190 for (i = 0; i < 8; ++i) {
2191 if (!scanhex(&args[i]) || termch == '\n')
2192 break;
2193 termch = 0;
2195 func = (callfunc_t) adrs;
2196 ret = 0;
2197 if (setjmp(bus_error_jmp) == 0) {
2198 catch_memory_errors = 1;
2199 sync();
2200 ret = func(args[0], args[1], args[2], args[3],
2201 args[4], args[5], args[6], args[7]);
2202 sync();
2203 printf("return value is %x\n", ret);
2204 } else {
2205 printf("*** %x exception occurred\n", fault_except);
2207 catch_memory_errors = 0;
2210 /* Input scanning routines */
2212 skipbl(void)
2214 int c;
2216 if( termch != 0 ){
2217 c = termch;
2218 termch = 0;
2219 } else
2220 c = inchar();
2221 while( c == ' ' || c == '\t' )
2222 c = inchar();
2223 return c;
2226 #define N_PTREGS 44
2227 static char *regnames[N_PTREGS] = {
2228 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2229 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2230 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2231 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2232 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2233 #ifdef CONFIG_PPC64
2234 "softe",
2235 #else
2236 "mq",
2237 #endif
2238 "trap", "dar", "dsisr", "res"
2242 scanhex(unsigned long *vp)
2244 int c, d;
2245 unsigned long v;
2247 c = skipbl();
2248 if (c == '%') {
2249 /* parse register name */
2250 char regname[8];
2251 int i;
2253 for (i = 0; i < sizeof(regname) - 1; ++i) {
2254 c = inchar();
2255 if (!isalnum(c)) {
2256 termch = c;
2257 break;
2259 regname[i] = c;
2261 regname[i] = 0;
2262 for (i = 0; i < N_PTREGS; ++i) {
2263 if (strcmp(regnames[i], regname) == 0) {
2264 if (xmon_regs == NULL) {
2265 printf("regs not available\n");
2266 return 0;
2268 *vp = ((unsigned long *)xmon_regs)[i];
2269 return 1;
2272 printf("invalid register name '%%%s'\n", regname);
2273 return 0;
2276 /* skip leading "0x" if any */
2278 if (c == '0') {
2279 c = inchar();
2280 if (c == 'x') {
2281 c = inchar();
2282 } else {
2283 d = hexdigit(c);
2284 if (d == EOF) {
2285 termch = c;
2286 *vp = 0;
2287 return 1;
2290 } else if (c == '$') {
2291 int i;
2292 for (i=0; i<63; i++) {
2293 c = inchar();
2294 if (isspace(c)) {
2295 termch = c;
2296 break;
2298 tmpstr[i] = c;
2300 tmpstr[i++] = 0;
2301 *vp = 0;
2302 if (setjmp(bus_error_jmp) == 0) {
2303 catch_memory_errors = 1;
2304 sync();
2305 *vp = kallsyms_lookup_name(tmpstr);
2306 sync();
2308 catch_memory_errors = 0;
2309 if (!(*vp)) {
2310 printf("unknown symbol '%s'\n", tmpstr);
2311 return 0;
2313 return 1;
2316 d = hexdigit(c);
2317 if (d == EOF) {
2318 termch = c;
2319 return 0;
2321 v = 0;
2322 do {
2323 v = (v << 4) + d;
2324 c = inchar();
2325 d = hexdigit(c);
2326 } while (d != EOF);
2327 termch = c;
2328 *vp = v;
2329 return 1;
2332 void
2333 scannl(void)
2335 int c;
2337 c = termch;
2338 termch = 0;
2339 while( c != '\n' )
2340 c = inchar();
2343 int hexdigit(int c)
2345 if( '0' <= c && c <= '9' )
2346 return c - '0';
2347 if( 'A' <= c && c <= 'F' )
2348 return c - ('A' - 10);
2349 if( 'a' <= c && c <= 'f' )
2350 return c - ('a' - 10);
2351 return EOF;
2354 void
2355 getstring(char *s, int size)
2357 int c;
2359 c = skipbl();
2360 do {
2361 if( size > 1 ){
2362 *s++ = c;
2363 --size;
2365 c = inchar();
2366 } while( c != ' ' && c != '\t' && c != '\n' );
2367 termch = c;
2368 *s = 0;
2371 static char line[256];
2372 static char *lineptr;
2374 void
2375 flush_input(void)
2377 lineptr = NULL;
2381 inchar(void)
2383 if (lineptr == NULL || *lineptr == 0) {
2384 if (xmon_gets(line, sizeof(line)) == NULL) {
2385 lineptr = NULL;
2386 return EOF;
2388 lineptr = line;
2390 return *lineptr++;
2393 void
2394 take_input(char *str)
2396 lineptr = str;
2400 static void
2401 symbol_lookup(void)
2403 int type = inchar();
2404 unsigned long addr;
2405 static char tmp[64];
2407 switch (type) {
2408 case 'a':
2409 if (scanhex(&addr))
2410 xmon_print_symbol(addr, ": ", "\n");
2411 termch = 0;
2412 break;
2413 case 's':
2414 getstring(tmp, 64);
2415 if (setjmp(bus_error_jmp) == 0) {
2416 catch_memory_errors = 1;
2417 sync();
2418 addr = kallsyms_lookup_name(tmp);
2419 if (addr)
2420 printf("%s: %lx\n", tmp, addr);
2421 else
2422 printf("Symbol '%s' not found.\n", tmp);
2423 sync();
2425 catch_memory_errors = 0;
2426 termch = 0;
2427 break;
2432 /* Print an address in numeric and symbolic form (if possible) */
2433 static void xmon_print_symbol(unsigned long address, const char *mid,
2434 const char *after)
2436 char *modname;
2437 const char *name = NULL;
2438 unsigned long offset, size;
2440 printf(REG, address);
2441 if (setjmp(bus_error_jmp) == 0) {
2442 catch_memory_errors = 1;
2443 sync();
2444 name = kallsyms_lookup(address, &size, &offset, &modname,
2445 tmpstr);
2446 sync();
2447 /* wait a little while to see if we get a machine check */
2448 __delay(200);
2451 catch_memory_errors = 0;
2453 if (name) {
2454 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2455 if (modname)
2456 printf(" [%s]", modname);
2458 printf("%s", after);
2461 #ifdef CONFIG_PPC64
2462 static void dump_slb(void)
2464 int i;
2465 unsigned long tmp;
2467 printf("SLB contents of cpu %x\n", smp_processor_id());
2469 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2470 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2471 printf("%02d %016lx ", i, tmp);
2473 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2474 printf("%016lx\n", tmp);
2478 static void dump_stab(void)
2480 int i;
2481 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2483 printf("Segment table contents of cpu %x\n", smp_processor_id());
2485 for (i = 0; i < PAGE_SIZE/16; i++) {
2486 unsigned long a, b;
2488 a = *tmp++;
2489 b = *tmp++;
2491 if (a || b) {
2492 printf("%03d %016lx ", i, a);
2493 printf("%016lx\n", b);
2498 void dump_segments(void)
2500 if (cpu_has_feature(CPU_FTR_SLB))
2501 dump_slb();
2502 else
2503 dump_stab();
2505 #endif
2507 #ifdef CONFIG_PPC_STD_MMU_32
2508 void dump_segments(void)
2510 int i;
2512 printf("sr0-15 =");
2513 for (i = 0; i < 16; ++i)
2514 printf(" %x", mfsrin(i));
2515 printf("\n");
2517 #endif
2519 void xmon_init(int enable)
2521 if (enable) {
2522 __debugger = xmon;
2523 __debugger_ipi = xmon_ipi;
2524 __debugger_bpt = xmon_bpt;
2525 __debugger_sstep = xmon_sstep;
2526 __debugger_iabr_match = xmon_iabr_match;
2527 __debugger_dabr_match = xmon_dabr_match;
2528 __debugger_fault_handler = xmon_fault_handler;
2529 } else {
2530 __debugger = NULL;
2531 __debugger_ipi = NULL;
2532 __debugger_bpt = NULL;
2533 __debugger_sstep = NULL;
2534 __debugger_iabr_match = NULL;
2535 __debugger_dabr_match = NULL;
2536 __debugger_fault_handler = NULL;
2538 xmon_map_scc();
2541 #ifdef CONFIG_MAGIC_SYSRQ
2542 static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2543 struct tty_struct *tty)
2545 /* ensure xmon is enabled */
2546 xmon_init(1);
2547 debugger(pt_regs);
2550 static struct sysrq_key_op sysrq_xmon_op =
2552 .handler = sysrq_handle_xmon,
2553 .help_msg = "Xmon",
2554 .action_msg = "Entering xmon",
2557 static int __init setup_xmon_sysrq(void)
2559 register_sysrq_key('x', &sysrq_xmon_op);
2560 return 0;
2562 __initcall(setup_xmon_sysrq);
2563 #endif /* CONFIG_MAGIC_SYSRQ */