[PATCH] powerpc: add a raw dump command to xmon
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / powerpc / xmon / xmon.c
blob4735b41c113c7d7814a1ecff82451cb69d2f05b2
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 dr dump stream of raw bytes\n\
195 e print exception information\n\
196 f flush cache\n\
197 la lookup symbol+offset of specified address\n\
198 ls lookup address of specified symbol\n\
199 m examine/change memory\n\
200 mm move a block of memory\n\
201 ms set a block of memory\n\
202 md compare two blocks of memory\n\
203 ml locate a block of memory\n\
204 mz zero a block of memory\n\
205 mi show information about memory allocation\n\
206 p call a procedure\n\
207 r print registers\n\
208 s single step\n\
209 S print special registers\n\
210 t print backtrace\n\
211 x exit monitor and recover\n\
212 X exit monitor and dont recover\n"
213 #ifdef CONFIG_PPC64
214 " u dump segment table or SLB\n"
215 #endif
216 #ifdef CONFIG_PPC_STD_MMU_32
217 " u dump segment registers\n"
218 #endif
219 " ? help\n"
220 " zr reboot\n\
221 zh halt\n"
224 static struct pt_regs *xmon_regs;
226 static inline void sync(void)
228 asm volatile("sync; isync");
231 static inline void store_inst(void *p)
233 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
236 static inline void cflush(void *p)
238 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
241 static inline void cinval(void *p)
243 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
247 * Disable surveillance (the service processor watchdog function)
248 * while we are in xmon.
249 * XXX we should re-enable it when we leave. :)
251 #define SURVEILLANCE_TOKEN 9000
253 static inline void disable_surveillance(void)
255 #ifdef CONFIG_PPC_PSERIES
256 /* Since this can't be a module, args should end up below 4GB. */
257 static struct rtas_args args;
260 * At this point we have got all the cpus we can into
261 * xmon, so there is hopefully no other cpu calling RTAS
262 * at the moment, even though we don't take rtas.lock.
263 * If we did try to take rtas.lock there would be a
264 * real possibility of deadlock.
266 args.token = rtas_token("set-indicator");
267 if (args.token == RTAS_UNKNOWN_SERVICE)
268 return;
269 args.nargs = 3;
270 args.nret = 1;
271 args.rets = &args.args[3];
272 args.args[0] = SURVEILLANCE_TOKEN;
273 args.args[1] = 0;
274 args.args[2] = 0;
275 enter_rtas(__pa(&args));
276 #endif /* CONFIG_PPC_PSERIES */
279 #ifdef CONFIG_SMP
280 static int xmon_speaker;
282 static void get_output_lock(void)
284 int me = smp_processor_id() + 0x100;
285 int last_speaker = 0, prev;
286 long timeout;
288 if (xmon_speaker == me)
289 return;
290 for (;;) {
291 if (xmon_speaker == 0) {
292 last_speaker = cmpxchg(&xmon_speaker, 0, me);
293 if (last_speaker == 0)
294 return;
296 timeout = 10000000;
297 while (xmon_speaker == last_speaker) {
298 if (--timeout > 0)
299 continue;
300 /* hostile takeover */
301 prev = cmpxchg(&xmon_speaker, last_speaker, me);
302 if (prev == last_speaker)
303 return;
304 break;
309 static void release_output_lock(void)
311 xmon_speaker = 0;
313 #endif
315 static int xmon_core(struct pt_regs *regs, int fromipi)
317 int cmd = 0;
318 unsigned long msr;
319 struct bpt *bp;
320 long recurse_jmp[JMP_BUF_LEN];
321 unsigned long offset;
322 #ifdef CONFIG_SMP
323 int cpu;
324 int secondary;
325 unsigned long timeout;
326 #endif
328 msr = mfmsr();
329 mtmsr(msr & ~MSR_EE); /* disable interrupts */
331 bp = in_breakpoint_table(regs->nip, &offset);
332 if (bp != NULL) {
333 regs->nip = bp->address + offset;
334 atomic_dec(&bp->ref_count);
337 remove_cpu_bpts();
339 #ifdef CONFIG_SMP
340 cpu = smp_processor_id();
341 if (cpu_isset(cpu, cpus_in_xmon)) {
342 get_output_lock();
343 excprint(regs);
344 printf("cpu 0x%x: Exception %lx %s in xmon, "
345 "returning to main loop\n",
346 cpu, regs->trap, getvecname(TRAP(regs)));
347 release_output_lock();
348 longjmp(xmon_fault_jmp[cpu], 1);
351 if (setjmp(recurse_jmp) != 0) {
352 if (!in_xmon || !xmon_gate) {
353 get_output_lock();
354 printf("xmon: WARNING: bad recursive fault "
355 "on cpu 0x%x\n", cpu);
356 release_output_lock();
357 goto waiting;
359 secondary = !(xmon_taken && cpu == xmon_owner);
360 goto cmdloop;
363 xmon_fault_jmp[cpu] = recurse_jmp;
364 cpu_set(cpu, cpus_in_xmon);
366 bp = NULL;
367 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
368 bp = at_breakpoint(regs->nip);
369 if (bp || (regs->msr & MSR_RI) == 0)
370 fromipi = 0;
372 if (!fromipi) {
373 get_output_lock();
374 excprint(regs);
375 if (bp) {
376 printf("cpu 0x%x stopped at breakpoint 0x%x (",
377 cpu, BP_NUM(bp));
378 xmon_print_symbol(regs->nip, " ", ")\n");
380 if ((regs->msr & MSR_RI) == 0)
381 printf("WARNING: exception is not recoverable, "
382 "can't continue\n");
383 release_output_lock();
386 waiting:
387 secondary = 1;
388 while (secondary && !xmon_gate) {
389 if (in_xmon == 0) {
390 if (fromipi)
391 goto leave;
392 secondary = test_and_set_bit(0, &in_xmon);
394 barrier();
397 if (!secondary && !xmon_gate) {
398 /* we are the first cpu to come in */
399 /* interrupt other cpu(s) */
400 int ncpus = num_online_cpus();
402 xmon_owner = cpu;
403 mb();
404 if (ncpus > 1) {
405 smp_send_debugger_break(MSG_ALL_BUT_SELF);
406 /* wait for other cpus to come in */
407 for (timeout = 100000000; timeout != 0; --timeout) {
408 if (cpus_weight(cpus_in_xmon) >= ncpus)
409 break;
410 barrier();
413 remove_bpts();
414 disable_surveillance();
415 /* for breakpoint or single step, print the current instr. */
416 if (bp || TRAP(regs) == 0xd00)
417 ppc_inst_dump(regs->nip, 1, 0);
418 printf("enter ? for help\n");
419 mb();
420 xmon_gate = 1;
421 barrier();
424 cmdloop:
425 while (in_xmon) {
426 if (secondary) {
427 if (cpu == xmon_owner) {
428 if (!test_and_set_bit(0, &xmon_taken)) {
429 secondary = 0;
430 continue;
432 /* missed it */
433 while (cpu == xmon_owner)
434 barrier();
436 barrier();
437 } else {
438 cmd = cmds(regs);
439 if (cmd != 0) {
440 /* exiting xmon */
441 insert_bpts();
442 xmon_gate = 0;
443 wmb();
444 in_xmon = 0;
445 break;
447 /* have switched to some other cpu */
448 secondary = 1;
451 leave:
452 cpu_clear(cpu, cpus_in_xmon);
453 xmon_fault_jmp[cpu] = NULL;
454 #else
455 /* UP is simple... */
456 if (in_xmon) {
457 printf("Exception %lx %s in xmon, returning to main loop\n",
458 regs->trap, getvecname(TRAP(regs)));
459 longjmp(xmon_fault_jmp[0], 1);
461 if (setjmp(recurse_jmp) == 0) {
462 xmon_fault_jmp[0] = recurse_jmp;
463 in_xmon = 1;
465 excprint(regs);
466 bp = at_breakpoint(regs->nip);
467 if (bp) {
468 printf("Stopped at breakpoint %x (", BP_NUM(bp));
469 xmon_print_symbol(regs->nip, " ", ")\n");
471 if ((regs->msr & MSR_RI) == 0)
472 printf("WARNING: exception is not recoverable, "
473 "can't continue\n");
474 remove_bpts();
475 disable_surveillance();
476 /* for breakpoint or single step, print the current instr. */
477 if (bp || TRAP(regs) == 0xd00)
478 ppc_inst_dump(regs->nip, 1, 0);
479 printf("enter ? for help\n");
482 cmd = cmds(regs);
484 insert_bpts();
485 in_xmon = 0;
486 #endif
488 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
489 bp = at_breakpoint(regs->nip);
490 if (bp != NULL) {
491 int stepped = emulate_step(regs, bp->instr[0]);
492 if (stepped == 0) {
493 regs->nip = (unsigned long) &bp->instr[0];
494 atomic_inc(&bp->ref_count);
495 } else if (stepped < 0) {
496 printf("Couldn't single-step %s instruction\n",
497 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
502 insert_cpu_bpts();
504 mtmsr(msr); /* restore interrupt enable */
506 return cmd != 'X';
509 int xmon(struct pt_regs *excp)
511 struct pt_regs regs;
513 if (excp == NULL) {
514 xmon_save_regs(&regs);
515 excp = &regs;
517 return xmon_core(excp, 0);
519 EXPORT_SYMBOL(xmon);
521 irqreturn_t
522 xmon_irq(int irq, void *d, struct pt_regs *regs)
524 unsigned long flags;
525 local_irq_save(flags);
526 printf("Keyboard interrupt\n");
527 xmon(regs);
528 local_irq_restore(flags);
529 return IRQ_HANDLED;
532 static int xmon_bpt(struct pt_regs *regs)
534 struct bpt *bp;
535 unsigned long offset;
537 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
538 return 0;
540 /* Are we at the trap at bp->instr[1] for some bp? */
541 bp = in_breakpoint_table(regs->nip, &offset);
542 if (bp != NULL && offset == 4) {
543 regs->nip = bp->address + 4;
544 atomic_dec(&bp->ref_count);
545 return 1;
548 /* Are we at a breakpoint? */
549 bp = at_breakpoint(regs->nip);
550 if (!bp)
551 return 0;
553 xmon_core(regs, 0);
555 return 1;
558 static int xmon_sstep(struct pt_regs *regs)
560 if (user_mode(regs))
561 return 0;
562 xmon_core(regs, 0);
563 return 1;
566 static int xmon_dabr_match(struct pt_regs *regs)
568 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
569 return 0;
570 if (dabr.enabled == 0)
571 return 0;
572 xmon_core(regs, 0);
573 return 1;
576 static int xmon_iabr_match(struct pt_regs *regs)
578 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
579 return 0;
580 if (iabr == 0)
581 return 0;
582 xmon_core(regs, 0);
583 return 1;
586 static int xmon_ipi(struct pt_regs *regs)
588 #ifdef CONFIG_SMP
589 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
590 xmon_core(regs, 1);
591 #endif
592 return 0;
595 static int xmon_fault_handler(struct pt_regs *regs)
597 struct bpt *bp;
598 unsigned long offset;
600 if (in_xmon && catch_memory_errors)
601 handle_fault(regs); /* doesn't return */
603 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
604 bp = in_breakpoint_table(regs->nip, &offset);
605 if (bp != NULL) {
606 regs->nip = bp->address + offset;
607 atomic_dec(&bp->ref_count);
611 return 0;
614 static struct bpt *at_breakpoint(unsigned long pc)
616 int i;
617 struct bpt *bp;
619 bp = bpts;
620 for (i = 0; i < NBPTS; ++i, ++bp)
621 if (bp->enabled && pc == bp->address)
622 return bp;
623 return NULL;
626 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
628 unsigned long off;
630 off = nip - (unsigned long) bpts;
631 if (off >= sizeof(bpts))
632 return NULL;
633 off %= sizeof(struct bpt);
634 if (off != offsetof(struct bpt, instr[0])
635 && off != offsetof(struct bpt, instr[1]))
636 return NULL;
637 *offp = off - offsetof(struct bpt, instr[0]);
638 return (struct bpt *) (nip - off);
641 static struct bpt *new_breakpoint(unsigned long a)
643 struct bpt *bp;
645 a &= ~3UL;
646 bp = at_breakpoint(a);
647 if (bp)
648 return bp;
650 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
651 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
652 bp->address = a;
653 bp->instr[1] = bpinstr;
654 store_inst(&bp->instr[1]);
655 return bp;
659 printf("Sorry, no free breakpoints. Please clear one first.\n");
660 return NULL;
663 static void insert_bpts(void)
665 int i;
666 struct bpt *bp;
668 bp = bpts;
669 for (i = 0; i < NBPTS; ++i, ++bp) {
670 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
671 continue;
672 if (mread(bp->address, &bp->instr[0], 4) != 4) {
673 printf("Couldn't read instruction at %lx, "
674 "disabling breakpoint there\n", bp->address);
675 bp->enabled = 0;
676 continue;
678 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
679 printf("Breakpoint at %lx is on an mtmsrd or rfid "
680 "instruction, disabling it\n", bp->address);
681 bp->enabled = 0;
682 continue;
684 store_inst(&bp->instr[0]);
685 if (bp->enabled & BP_IABR)
686 continue;
687 if (mwrite(bp->address, &bpinstr, 4) != 4) {
688 printf("Couldn't write instruction at %lx, "
689 "disabling breakpoint there\n", bp->address);
690 bp->enabled &= ~BP_TRAP;
691 continue;
693 store_inst((void *)bp->address);
697 static void insert_cpu_bpts(void)
699 if (dabr.enabled)
700 set_dabr(dabr.address | (dabr.enabled & 7));
701 if (iabr && cpu_has_feature(CPU_FTR_IABR))
702 mtspr(SPRN_IABR, iabr->address
703 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
706 static void remove_bpts(void)
708 int i;
709 struct bpt *bp;
710 unsigned instr;
712 bp = bpts;
713 for (i = 0; i < NBPTS; ++i, ++bp) {
714 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
715 continue;
716 if (mread(bp->address, &instr, 4) == 4
717 && instr == bpinstr
718 && mwrite(bp->address, &bp->instr, 4) != 4)
719 printf("Couldn't remove breakpoint at %lx\n",
720 bp->address);
721 else
722 store_inst((void *)bp->address);
726 static void remove_cpu_bpts(void)
728 set_dabr(0);
729 if (cpu_has_feature(CPU_FTR_IABR))
730 mtspr(SPRN_IABR, 0);
733 /* Command interpreting routine */
734 static char *last_cmd;
736 static int
737 cmds(struct pt_regs *excp)
739 int cmd = 0;
741 last_cmd = NULL;
742 xmon_regs = excp;
743 for(;;) {
744 #ifdef CONFIG_SMP
745 printf("%x:", smp_processor_id());
746 #endif /* CONFIG_SMP */
747 printf("mon> ");
748 flush_input();
749 termch = 0;
750 cmd = skipbl();
751 if( cmd == '\n' ) {
752 if (last_cmd == NULL)
753 continue;
754 take_input(last_cmd);
755 last_cmd = NULL;
756 cmd = inchar();
758 switch (cmd) {
759 case 'm':
760 cmd = inchar();
761 switch (cmd) {
762 case 'm':
763 case 's':
764 case 'd':
765 memops(cmd);
766 break;
767 case 'l':
768 memlocate();
769 break;
770 case 'z':
771 memzcan();
772 break;
773 case 'i':
774 show_mem();
775 break;
776 default:
777 termch = cmd;
778 memex();
780 break;
781 case 'd':
782 dump();
783 break;
784 case 'l':
785 symbol_lookup();
786 break;
787 case 'r':
788 prregs(excp); /* print regs */
789 break;
790 case 'e':
791 excprint(excp);
792 break;
793 case 'S':
794 super_regs();
795 break;
796 case 't':
797 backtrace(excp);
798 break;
799 case 'f':
800 cacheflush();
801 break;
802 case 's':
803 if (do_step(excp))
804 return cmd;
805 break;
806 case 'x':
807 case 'X':
808 return cmd;
809 case EOF:
810 printf(" <no input ...>\n");
811 mdelay(2000);
812 return cmd;
813 case '?':
814 printf(help_string);
815 break;
816 case 'b':
817 bpt_cmds();
818 break;
819 case 'C':
820 csum();
821 break;
822 case 'c':
823 if (cpu_cmd())
824 return 0;
825 break;
826 case 'z':
827 bootcmds();
828 break;
829 case 'p':
830 proccall();
831 break;
832 #ifdef CONFIG_PPC_STD_MMU
833 case 'u':
834 dump_segments();
835 break;
836 #endif
837 default:
838 printf("Unrecognized command: ");
839 do {
840 if (' ' < cmd && cmd <= '~')
841 putchar(cmd);
842 else
843 printf("\\x%x", cmd);
844 cmd = inchar();
845 } while (cmd != '\n');
846 printf(" (type ? for help)\n");
847 break;
853 * Step a single instruction.
854 * Some instructions we emulate, others we execute with MSR_SE set.
856 static int do_step(struct pt_regs *regs)
858 unsigned int instr;
859 int stepped;
861 /* check we are in 64-bit kernel mode, translation enabled */
862 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
863 if (mread(regs->nip, &instr, 4) == 4) {
864 stepped = emulate_step(regs, instr);
865 if (stepped < 0) {
866 printf("Couldn't single-step %s instruction\n",
867 (IS_RFID(instr)? "rfid": "mtmsrd"));
868 return 0;
870 if (stepped > 0) {
871 regs->trap = 0xd00 | (regs->trap & 1);
872 printf("stepped to ");
873 xmon_print_symbol(regs->nip, " ", "\n");
874 ppc_inst_dump(regs->nip, 1, 0);
875 return 0;
879 regs->msr |= MSR_SE;
880 return 1;
883 static void bootcmds(void)
885 int cmd;
887 cmd = inchar();
888 if (cmd == 'r')
889 ppc_md.restart(NULL);
890 else if (cmd == 'h')
891 ppc_md.halt();
892 else if (cmd == 'p')
893 ppc_md.power_off();
896 static int cpu_cmd(void)
898 #ifdef CONFIG_SMP
899 unsigned long cpu;
900 int timeout;
901 int count;
903 if (!scanhex(&cpu)) {
904 /* print cpus waiting or in xmon */
905 printf("cpus stopped:");
906 count = 0;
907 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
908 if (cpu_isset(cpu, cpus_in_xmon)) {
909 if (count == 0)
910 printf(" %x", cpu);
911 ++count;
912 } else {
913 if (count > 1)
914 printf("-%x", cpu - 1);
915 count = 0;
918 if (count > 1)
919 printf("-%x", NR_CPUS - 1);
920 printf("\n");
921 return 0;
923 /* try to switch to cpu specified */
924 if (!cpu_isset(cpu, cpus_in_xmon)) {
925 printf("cpu 0x%x isn't in xmon\n", cpu);
926 return 0;
928 xmon_taken = 0;
929 mb();
930 xmon_owner = cpu;
931 timeout = 10000000;
932 while (!xmon_taken) {
933 if (--timeout == 0) {
934 if (test_and_set_bit(0, &xmon_taken))
935 break;
936 /* take control back */
937 mb();
938 xmon_owner = smp_processor_id();
939 printf("cpu %u didn't take control\n", cpu);
940 return 0;
942 barrier();
944 return 1;
945 #else
946 return 0;
947 #endif /* CONFIG_SMP */
950 static unsigned short fcstab[256] = {
951 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
952 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
953 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
954 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
955 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
956 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
957 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
958 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
959 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
960 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
961 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
962 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
963 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
964 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
965 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
966 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
967 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
968 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
969 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
970 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
971 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
972 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
973 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
974 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
975 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
976 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
977 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
978 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
979 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
980 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
981 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
982 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
985 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
987 static void
988 csum(void)
990 unsigned int i;
991 unsigned short fcs;
992 unsigned char v;
994 if (!scanhex(&adrs))
995 return;
996 if (!scanhex(&ncsum))
997 return;
998 fcs = 0xffff;
999 for (i = 0; i < ncsum; ++i) {
1000 if (mread(adrs+i, &v, 1) == 0) {
1001 printf("csum stopped at %x\n", adrs+i);
1002 break;
1004 fcs = FCS(fcs, v);
1006 printf("%x\n", fcs);
1010 * Check if this is a suitable place to put a breakpoint.
1012 static long check_bp_loc(unsigned long addr)
1014 unsigned int instr;
1016 addr &= ~3;
1017 if (!is_kernel_addr(addr)) {
1018 printf("Breakpoints may only be placed at kernel addresses\n");
1019 return 0;
1021 if (!mread(addr, &instr, sizeof(instr))) {
1022 printf("Can't read instruction at address %lx\n", addr);
1023 return 0;
1025 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1026 printf("Breakpoints may not be placed on mtmsrd or rfid "
1027 "instructions\n");
1028 return 0;
1030 return 1;
1033 static char *breakpoint_help_string =
1034 "Breakpoint command usage:\n"
1035 "b show breakpoints\n"
1036 "b <addr> [cnt] set breakpoint at given instr addr\n"
1037 "bc clear all breakpoints\n"
1038 "bc <n/addr> clear breakpoint number n or at addr\n"
1039 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1040 "bd <addr> [cnt] set hardware data breakpoint\n"
1043 static void
1044 bpt_cmds(void)
1046 int cmd;
1047 unsigned long a;
1048 int mode, i;
1049 struct bpt *bp;
1050 const char badaddr[] = "Only kernel addresses are permitted "
1051 "for breakpoints\n";
1053 cmd = inchar();
1054 switch (cmd) {
1055 #ifndef CONFIG_8xx
1056 case 'd': /* bd - hardware data breakpoint */
1057 mode = 7;
1058 cmd = inchar();
1059 if (cmd == 'r')
1060 mode = 5;
1061 else if (cmd == 'w')
1062 mode = 6;
1063 else
1064 termch = cmd;
1065 dabr.address = 0;
1066 dabr.enabled = 0;
1067 if (scanhex(&dabr.address)) {
1068 if (!is_kernel_addr(dabr.address)) {
1069 printf(badaddr);
1070 break;
1072 dabr.address &= ~7;
1073 dabr.enabled = mode | BP_DABR;
1075 break;
1077 case 'i': /* bi - hardware instr breakpoint */
1078 if (!cpu_has_feature(CPU_FTR_IABR)) {
1079 printf("Hardware instruction breakpoint "
1080 "not supported on this cpu\n");
1081 break;
1083 if (iabr) {
1084 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1085 iabr = NULL;
1087 if (!scanhex(&a))
1088 break;
1089 if (!check_bp_loc(a))
1090 break;
1091 bp = new_breakpoint(a);
1092 if (bp != NULL) {
1093 bp->enabled |= BP_IABR | BP_IABR_TE;
1094 iabr = bp;
1096 break;
1097 #endif
1099 case 'c':
1100 if (!scanhex(&a)) {
1101 /* clear all breakpoints */
1102 for (i = 0; i < NBPTS; ++i)
1103 bpts[i].enabled = 0;
1104 iabr = NULL;
1105 dabr.enabled = 0;
1106 printf("All breakpoints cleared\n");
1107 break;
1110 if (a <= NBPTS && a >= 1) {
1111 /* assume a breakpoint number */
1112 bp = &bpts[a-1]; /* bp nums are 1 based */
1113 } else {
1114 /* assume a breakpoint address */
1115 bp = at_breakpoint(a);
1116 if (bp == 0) {
1117 printf("No breakpoint at %x\n", a);
1118 break;
1122 printf("Cleared breakpoint %x (", BP_NUM(bp));
1123 xmon_print_symbol(bp->address, " ", ")\n");
1124 bp->enabled = 0;
1125 break;
1127 default:
1128 termch = cmd;
1129 cmd = skipbl();
1130 if (cmd == '?') {
1131 printf(breakpoint_help_string);
1132 break;
1134 termch = cmd;
1135 if (!scanhex(&a)) {
1136 /* print all breakpoints */
1137 printf(" type address\n");
1138 if (dabr.enabled) {
1139 printf(" data "REG" [", dabr.address);
1140 if (dabr.enabled & 1)
1141 printf("r");
1142 if (dabr.enabled & 2)
1143 printf("w");
1144 printf("]\n");
1146 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1147 if (!bp->enabled)
1148 continue;
1149 printf("%2x %s ", BP_NUM(bp),
1150 (bp->enabled & BP_IABR)? "inst": "trap");
1151 xmon_print_symbol(bp->address, " ", "\n");
1153 break;
1156 if (!check_bp_loc(a))
1157 break;
1158 bp = new_breakpoint(a);
1159 if (bp != NULL)
1160 bp->enabled |= BP_TRAP;
1161 break;
1165 /* Very cheap human name for vector lookup. */
1166 static
1167 const char *getvecname(unsigned long vec)
1169 char *ret;
1171 switch (vec) {
1172 case 0x100: ret = "(System Reset)"; break;
1173 case 0x200: ret = "(Machine Check)"; break;
1174 case 0x300: ret = "(Data Access)"; break;
1175 case 0x380: ret = "(Data SLB Access)"; break;
1176 case 0x400: ret = "(Instruction Access)"; break;
1177 case 0x480: ret = "(Instruction SLB Access)"; break;
1178 case 0x500: ret = "(Hardware Interrupt)"; break;
1179 case 0x600: ret = "(Alignment)"; break;
1180 case 0x700: ret = "(Program Check)"; break;
1181 case 0x800: ret = "(FPU Unavailable)"; break;
1182 case 0x900: ret = "(Decrementer)"; break;
1183 case 0xc00: ret = "(System Call)"; break;
1184 case 0xd00: ret = "(Single Step)"; break;
1185 case 0xf00: ret = "(Performance Monitor)"; break;
1186 case 0xf20: ret = "(Altivec Unavailable)"; break;
1187 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1188 default: ret = "";
1190 return ret;
1193 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1194 unsigned long *endp)
1196 unsigned long size, offset;
1197 const char *name;
1198 char *modname;
1200 *startp = *endp = 0;
1201 if (pc == 0)
1202 return;
1203 if (setjmp(bus_error_jmp) == 0) {
1204 catch_memory_errors = 1;
1205 sync();
1206 name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
1207 if (name != NULL) {
1208 *startp = pc - offset;
1209 *endp = pc - offset + size;
1211 sync();
1213 catch_memory_errors = 0;
1216 static int xmon_depth_to_print = 64;
1218 #ifdef CONFIG_PPC64
1219 #define LRSAVE_OFFSET 0x10
1220 #define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
1221 #define MARKER_OFFSET 0x60
1222 #define REGS_OFFSET 0x70
1223 #else
1224 #define LRSAVE_OFFSET 4
1225 #define REG_FRAME_MARKER 0x72656773
1226 #define MARKER_OFFSET 8
1227 #define REGS_OFFSET 16
1228 #endif
1230 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1231 unsigned long pc)
1233 unsigned long ip;
1234 unsigned long newsp;
1235 unsigned long marker;
1236 int count = 0;
1237 struct pt_regs regs;
1239 do {
1240 if (sp < PAGE_OFFSET) {
1241 if (sp != 0)
1242 printf("SP (%lx) is in userspace\n", sp);
1243 break;
1246 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1247 || !mread(sp, &newsp, sizeof(unsigned long))) {
1248 printf("Couldn't read stack frame at %lx\n", sp);
1249 break;
1253 * For the first stack frame, try to work out if
1254 * LR and/or the saved LR value in the bottommost
1255 * stack frame are valid.
1257 if ((pc | lr) != 0) {
1258 unsigned long fnstart, fnend;
1259 unsigned long nextip;
1260 int printip = 1;
1262 get_function_bounds(pc, &fnstart, &fnend);
1263 nextip = 0;
1264 if (newsp > sp)
1265 mread(newsp + LRSAVE_OFFSET, &nextip,
1266 sizeof(unsigned long));
1267 if (lr == ip) {
1268 if (lr < PAGE_OFFSET
1269 || (fnstart <= lr && lr < fnend))
1270 printip = 0;
1271 } else if (lr == nextip) {
1272 printip = 0;
1273 } else if (lr >= PAGE_OFFSET
1274 && !(fnstart <= lr && lr < fnend)) {
1275 printf("[link register ] ");
1276 xmon_print_symbol(lr, " ", "\n");
1278 if (printip) {
1279 printf("["REG"] ", sp);
1280 xmon_print_symbol(ip, " ", " (unreliable)\n");
1282 pc = lr = 0;
1284 } else {
1285 printf("["REG"] ", sp);
1286 xmon_print_symbol(ip, " ", "\n");
1289 /* Look for "regshere" marker to see if this is
1290 an exception frame. */
1291 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1292 && marker == REG_FRAME_MARKER) {
1293 if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
1294 != sizeof(regs)) {
1295 printf("Couldn't read registers at %lx\n",
1296 sp + REGS_OFFSET);
1297 break;
1299 printf("--- Exception: %lx %s at ", regs.trap,
1300 getvecname(TRAP(&regs)));
1301 pc = regs.nip;
1302 lr = regs.link;
1303 xmon_print_symbol(pc, " ", "\n");
1306 if (newsp == 0)
1307 break;
1309 sp = newsp;
1310 } while (count++ < xmon_depth_to_print);
1313 static void backtrace(struct pt_regs *excp)
1315 unsigned long sp;
1317 if (scanhex(&sp))
1318 xmon_show_stack(sp, 0, 0);
1319 else
1320 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1321 scannl();
1324 static void print_bug_trap(struct pt_regs *regs)
1326 struct bug_entry *bug;
1327 unsigned long addr;
1329 if (regs->msr & MSR_PR)
1330 return; /* not in kernel */
1331 addr = regs->nip; /* address of trap instruction */
1332 if (addr < PAGE_OFFSET)
1333 return;
1334 bug = find_bug(regs->nip);
1335 if (bug == NULL)
1336 return;
1337 if (bug->line & BUG_WARNING_TRAP)
1338 return;
1340 printf("kernel BUG in %s at %s:%d!\n",
1341 bug->function, bug->file, (unsigned int)bug->line);
1344 void excprint(struct pt_regs *fp)
1346 unsigned long trap;
1348 #ifdef CONFIG_SMP
1349 printf("cpu 0x%x: ", smp_processor_id());
1350 #endif /* CONFIG_SMP */
1352 trap = TRAP(fp);
1353 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1354 printf(" pc: ");
1355 xmon_print_symbol(fp->nip, ": ", "\n");
1357 printf(" lr: ", fp->link);
1358 xmon_print_symbol(fp->link, ": ", "\n");
1360 printf(" sp: %lx\n", fp->gpr[1]);
1361 printf(" msr: %lx\n", fp->msr);
1363 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1364 printf(" dar: %lx\n", fp->dar);
1365 if (trap != 0x380)
1366 printf(" dsisr: %lx\n", fp->dsisr);
1369 printf(" current = 0x%lx\n", current);
1370 #ifdef CONFIG_PPC64
1371 printf(" paca = 0x%lx\n", get_paca());
1372 #endif
1373 if (current) {
1374 printf(" pid = %ld, comm = %s\n",
1375 current->pid, current->comm);
1378 if (trap == 0x700)
1379 print_bug_trap(fp);
1382 void prregs(struct pt_regs *fp)
1384 int n, trap;
1385 unsigned long base;
1386 struct pt_regs regs;
1388 if (scanhex(&base)) {
1389 if (setjmp(bus_error_jmp) == 0) {
1390 catch_memory_errors = 1;
1391 sync();
1392 regs = *(struct pt_regs *)base;
1393 sync();
1394 __delay(200);
1395 } else {
1396 catch_memory_errors = 0;
1397 printf("*** Error reading registers from "REG"\n",
1398 base);
1399 return;
1401 catch_memory_errors = 0;
1402 fp = &regs;
1405 #ifdef CONFIG_PPC64
1406 if (FULL_REGS(fp)) {
1407 for (n = 0; n < 16; ++n)
1408 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1409 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1410 } else {
1411 for (n = 0; n < 7; ++n)
1412 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1413 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1415 #else
1416 for (n = 0; n < 32; ++n) {
1417 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1418 (n & 3) == 3? "\n": " ");
1419 if (n == 12 && !FULL_REGS(fp)) {
1420 printf("\n");
1421 break;
1424 #endif
1425 printf("pc = ");
1426 xmon_print_symbol(fp->nip, " ", "\n");
1427 printf("lr = ");
1428 xmon_print_symbol(fp->link, " ", "\n");
1429 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1430 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1431 fp->ctr, fp->xer, fp->trap);
1432 trap = TRAP(fp);
1433 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1434 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1437 void cacheflush(void)
1439 int cmd;
1440 unsigned long nflush;
1442 cmd = inchar();
1443 if (cmd != 'i')
1444 termch = cmd;
1445 scanhex((void *)&adrs);
1446 if (termch != '\n')
1447 termch = 0;
1448 nflush = 1;
1449 scanhex(&nflush);
1450 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1451 if (setjmp(bus_error_jmp) == 0) {
1452 catch_memory_errors = 1;
1453 sync();
1455 if (cmd != 'i') {
1456 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1457 cflush((void *) adrs);
1458 } else {
1459 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1460 cinval((void *) adrs);
1462 sync();
1463 /* wait a little while to see if we get a machine check */
1464 __delay(200);
1466 catch_memory_errors = 0;
1469 unsigned long
1470 read_spr(int n)
1472 unsigned int instrs[2];
1473 unsigned long (*code)(void);
1474 unsigned long ret = -1UL;
1475 #ifdef CONFIG_PPC64
1476 unsigned long opd[3];
1478 opd[0] = (unsigned long)instrs;
1479 opd[1] = 0;
1480 opd[2] = 0;
1481 code = (unsigned long (*)(void)) opd;
1482 #else
1483 code = (unsigned long (*)(void)) instrs;
1484 #endif
1486 /* mfspr r3,n; blr */
1487 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1488 instrs[1] = 0x4e800020;
1489 store_inst(instrs);
1490 store_inst(instrs+1);
1492 if (setjmp(bus_error_jmp) == 0) {
1493 catch_memory_errors = 1;
1494 sync();
1496 ret = code();
1498 sync();
1499 /* wait a little while to see if we get a machine check */
1500 __delay(200);
1501 n = size;
1504 return ret;
1507 void
1508 write_spr(int n, unsigned long val)
1510 unsigned int instrs[2];
1511 unsigned long (*code)(unsigned long);
1512 #ifdef CONFIG_PPC64
1513 unsigned long opd[3];
1515 opd[0] = (unsigned long)instrs;
1516 opd[1] = 0;
1517 opd[2] = 0;
1518 code = (unsigned long (*)(unsigned long)) opd;
1519 #else
1520 code = (unsigned long (*)(unsigned long)) instrs;
1521 #endif
1523 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1524 instrs[1] = 0x4e800020;
1525 store_inst(instrs);
1526 store_inst(instrs+1);
1528 if (setjmp(bus_error_jmp) == 0) {
1529 catch_memory_errors = 1;
1530 sync();
1532 code(val);
1534 sync();
1535 /* wait a little while to see if we get a machine check */
1536 __delay(200);
1537 n = size;
1541 static unsigned long regno;
1542 extern char exc_prolog;
1543 extern char dec_exc;
1545 void super_regs(void)
1547 int cmd;
1548 unsigned long val;
1549 #ifdef CONFIG_PPC_ISERIES
1550 struct paca_struct *ptrPaca = NULL;
1551 struct lppaca *ptrLpPaca = NULL;
1552 struct ItLpRegSave *ptrLpRegSave = NULL;
1553 #endif
1555 cmd = skipbl();
1556 if (cmd == '\n') {
1557 unsigned long sp, toc;
1558 asm("mr %0,1" : "=r" (sp) :);
1559 asm("mr %0,2" : "=r" (toc) :);
1561 printf("msr = "REG" sprg0= "REG"\n",
1562 mfmsr(), mfspr(SPRN_SPRG0));
1563 printf("pvr = "REG" sprg1= "REG"\n",
1564 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1565 printf("dec = "REG" sprg2= "REG"\n",
1566 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1567 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1568 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1569 #ifdef CONFIG_PPC_ISERIES
1570 // Dump out relevant Paca data areas.
1571 printf("Paca: \n");
1572 ptrPaca = get_paca();
1574 printf(" Local Processor Control Area (LpPaca): \n");
1575 ptrLpPaca = ptrPaca->lppaca_ptr;
1576 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1577 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1578 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1579 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1580 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1582 printf(" Local Processor Register Save Area (LpRegSave): \n");
1583 ptrLpRegSave = ptrPaca->reg_save_ptr;
1584 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1585 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1586 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1587 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1588 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1589 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1590 #endif
1592 return;
1595 scanhex(&regno);
1596 switch (cmd) {
1597 case 'w':
1598 val = read_spr(regno);
1599 scanhex(&val);
1600 write_spr(regno, val);
1601 /* fall through */
1602 case 'r':
1603 printf("spr %lx = %lx\n", regno, read_spr(regno));
1604 break;
1606 scannl();
1610 * Stuff for reading and writing memory safely
1613 mread(unsigned long adrs, void *buf, int size)
1615 volatile int n;
1616 char *p, *q;
1618 n = 0;
1619 if (setjmp(bus_error_jmp) == 0) {
1620 catch_memory_errors = 1;
1621 sync();
1622 p = (char *)adrs;
1623 q = (char *)buf;
1624 switch (size) {
1625 case 2:
1626 *(u16 *)q = *(u16 *)p;
1627 break;
1628 case 4:
1629 *(u32 *)q = *(u32 *)p;
1630 break;
1631 case 8:
1632 *(u64 *)q = *(u64 *)p;
1633 break;
1634 default:
1635 for( ; n < size; ++n) {
1636 *q++ = *p++;
1637 sync();
1640 sync();
1641 /* wait a little while to see if we get a machine check */
1642 __delay(200);
1643 n = size;
1645 catch_memory_errors = 0;
1646 return n;
1650 mwrite(unsigned long adrs, void *buf, int size)
1652 volatile int n;
1653 char *p, *q;
1655 n = 0;
1656 if (setjmp(bus_error_jmp) == 0) {
1657 catch_memory_errors = 1;
1658 sync();
1659 p = (char *) adrs;
1660 q = (char *) buf;
1661 switch (size) {
1662 case 2:
1663 *(u16 *)p = *(u16 *)q;
1664 break;
1665 case 4:
1666 *(u32 *)p = *(u32 *)q;
1667 break;
1668 case 8:
1669 *(u64 *)p = *(u64 *)q;
1670 break;
1671 default:
1672 for ( ; n < size; ++n) {
1673 *p++ = *q++;
1674 sync();
1677 sync();
1678 /* wait a little while to see if we get a machine check */
1679 __delay(200);
1680 n = size;
1681 } else {
1682 printf("*** Error writing address %x\n", adrs + n);
1684 catch_memory_errors = 0;
1685 return n;
1688 static int fault_type;
1689 static int fault_except;
1690 static char *fault_chars[] = { "--", "**", "##" };
1692 static int handle_fault(struct pt_regs *regs)
1694 fault_except = TRAP(regs);
1695 switch (TRAP(regs)) {
1696 case 0x200:
1697 fault_type = 0;
1698 break;
1699 case 0x300:
1700 case 0x380:
1701 fault_type = 1;
1702 break;
1703 default:
1704 fault_type = 2;
1707 longjmp(bus_error_jmp, 1);
1709 return 0;
1712 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1714 void
1715 byterev(unsigned char *val, int size)
1717 int t;
1719 switch (size) {
1720 case 2:
1721 SWAP(val[0], val[1], t);
1722 break;
1723 case 4:
1724 SWAP(val[0], val[3], t);
1725 SWAP(val[1], val[2], t);
1726 break;
1727 case 8: /* is there really any use for this? */
1728 SWAP(val[0], val[7], t);
1729 SWAP(val[1], val[6], t);
1730 SWAP(val[2], val[5], t);
1731 SWAP(val[3], val[4], t);
1732 break;
1736 static int brev;
1737 static int mnoread;
1739 static char *memex_help_string =
1740 "Memory examine command usage:\n"
1741 "m [addr] [flags] examine/change memory\n"
1742 " addr is optional. will start where left off.\n"
1743 " flags may include chars from this set:\n"
1744 " b modify by bytes (default)\n"
1745 " w modify by words (2 byte)\n"
1746 " l modify by longs (4 byte)\n"
1747 " d modify by doubleword (8 byte)\n"
1748 " r toggle reverse byte order mode\n"
1749 " n do not read memory (for i/o spaces)\n"
1750 " . ok to read (default)\n"
1751 "NOTE: flags are saved as defaults\n"
1754 static char *memex_subcmd_help_string =
1755 "Memory examine subcommands:\n"
1756 " hexval write this val to current location\n"
1757 " 'string' write chars from string to this location\n"
1758 " ' increment address\n"
1759 " ^ decrement address\n"
1760 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1761 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1762 " ` clear no-read flag\n"
1763 " ; stay at this addr\n"
1764 " v change to byte mode\n"
1765 " w change to word (2 byte) mode\n"
1766 " l change to long (4 byte) mode\n"
1767 " u change to doubleword (8 byte) mode\n"
1768 " m addr change current addr\n"
1769 " n toggle no-read flag\n"
1770 " r toggle byte reverse flag\n"
1771 " < count back up count bytes\n"
1772 " > count skip forward count bytes\n"
1773 " x exit this mode\n"
1776 void
1777 memex(void)
1779 int cmd, inc, i, nslash;
1780 unsigned long n;
1781 unsigned char val[16];
1783 scanhex((void *)&adrs);
1784 cmd = skipbl();
1785 if (cmd == '?') {
1786 printf(memex_help_string);
1787 return;
1788 } else {
1789 termch = cmd;
1791 last_cmd = "m\n";
1792 while ((cmd = skipbl()) != '\n') {
1793 switch( cmd ){
1794 case 'b': size = 1; break;
1795 case 'w': size = 2; break;
1796 case 'l': size = 4; break;
1797 case 'd': size = 8; break;
1798 case 'r': brev = !brev; break;
1799 case 'n': mnoread = 1; break;
1800 case '.': mnoread = 0; break;
1803 if( size <= 0 )
1804 size = 1;
1805 else if( size > 8 )
1806 size = 8;
1807 for(;;){
1808 if (!mnoread)
1809 n = mread(adrs, val, size);
1810 printf(REG"%c", adrs, brev? 'r': ' ');
1811 if (!mnoread) {
1812 if (brev)
1813 byterev(val, size);
1814 putchar(' ');
1815 for (i = 0; i < n; ++i)
1816 printf("%.2x", val[i]);
1817 for (; i < size; ++i)
1818 printf("%s", fault_chars[fault_type]);
1820 putchar(' ');
1821 inc = size;
1822 nslash = 0;
1823 for(;;){
1824 if( scanhex(&n) ){
1825 for (i = 0; i < size; ++i)
1826 val[i] = n >> (i * 8);
1827 if (!brev)
1828 byterev(val, size);
1829 mwrite(adrs, val, size);
1830 inc = size;
1832 cmd = skipbl();
1833 if (cmd == '\n')
1834 break;
1835 inc = 0;
1836 switch (cmd) {
1837 case '\'':
1838 for(;;){
1839 n = inchar();
1840 if( n == '\\' )
1841 n = bsesc();
1842 else if( n == '\'' )
1843 break;
1844 for (i = 0; i < size; ++i)
1845 val[i] = n >> (i * 8);
1846 if (!brev)
1847 byterev(val, size);
1848 mwrite(adrs, val, size);
1849 adrs += size;
1851 adrs -= size;
1852 inc = size;
1853 break;
1854 case ',':
1855 adrs += size;
1856 break;
1857 case '.':
1858 mnoread = 0;
1859 break;
1860 case ';':
1861 break;
1862 case 'x':
1863 case EOF:
1864 scannl();
1865 return;
1866 case 'b':
1867 case 'v':
1868 size = 1;
1869 break;
1870 case 'w':
1871 size = 2;
1872 break;
1873 case 'l':
1874 size = 4;
1875 break;
1876 case 'u':
1877 size = 8;
1878 break;
1879 case '^':
1880 adrs -= size;
1881 break;
1882 break;
1883 case '/':
1884 if (nslash > 0)
1885 adrs -= 1 << nslash;
1886 else
1887 nslash = 0;
1888 nslash += 4;
1889 adrs += 1 << nslash;
1890 break;
1891 case '\\':
1892 if (nslash < 0)
1893 adrs += 1 << -nslash;
1894 else
1895 nslash = 0;
1896 nslash -= 4;
1897 adrs -= 1 << -nslash;
1898 break;
1899 case 'm':
1900 scanhex((void *)&adrs);
1901 break;
1902 case 'n':
1903 mnoread = 1;
1904 break;
1905 case 'r':
1906 brev = !brev;
1907 break;
1908 case '<':
1909 n = size;
1910 scanhex(&n);
1911 adrs -= n;
1912 break;
1913 case '>':
1914 n = size;
1915 scanhex(&n);
1916 adrs += n;
1917 break;
1918 case '?':
1919 printf(memex_subcmd_help_string);
1920 break;
1923 adrs += inc;
1928 bsesc(void)
1930 int c;
1932 c = inchar();
1933 switch( c ){
1934 case 'n': c = '\n'; break;
1935 case 'r': c = '\r'; break;
1936 case 'b': c = '\b'; break;
1937 case 't': c = '\t'; break;
1939 return c;
1942 static void xmon_rawdump (unsigned long adrs, long ndump)
1944 long n, m, r, nr;
1945 unsigned char temp[16];
1947 for (n = ndump; n > 0;) {
1948 r = n < 16? n: 16;
1949 nr = mread(adrs, temp, r);
1950 adrs += nr;
1951 for (m = 0; m < r; ++m) {
1952 if (m < nr)
1953 printf("%.2x", temp[m]);
1954 else
1955 printf("%s", fault_chars[fault_type]);
1957 n -= r;
1958 if (nr < r)
1959 break;
1961 printf("\n");
1964 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1965 || ('a' <= (c) && (c) <= 'f') \
1966 || ('A' <= (c) && (c) <= 'F'))
1967 void
1968 dump(void)
1970 int c;
1972 c = inchar();
1973 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1974 termch = c;
1975 scanhex((void *)&adrs);
1976 if (termch != '\n')
1977 termch = 0;
1978 if (c == 'i') {
1979 scanhex(&nidump);
1980 if (nidump == 0)
1981 nidump = 16;
1982 else if (nidump > MAX_DUMP)
1983 nidump = MAX_DUMP;
1984 adrs += ppc_inst_dump(adrs, nidump, 1);
1985 last_cmd = "di\n";
1986 } else if (c == 'r') {
1987 scanhex(&ndump);
1988 if (ndump == 0)
1989 ndump = 64;
1990 xmon_rawdump(adrs, ndump);
1991 adrs += ndump;
1992 last_cmd = "dr\n";
1993 } else {
1994 scanhex(&ndump);
1995 if (ndump == 0)
1996 ndump = 64;
1997 else if (ndump > MAX_DUMP)
1998 ndump = MAX_DUMP;
1999 prdump(adrs, ndump);
2000 adrs += ndump;
2001 last_cmd = "d\n";
2005 void
2006 prdump(unsigned long adrs, long ndump)
2008 long n, m, c, r, nr;
2009 unsigned char temp[16];
2011 for (n = ndump; n > 0;) {
2012 printf(REG, adrs);
2013 putchar(' ');
2014 r = n < 16? n: 16;
2015 nr = mread(adrs, temp, r);
2016 adrs += nr;
2017 for (m = 0; m < r; ++m) {
2018 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2019 putchar(' ');
2020 if (m < nr)
2021 printf("%.2x", temp[m]);
2022 else
2023 printf("%s", fault_chars[fault_type]);
2025 for (; m < 16; ++m) {
2026 if ((m & (sizeof(long) - 1)) == 0)
2027 putchar(' ');
2028 printf(" ");
2030 printf(" |");
2031 for (m = 0; m < r; ++m) {
2032 if (m < nr) {
2033 c = temp[m];
2034 putchar(' ' <= c && c <= '~'? c: '.');
2035 } else
2036 putchar(' ');
2038 n -= r;
2039 for (; m < 16; ++m)
2040 putchar(' ');
2041 printf("|\n");
2042 if (nr < r)
2043 break;
2048 ppc_inst_dump(unsigned long adr, long count, int praddr)
2050 int nr, dotted;
2051 unsigned long first_adr;
2052 unsigned long inst, last_inst = 0;
2053 unsigned char val[4];
2055 dotted = 0;
2056 for (first_adr = adr; count > 0; --count, adr += 4) {
2057 nr = mread(adr, val, 4);
2058 if (nr == 0) {
2059 if (praddr) {
2060 const char *x = fault_chars[fault_type];
2061 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2063 break;
2065 inst = GETWORD(val);
2066 if (adr > first_adr && inst == last_inst) {
2067 if (!dotted) {
2068 printf(" ...\n");
2069 dotted = 1;
2071 continue;
2073 dotted = 0;
2074 last_inst = inst;
2075 if (praddr)
2076 printf(REG" %.8x", adr, inst);
2077 printf("\t");
2078 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2079 printf("\n");
2081 return adr - first_adr;
2084 void
2085 print_address(unsigned long addr)
2087 xmon_print_symbol(addr, "\t# ", "");
2092 * Memory operations - move, set, print differences
2094 static unsigned long mdest; /* destination address */
2095 static unsigned long msrc; /* source address */
2096 static unsigned long mval; /* byte value to set memory to */
2097 static unsigned long mcount; /* # bytes to affect */
2098 static unsigned long mdiffs; /* max # differences to print */
2100 void
2101 memops(int cmd)
2103 scanhex((void *)&mdest);
2104 if( termch != '\n' )
2105 termch = 0;
2106 scanhex((void *)(cmd == 's'? &mval: &msrc));
2107 if( termch != '\n' )
2108 termch = 0;
2109 scanhex((void *)&mcount);
2110 switch( cmd ){
2111 case 'm':
2112 memmove((void *)mdest, (void *)msrc, mcount);
2113 break;
2114 case 's':
2115 memset((void *)mdest, mval, mcount);
2116 break;
2117 case 'd':
2118 if( termch != '\n' )
2119 termch = 0;
2120 scanhex((void *)&mdiffs);
2121 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2122 break;
2126 void
2127 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2129 unsigned n, prt;
2131 prt = 0;
2132 for( n = nb; n > 0; --n )
2133 if( *p1++ != *p2++ )
2134 if( ++prt <= maxpr )
2135 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2136 p1[-1], p2 - 1, p2[-1]);
2137 if( prt > maxpr )
2138 printf("Total of %d differences\n", prt);
2141 static unsigned mend;
2142 static unsigned mask;
2144 void
2145 memlocate(void)
2147 unsigned a, n;
2148 unsigned char val[4];
2150 last_cmd = "ml";
2151 scanhex((void *)&mdest);
2152 if (termch != '\n') {
2153 termch = 0;
2154 scanhex((void *)&mend);
2155 if (termch != '\n') {
2156 termch = 0;
2157 scanhex((void *)&mval);
2158 mask = ~0;
2159 if (termch != '\n') termch = 0;
2160 scanhex((void *)&mask);
2163 n = 0;
2164 for (a = mdest; a < mend; a += 4) {
2165 if (mread(a, val, 4) == 4
2166 && ((GETWORD(val) ^ mval) & mask) == 0) {
2167 printf("%.16x: %.16x\n", a, GETWORD(val));
2168 if (++n >= 10)
2169 break;
2174 static unsigned long mskip = 0x1000;
2175 static unsigned long mlim = 0xffffffff;
2177 void
2178 memzcan(void)
2180 unsigned char v;
2181 unsigned a;
2182 int ok, ook;
2184 scanhex(&mdest);
2185 if (termch != '\n') termch = 0;
2186 scanhex(&mskip);
2187 if (termch != '\n') termch = 0;
2188 scanhex(&mlim);
2189 ook = 0;
2190 for (a = mdest; a < mlim; a += mskip) {
2191 ok = mread(a, &v, 1);
2192 if (ok && !ook) {
2193 printf("%.8x .. ", a);
2194 } else if (!ok && ook)
2195 printf("%.8x\n", a - mskip);
2196 ook = ok;
2197 if (a + mskip < a)
2198 break;
2200 if (ook)
2201 printf("%.8x\n", a - mskip);
2204 void proccall(void)
2206 unsigned long args[8];
2207 unsigned long ret;
2208 int i;
2209 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2210 unsigned long, unsigned long, unsigned long,
2211 unsigned long, unsigned long, unsigned long);
2212 callfunc_t func;
2214 if (!scanhex(&adrs))
2215 return;
2216 if (termch != '\n')
2217 termch = 0;
2218 for (i = 0; i < 8; ++i)
2219 args[i] = 0;
2220 for (i = 0; i < 8; ++i) {
2221 if (!scanhex(&args[i]) || termch == '\n')
2222 break;
2223 termch = 0;
2225 func = (callfunc_t) adrs;
2226 ret = 0;
2227 if (setjmp(bus_error_jmp) == 0) {
2228 catch_memory_errors = 1;
2229 sync();
2230 ret = func(args[0], args[1], args[2], args[3],
2231 args[4], args[5], args[6], args[7]);
2232 sync();
2233 printf("return value is %x\n", ret);
2234 } else {
2235 printf("*** %x exception occurred\n", fault_except);
2237 catch_memory_errors = 0;
2240 /* Input scanning routines */
2242 skipbl(void)
2244 int c;
2246 if( termch != 0 ){
2247 c = termch;
2248 termch = 0;
2249 } else
2250 c = inchar();
2251 while( c == ' ' || c == '\t' )
2252 c = inchar();
2253 return c;
2256 #define N_PTREGS 44
2257 static char *regnames[N_PTREGS] = {
2258 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2259 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2260 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2261 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2262 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2263 #ifdef CONFIG_PPC64
2264 "softe",
2265 #else
2266 "mq",
2267 #endif
2268 "trap", "dar", "dsisr", "res"
2272 scanhex(unsigned long *vp)
2274 int c, d;
2275 unsigned long v;
2277 c = skipbl();
2278 if (c == '%') {
2279 /* parse register name */
2280 char regname[8];
2281 int i;
2283 for (i = 0; i < sizeof(regname) - 1; ++i) {
2284 c = inchar();
2285 if (!isalnum(c)) {
2286 termch = c;
2287 break;
2289 regname[i] = c;
2291 regname[i] = 0;
2292 for (i = 0; i < N_PTREGS; ++i) {
2293 if (strcmp(regnames[i], regname) == 0) {
2294 if (xmon_regs == NULL) {
2295 printf("regs not available\n");
2296 return 0;
2298 *vp = ((unsigned long *)xmon_regs)[i];
2299 return 1;
2302 printf("invalid register name '%%%s'\n", regname);
2303 return 0;
2306 /* skip leading "0x" if any */
2308 if (c == '0') {
2309 c = inchar();
2310 if (c == 'x') {
2311 c = inchar();
2312 } else {
2313 d = hexdigit(c);
2314 if (d == EOF) {
2315 termch = c;
2316 *vp = 0;
2317 return 1;
2320 } else if (c == '$') {
2321 int i;
2322 for (i=0; i<63; i++) {
2323 c = inchar();
2324 if (isspace(c)) {
2325 termch = c;
2326 break;
2328 tmpstr[i] = c;
2330 tmpstr[i++] = 0;
2331 *vp = 0;
2332 if (setjmp(bus_error_jmp) == 0) {
2333 catch_memory_errors = 1;
2334 sync();
2335 *vp = kallsyms_lookup_name(tmpstr);
2336 sync();
2338 catch_memory_errors = 0;
2339 if (!(*vp)) {
2340 printf("unknown symbol '%s'\n", tmpstr);
2341 return 0;
2343 return 1;
2346 d = hexdigit(c);
2347 if (d == EOF) {
2348 termch = c;
2349 return 0;
2351 v = 0;
2352 do {
2353 v = (v << 4) + d;
2354 c = inchar();
2355 d = hexdigit(c);
2356 } while (d != EOF);
2357 termch = c;
2358 *vp = v;
2359 return 1;
2362 void
2363 scannl(void)
2365 int c;
2367 c = termch;
2368 termch = 0;
2369 while( c != '\n' )
2370 c = inchar();
2373 int hexdigit(int c)
2375 if( '0' <= c && c <= '9' )
2376 return c - '0';
2377 if( 'A' <= c && c <= 'F' )
2378 return c - ('A' - 10);
2379 if( 'a' <= c && c <= 'f' )
2380 return c - ('a' - 10);
2381 return EOF;
2384 void
2385 getstring(char *s, int size)
2387 int c;
2389 c = skipbl();
2390 do {
2391 if( size > 1 ){
2392 *s++ = c;
2393 --size;
2395 c = inchar();
2396 } while( c != ' ' && c != '\t' && c != '\n' );
2397 termch = c;
2398 *s = 0;
2401 static char line[256];
2402 static char *lineptr;
2404 void
2405 flush_input(void)
2407 lineptr = NULL;
2411 inchar(void)
2413 if (lineptr == NULL || *lineptr == 0) {
2414 if (xmon_gets(line, sizeof(line)) == NULL) {
2415 lineptr = NULL;
2416 return EOF;
2418 lineptr = line;
2420 return *lineptr++;
2423 void
2424 take_input(char *str)
2426 lineptr = str;
2430 static void
2431 symbol_lookup(void)
2433 int type = inchar();
2434 unsigned long addr;
2435 static char tmp[64];
2437 switch (type) {
2438 case 'a':
2439 if (scanhex(&addr))
2440 xmon_print_symbol(addr, ": ", "\n");
2441 termch = 0;
2442 break;
2443 case 's':
2444 getstring(tmp, 64);
2445 if (setjmp(bus_error_jmp) == 0) {
2446 catch_memory_errors = 1;
2447 sync();
2448 addr = kallsyms_lookup_name(tmp);
2449 if (addr)
2450 printf("%s: %lx\n", tmp, addr);
2451 else
2452 printf("Symbol '%s' not found.\n", tmp);
2453 sync();
2455 catch_memory_errors = 0;
2456 termch = 0;
2457 break;
2462 /* Print an address in numeric and symbolic form (if possible) */
2463 static void xmon_print_symbol(unsigned long address, const char *mid,
2464 const char *after)
2466 char *modname;
2467 const char *name = NULL;
2468 unsigned long offset, size;
2470 printf(REG, address);
2471 if (setjmp(bus_error_jmp) == 0) {
2472 catch_memory_errors = 1;
2473 sync();
2474 name = kallsyms_lookup(address, &size, &offset, &modname,
2475 tmpstr);
2476 sync();
2477 /* wait a little while to see if we get a machine check */
2478 __delay(200);
2481 catch_memory_errors = 0;
2483 if (name) {
2484 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2485 if (modname)
2486 printf(" [%s]", modname);
2488 printf("%s", after);
2491 #ifdef CONFIG_PPC64
2492 static void dump_slb(void)
2494 int i;
2495 unsigned long tmp;
2497 printf("SLB contents of cpu %x\n", smp_processor_id());
2499 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2500 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2501 printf("%02d %016lx ", i, tmp);
2503 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2504 printf("%016lx\n", tmp);
2508 static void dump_stab(void)
2510 int i;
2511 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2513 printf("Segment table contents of cpu %x\n", smp_processor_id());
2515 for (i = 0; i < PAGE_SIZE/16; i++) {
2516 unsigned long a, b;
2518 a = *tmp++;
2519 b = *tmp++;
2521 if (a || b) {
2522 printf("%03d %016lx ", i, a);
2523 printf("%016lx\n", b);
2528 void dump_segments(void)
2530 if (cpu_has_feature(CPU_FTR_SLB))
2531 dump_slb();
2532 else
2533 dump_stab();
2535 #endif
2537 #ifdef CONFIG_PPC_STD_MMU_32
2538 void dump_segments(void)
2540 int i;
2542 printf("sr0-15 =");
2543 for (i = 0; i < 16; ++i)
2544 printf(" %x", mfsrin(i));
2545 printf("\n");
2547 #endif
2549 void xmon_init(int enable)
2551 if (enable) {
2552 __debugger = xmon;
2553 __debugger_ipi = xmon_ipi;
2554 __debugger_bpt = xmon_bpt;
2555 __debugger_sstep = xmon_sstep;
2556 __debugger_iabr_match = xmon_iabr_match;
2557 __debugger_dabr_match = xmon_dabr_match;
2558 __debugger_fault_handler = xmon_fault_handler;
2559 } else {
2560 __debugger = NULL;
2561 __debugger_ipi = NULL;
2562 __debugger_bpt = NULL;
2563 __debugger_sstep = NULL;
2564 __debugger_iabr_match = NULL;
2565 __debugger_dabr_match = NULL;
2566 __debugger_fault_handler = NULL;
2568 xmon_map_scc();
2571 #ifdef CONFIG_MAGIC_SYSRQ
2572 static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2573 struct tty_struct *tty)
2575 /* ensure xmon is enabled */
2576 xmon_init(1);
2577 debugger(pt_regs);
2580 static struct sysrq_key_op sysrq_xmon_op =
2582 .handler = sysrq_handle_xmon,
2583 .help_msg = "Xmon",
2584 .action_msg = "Entering xmon",
2587 static int __init setup_xmon_sysrq(void)
2589 register_sysrq_key('x', &sysrq_xmon_op);
2590 return 0;
2592 __initcall(setup_xmon_sysrq);
2593 #endif /* CONFIG_MAGIC_SYSRQ */