2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996-2005 Paul Mackerras.
5 * Copyright (C) 2001 PPC64 Team, IBM Corp
6 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/smp.h>
17 #include <linux/reboot.h>
18 #include <linux/delay.h>
19 #include <linux/kallsyms.h>
20 #include <linux/cpumask.h>
21 #include <linux/module.h>
22 #include <linux/sysrq.h>
23 #include <linux/interrupt.h>
24 #include <linux/irq.h>
26 #include <asm/ptrace.h>
27 #include <asm/string.h>
29 #include <asm/machdep.h>
31 #include <asm/processor.h>
32 #include <asm/pgtable.h>
34 #include <asm/mmu_context.h>
35 #include <asm/cputable.h>
37 #include <asm/sstep.h>
41 #include <asm/hvcall.h>
47 #define scanhex xmon_scanhex
48 #define skipbl xmon_skipbl
51 cpumask_t cpus_in_xmon = CPU_MASK_NONE;
52 static unsigned long xmon_taken = 1;
53 static int xmon_owner;
55 #endif /* CONFIG_SMP */
57 static unsigned long in_xmon = 0;
59 static unsigned long adrs;
61 #define MAX_DUMP (128 * 1024)
62 static unsigned long ndump = 64;
63 static unsigned long nidump = 16;
64 static unsigned long ncsum = 4096;
66 static char tmpstr[128];
68 #define JMP_BUF_LEN 23
69 static long bus_error_jmp[JMP_BUF_LEN];
70 static int catch_memory_errors;
71 static long *xmon_fault_jmp[NR_CPUS];
72 #define setjmp xmon_setjmp
73 #define longjmp xmon_longjmp
75 /* Breakpoint stuff */
77 unsigned long address;
78 unsigned int instr[2];
84 /* Bits in bpt.enabled */
85 #define BP_IABR_TE 1 /* IABR translation enabled */
91 static struct bpt bpts[NBPTS];
92 static struct bpt dabr;
93 static struct bpt *iabr;
94 static unsigned bpinstr = 0x7fe00008; /* trap */
96 #define BP_NUM(bp) ((bp) - bpts + 1)
99 static int cmds(struct pt_regs *);
100 static int mread(unsigned long, void *, int);
101 static int mwrite(unsigned long, void *, int);
102 static int handle_fault(struct pt_regs *);
103 static void byterev(unsigned char *, int);
104 static void memex(void);
105 static int bsesc(void);
106 static void dump(void);
107 static void prdump(unsigned long, long);
108 static int ppc_inst_dump(unsigned long, long, int);
109 void print_address(unsigned long);
110 static void backtrace(struct pt_regs *);
111 static void excprint(struct pt_regs *);
112 static void prregs(struct pt_regs *);
113 static void memops(int);
114 static void memlocate(void);
115 static void memzcan(void);
116 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
118 int scanhex(unsigned long *valp);
119 static void scannl(void);
120 static int hexdigit(int);
121 void getstring(char *, int);
122 static void flush_input(void);
123 static int inchar(void);
124 static void take_input(char *);
125 static unsigned long read_spr(int);
126 static void write_spr(int, unsigned long);
127 static void super_regs(void);
128 static void remove_bpts(void);
129 static void insert_bpts(void);
130 static void remove_cpu_bpts(void);
131 static void insert_cpu_bpts(void);
132 static struct bpt *at_breakpoint(unsigned long pc);
133 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
134 static int do_step(struct pt_regs *);
135 static void bpt_cmds(void);
136 static void cacheflush(void);
137 static int cpu_cmd(void);
138 static void csum(void);
139 static void bootcmds(void);
140 static void proccall(void);
141 void dump_segments(void);
142 static void symbol_lookup(void);
143 static void xmon_show_stack(unsigned long sp, unsigned long lr,
145 static void xmon_print_symbol(unsigned long address, const char *mid,
147 static const char *getvecname(unsigned long vec);
149 int xmon_no_auto_backtrace;
151 extern int print_insn_powerpc(unsigned long, unsigned long, int);
153 extern void xmon_enter(void);
154 extern void xmon_leave(void);
156 extern long setjmp(long *);
157 extern void longjmp(long *, long);
158 extern void xmon_save_regs(struct pt_regs *);
162 #define REGS_PER_LINE 4
163 #define LAST_VOLATILE 13
166 #define REGS_PER_LINE 8
167 #define LAST_VOLATILE 12
170 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
172 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
173 || ('a' <= (c) && (c) <= 'f') \
174 || ('A' <= (c) && (c) <= 'F'))
175 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
176 || ('a' <= (c) && (c) <= 'z') \
177 || ('A' <= (c) && (c) <= 'Z'))
178 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
180 static char *help_string = "\
182 b show breakpoints\n\
183 bd set data breakpoint\n\
184 bi set instruction breakpoint\n\
185 bc clear breakpoint\n"
188 c print cpus stopped in xmon\n\
189 c# try to switch to cpu number h (in hex)\n"
194 di dump instructions\n\
195 df dump float values\n\
196 dd dump double values\n\
197 dr dump stream of raw bytes\n\
198 e print exception information\n\
200 la lookup symbol+offset of specified address\n\
201 ls lookup address of specified symbol\n\
202 m examine/change memory\n\
203 mm move a block of memory\n\
204 ms set a block of memory\n\
205 md compare two blocks of memory\n\
206 ml locate a block of memory\n\
207 mz zero a block of memory\n\
208 mi show information about memory allocation\n\
209 p call a procedure\n\
212 S print special registers\n\
214 x exit monitor and recover\n\
215 X exit monitor and dont recover\n"
217 " u dump segment table or SLB\n"
219 #ifdef CONFIG_PPC_STD_MMU_32
220 " u dump segment registers\n"
227 static struct pt_regs *xmon_regs;
229 static inline void sync(void)
231 asm volatile("sync; isync");
234 static inline void store_inst(void *p)
236 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
239 static inline void cflush(void *p)
241 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
244 static inline void cinval(void *p)
246 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
250 * Disable surveillance (the service processor watchdog function)
251 * while we are in xmon.
252 * XXX we should re-enable it when we leave. :)
254 #define SURVEILLANCE_TOKEN 9000
256 static inline void disable_surveillance(void)
258 #ifdef CONFIG_PPC_PSERIES
259 /* Since this can't be a module, args should end up below 4GB. */
260 static struct rtas_args args;
263 * At this point we have got all the cpus we can into
264 * xmon, so there is hopefully no other cpu calling RTAS
265 * at the moment, even though we don't take rtas.lock.
266 * If we did try to take rtas.lock there would be a
267 * real possibility of deadlock.
269 args.token = rtas_token("set-indicator");
270 if (args.token == RTAS_UNKNOWN_SERVICE)
274 args.rets = &args.args[3];
275 args.args[0] = SURVEILLANCE_TOKEN;
278 enter_rtas(__pa(&args));
279 #endif /* CONFIG_PPC_PSERIES */
283 static int xmon_speaker;
285 static void get_output_lock(void)
287 int me = smp_processor_id() + 0x100;
288 int last_speaker = 0, prev;
291 if (xmon_speaker == me)
294 if (xmon_speaker == 0) {
295 last_speaker = cmpxchg(&xmon_speaker, 0, me);
296 if (last_speaker == 0)
300 while (xmon_speaker == last_speaker) {
303 /* hostile takeover */
304 prev = cmpxchg(&xmon_speaker, last_speaker, me);
305 if (prev == last_speaker)
312 static void release_output_lock(void)
318 static int xmon_core(struct pt_regs *regs, int fromipi)
323 long recurse_jmp[JMP_BUF_LEN];
324 unsigned long offset;
328 unsigned long timeout;
332 mtmsr(msr & ~MSR_EE); /* disable interrupts */
334 bp = in_breakpoint_table(regs->nip, &offset);
336 regs->nip = bp->address + offset;
337 atomic_dec(&bp->ref_count);
343 cpu = smp_processor_id();
344 if (cpu_isset(cpu, cpus_in_xmon)) {
347 printf("cpu 0x%x: Exception %lx %s in xmon, "
348 "returning to main loop\n",
349 cpu, regs->trap, getvecname(TRAP(regs)));
350 release_output_lock();
351 longjmp(xmon_fault_jmp[cpu], 1);
354 if (setjmp(recurse_jmp) != 0) {
355 if (!in_xmon || !xmon_gate) {
357 printf("xmon: WARNING: bad recursive fault "
358 "on cpu 0x%x\n", cpu);
359 release_output_lock();
362 secondary = !(xmon_taken && cpu == xmon_owner);
366 xmon_fault_jmp[cpu] = recurse_jmp;
367 cpu_set(cpu, cpus_in_xmon);
370 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
371 bp = at_breakpoint(regs->nip);
372 if (bp || (regs->msr & MSR_RI) == 0)
379 printf("cpu 0x%x stopped at breakpoint 0x%x (",
381 xmon_print_symbol(regs->nip, " ", ")\n");
383 if ((regs->msr & MSR_RI) == 0)
384 printf("WARNING: exception is not recoverable, "
386 release_output_lock();
391 while (secondary && !xmon_gate) {
395 secondary = test_and_set_bit(0, &in_xmon);
400 if (!secondary && !xmon_gate) {
401 /* we are the first cpu to come in */
402 /* interrupt other cpu(s) */
403 int ncpus = num_online_cpus();
408 smp_send_debugger_break(MSG_ALL_BUT_SELF);
409 /* wait for other cpus to come in */
410 for (timeout = 100000000; timeout != 0; --timeout) {
411 if (cpus_weight(cpus_in_xmon) >= ncpus)
417 disable_surveillance();
418 /* for breakpoint or single step, print the current instr. */
419 if (bp || TRAP(regs) == 0xd00)
420 ppc_inst_dump(regs->nip, 1, 0);
421 printf("enter ? for help\n");
430 if (cpu == xmon_owner) {
431 if (!test_and_set_bit(0, &xmon_taken)) {
436 while (cpu == xmon_owner)
450 /* have switched to some other cpu */
455 cpu_clear(cpu, cpus_in_xmon);
456 xmon_fault_jmp[cpu] = NULL;
458 /* UP is simple... */
460 printf("Exception %lx %s in xmon, returning to main loop\n",
461 regs->trap, getvecname(TRAP(regs)));
462 longjmp(xmon_fault_jmp[0], 1);
464 if (setjmp(recurse_jmp) == 0) {
465 xmon_fault_jmp[0] = recurse_jmp;
469 bp = at_breakpoint(regs->nip);
471 printf("Stopped at breakpoint %x (", BP_NUM(bp));
472 xmon_print_symbol(regs->nip, " ", ")\n");
474 if ((regs->msr & MSR_RI) == 0)
475 printf("WARNING: exception is not recoverable, "
478 disable_surveillance();
479 /* for breakpoint or single step, print the current instr. */
480 if (bp || TRAP(regs) == 0xd00)
481 ppc_inst_dump(regs->nip, 1, 0);
482 printf("enter ? for help\n");
491 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
492 bp = at_breakpoint(regs->nip);
494 int stepped = emulate_step(regs, bp->instr[0]);
496 regs->nip = (unsigned long) &bp->instr[0];
497 atomic_inc(&bp->ref_count);
498 } else if (stepped < 0) {
499 printf("Couldn't single-step %s instruction\n",
500 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
507 mtmsr(msr); /* restore interrupt enable */
509 return cmd != 'X' && cmd != EOF;
512 int xmon(struct pt_regs *excp)
517 xmon_save_regs(®s);
520 return xmon_core(excp, 0);
525 xmon_irq(int irq, void *d, struct pt_regs *regs)
528 local_irq_save(flags);
529 printf("Keyboard interrupt\n");
531 local_irq_restore(flags);
535 static int xmon_bpt(struct pt_regs *regs)
538 unsigned long offset;
540 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
543 /* Are we at the trap at bp->instr[1] for some bp? */
544 bp = in_breakpoint_table(regs->nip, &offset);
545 if (bp != NULL && offset == 4) {
546 regs->nip = bp->address + 4;
547 atomic_dec(&bp->ref_count);
551 /* Are we at a breakpoint? */
552 bp = at_breakpoint(regs->nip);
561 static int xmon_sstep(struct pt_regs *regs)
569 static int xmon_dabr_match(struct pt_regs *regs)
571 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
573 if (dabr.enabled == 0)
579 static int xmon_iabr_match(struct pt_regs *regs)
581 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
589 static int xmon_ipi(struct pt_regs *regs)
592 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
598 static int xmon_fault_handler(struct pt_regs *regs)
601 unsigned long offset;
603 if (in_xmon && catch_memory_errors)
604 handle_fault(regs); /* doesn't return */
606 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
607 bp = in_breakpoint_table(regs->nip, &offset);
609 regs->nip = bp->address + offset;
610 atomic_dec(&bp->ref_count);
617 static struct bpt *at_breakpoint(unsigned long pc)
623 for (i = 0; i < NBPTS; ++i, ++bp)
624 if (bp->enabled && pc == bp->address)
629 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
633 off = nip - (unsigned long) bpts;
634 if (off >= sizeof(bpts))
636 off %= sizeof(struct bpt);
637 if (off != offsetof(struct bpt, instr[0])
638 && off != offsetof(struct bpt, instr[1]))
640 *offp = off - offsetof(struct bpt, instr[0]);
641 return (struct bpt *) (nip - off);
644 static struct bpt *new_breakpoint(unsigned long a)
649 bp = at_breakpoint(a);
653 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
654 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
656 bp->instr[1] = bpinstr;
657 store_inst(&bp->instr[1]);
662 printf("Sorry, no free breakpoints. Please clear one first.\n");
666 static void insert_bpts(void)
672 for (i = 0; i < NBPTS; ++i, ++bp) {
673 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
675 if (mread(bp->address, &bp->instr[0], 4) != 4) {
676 printf("Couldn't read instruction at %lx, "
677 "disabling breakpoint there\n", bp->address);
681 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
682 printf("Breakpoint at %lx is on an mtmsrd or rfid "
683 "instruction, disabling it\n", bp->address);
687 store_inst(&bp->instr[0]);
688 if (bp->enabled & BP_IABR)
690 if (mwrite(bp->address, &bpinstr, 4) != 4) {
691 printf("Couldn't write instruction at %lx, "
692 "disabling breakpoint there\n", bp->address);
693 bp->enabled &= ~BP_TRAP;
696 store_inst((void *)bp->address);
700 static void insert_cpu_bpts(void)
703 set_dabr(dabr.address | (dabr.enabled & 7));
704 if (iabr && cpu_has_feature(CPU_FTR_IABR))
705 mtspr(SPRN_IABR, iabr->address
706 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
709 static void remove_bpts(void)
716 for (i = 0; i < NBPTS; ++i, ++bp) {
717 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
719 if (mread(bp->address, &instr, 4) == 4
721 && mwrite(bp->address, &bp->instr, 4) != 4)
722 printf("Couldn't remove breakpoint at %lx\n",
725 store_inst((void *)bp->address);
729 static void remove_cpu_bpts(void)
732 if (cpu_has_feature(CPU_FTR_IABR))
736 /* Command interpreting routine */
737 static char *last_cmd;
740 cmds(struct pt_regs *excp)
747 if (!xmon_no_auto_backtrace) {
748 xmon_no_auto_backtrace = 1;
749 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
754 printf("%x:", smp_processor_id());
755 #endif /* CONFIG_SMP */
761 if (last_cmd == NULL)
763 take_input(last_cmd);
797 prregs(excp); /* print regs */
819 printf(" <no input ...>\n");
841 #ifdef CONFIG_PPC_STD_MMU
847 printf("Unrecognized command: ");
849 if (' ' < cmd && cmd <= '~')
852 printf("\\x%x", cmd);
854 } while (cmd != '\n');
855 printf(" (type ? for help)\n");
862 * Step a single instruction.
863 * Some instructions we emulate, others we execute with MSR_SE set.
865 static int do_step(struct pt_regs *regs)
870 /* check we are in 64-bit kernel mode, translation enabled */
871 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
872 if (mread(regs->nip, &instr, 4) == 4) {
873 stepped = emulate_step(regs, instr);
875 printf("Couldn't single-step %s instruction\n",
876 (IS_RFID(instr)? "rfid": "mtmsrd"));
880 regs->trap = 0xd00 | (regs->trap & 1);
881 printf("stepped to ");
882 xmon_print_symbol(regs->nip, " ", "\n");
883 ppc_inst_dump(regs->nip, 1, 0);
892 static void bootcmds(void)
898 ppc_md.restart(NULL);
905 static int cpu_cmd(void)
912 if (!scanhex(&cpu)) {
913 /* print cpus waiting or in xmon */
914 printf("cpus stopped:");
916 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
917 if (cpu_isset(cpu, cpus_in_xmon)) {
923 printf("-%x", cpu - 1);
928 printf("-%x", NR_CPUS - 1);
932 /* try to switch to cpu specified */
933 if (!cpu_isset(cpu, cpus_in_xmon)) {
934 printf("cpu 0x%x isn't in xmon\n", cpu);
941 while (!xmon_taken) {
942 if (--timeout == 0) {
943 if (test_and_set_bit(0, &xmon_taken))
945 /* take control back */
947 xmon_owner = smp_processor_id();
948 printf("cpu %u didn't take control\n", cpu);
956 #endif /* CONFIG_SMP */
959 static unsigned short fcstab[256] = {
960 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
961 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
962 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
963 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
964 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
965 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
966 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
967 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
968 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
969 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
970 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
971 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
972 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
973 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
974 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
975 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
976 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
977 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
978 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
979 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
980 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
981 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
982 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
983 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
984 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
985 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
986 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
987 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
988 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
989 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
990 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
991 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
994 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1003 if (!scanhex(&adrs))
1005 if (!scanhex(&ncsum))
1008 for (i = 0; i < ncsum; ++i) {
1009 if (mread(adrs+i, &v, 1) == 0) {
1010 printf("csum stopped at %x\n", adrs+i);
1015 printf("%x\n", fcs);
1019 * Check if this is a suitable place to put a breakpoint.
1021 static long check_bp_loc(unsigned long addr)
1026 if (!is_kernel_addr(addr)) {
1027 printf("Breakpoints may only be placed at kernel addresses\n");
1030 if (!mread(addr, &instr, sizeof(instr))) {
1031 printf("Can't read instruction at address %lx\n", addr);
1034 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1035 printf("Breakpoints may not be placed on mtmsrd or rfid "
1042 static char *breakpoint_help_string =
1043 "Breakpoint command usage:\n"
1044 "b show breakpoints\n"
1045 "b <addr> [cnt] set breakpoint at given instr addr\n"
1046 "bc clear all breakpoints\n"
1047 "bc <n/addr> clear breakpoint number n or at addr\n"
1048 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1049 "bd <addr> [cnt] set hardware data breakpoint\n"
1059 const char badaddr[] = "Only kernel addresses are permitted "
1060 "for breakpoints\n";
1065 case 'd': /* bd - hardware data breakpoint */
1070 else if (cmd == 'w')
1076 if (scanhex(&dabr.address)) {
1077 if (!is_kernel_addr(dabr.address)) {
1082 dabr.enabled = mode | BP_DABR;
1086 case 'i': /* bi - hardware instr breakpoint */
1087 if (!cpu_has_feature(CPU_FTR_IABR)) {
1088 printf("Hardware instruction breakpoint "
1089 "not supported on this cpu\n");
1093 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1098 if (!check_bp_loc(a))
1100 bp = new_breakpoint(a);
1102 bp->enabled |= BP_IABR | BP_IABR_TE;
1110 /* clear all breakpoints */
1111 for (i = 0; i < NBPTS; ++i)
1112 bpts[i].enabled = 0;
1115 printf("All breakpoints cleared\n");
1119 if (a <= NBPTS && a >= 1) {
1120 /* assume a breakpoint number */
1121 bp = &bpts[a-1]; /* bp nums are 1 based */
1123 /* assume a breakpoint address */
1124 bp = at_breakpoint(a);
1126 printf("No breakpoint at %x\n", a);
1131 printf("Cleared breakpoint %x (", BP_NUM(bp));
1132 xmon_print_symbol(bp->address, " ", ")\n");
1140 printf(breakpoint_help_string);
1145 /* print all breakpoints */
1146 printf(" type address\n");
1148 printf(" data "REG" [", dabr.address);
1149 if (dabr.enabled & 1)
1151 if (dabr.enabled & 2)
1155 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1158 printf("%2x %s ", BP_NUM(bp),
1159 (bp->enabled & BP_IABR)? "inst": "trap");
1160 xmon_print_symbol(bp->address, " ", "\n");
1165 if (!check_bp_loc(a))
1167 bp = new_breakpoint(a);
1169 bp->enabled |= BP_TRAP;
1174 /* Very cheap human name for vector lookup. */
1176 const char *getvecname(unsigned long vec)
1181 case 0x100: ret = "(System Reset)"; break;
1182 case 0x200: ret = "(Machine Check)"; break;
1183 case 0x300: ret = "(Data Access)"; break;
1184 case 0x380: ret = "(Data SLB Access)"; break;
1185 case 0x400: ret = "(Instruction Access)"; break;
1186 case 0x480: ret = "(Instruction SLB Access)"; break;
1187 case 0x500: ret = "(Hardware Interrupt)"; break;
1188 case 0x600: ret = "(Alignment)"; break;
1189 case 0x700: ret = "(Program Check)"; break;
1190 case 0x800: ret = "(FPU Unavailable)"; break;
1191 case 0x900: ret = "(Decrementer)"; break;
1192 case 0xc00: ret = "(System Call)"; break;
1193 case 0xd00: ret = "(Single Step)"; break;
1194 case 0xf00: ret = "(Performance Monitor)"; break;
1195 case 0xf20: ret = "(Altivec Unavailable)"; break;
1196 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1202 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1203 unsigned long *endp)
1205 unsigned long size, offset;
1209 *startp = *endp = 0;
1212 if (setjmp(bus_error_jmp) == 0) {
1213 catch_memory_errors = 1;
1215 name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
1217 *startp = pc - offset;
1218 *endp = pc - offset + size;
1222 catch_memory_errors = 0;
1225 static int xmon_depth_to_print = 64;
1228 #define LRSAVE_OFFSET 0x10
1229 #define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
1230 #define MARKER_OFFSET 0x60
1231 #define REGS_OFFSET 0x70
1233 #define LRSAVE_OFFSET 4
1234 #define REG_FRAME_MARKER 0x72656773
1235 #define MARKER_OFFSET 8
1236 #define REGS_OFFSET 16
1239 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1243 unsigned long newsp;
1244 unsigned long marker;
1246 struct pt_regs regs;
1249 if (sp < PAGE_OFFSET) {
1251 printf("SP (%lx) is in userspace\n", sp);
1255 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1256 || !mread(sp, &newsp, sizeof(unsigned long))) {
1257 printf("Couldn't read stack frame at %lx\n", sp);
1262 * For the first stack frame, try to work out if
1263 * LR and/or the saved LR value in the bottommost
1264 * stack frame are valid.
1266 if ((pc | lr) != 0) {
1267 unsigned long fnstart, fnend;
1268 unsigned long nextip;
1271 get_function_bounds(pc, &fnstart, &fnend);
1274 mread(newsp + LRSAVE_OFFSET, &nextip,
1275 sizeof(unsigned long));
1277 if (lr < PAGE_OFFSET
1278 || (fnstart <= lr && lr < fnend))
1280 } else if (lr == nextip) {
1282 } else if (lr >= PAGE_OFFSET
1283 && !(fnstart <= lr && lr < fnend)) {
1284 printf("[link register ] ");
1285 xmon_print_symbol(lr, " ", "\n");
1288 printf("["REG"] ", sp);
1289 xmon_print_symbol(ip, " ", " (unreliable)\n");
1294 printf("["REG"] ", sp);
1295 xmon_print_symbol(ip, " ", "\n");
1298 /* Look for "regshere" marker to see if this is
1299 an exception frame. */
1300 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1301 && marker == REG_FRAME_MARKER) {
1302 if (mread(sp + REGS_OFFSET, ®s, sizeof(regs))
1304 printf("Couldn't read registers at %lx\n",
1308 printf("--- Exception: %lx %s at ", regs.trap,
1309 getvecname(TRAP(®s)));
1312 xmon_print_symbol(pc, " ", "\n");
1319 } while (count++ < xmon_depth_to_print);
1322 static void backtrace(struct pt_regs *excp)
1327 xmon_show_stack(sp, 0, 0);
1329 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1333 static void print_bug_trap(struct pt_regs *regs)
1335 struct bug_entry *bug;
1338 if (regs->msr & MSR_PR)
1339 return; /* not in kernel */
1340 addr = regs->nip; /* address of trap instruction */
1341 if (addr < PAGE_OFFSET)
1343 bug = find_bug(regs->nip);
1346 if (bug->line & BUG_WARNING_TRAP)
1349 printf("kernel BUG in %s at %s:%d!\n",
1350 bug->function, bug->file, (unsigned int)bug->line);
1353 void excprint(struct pt_regs *fp)
1358 printf("cpu 0x%x: ", smp_processor_id());
1359 #endif /* CONFIG_SMP */
1362 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1364 xmon_print_symbol(fp->nip, ": ", "\n");
1366 printf(" lr: ", fp->link);
1367 xmon_print_symbol(fp->link, ": ", "\n");
1369 printf(" sp: %lx\n", fp->gpr[1]);
1370 printf(" msr: %lx\n", fp->msr);
1372 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1373 printf(" dar: %lx\n", fp->dar);
1375 printf(" dsisr: %lx\n", fp->dsisr);
1378 printf(" current = 0x%lx\n", current);
1380 printf(" paca = 0x%lx\n", get_paca());
1383 printf(" pid = %ld, comm = %s\n",
1384 current->pid, current->comm);
1391 void prregs(struct pt_regs *fp)
1395 struct pt_regs regs;
1397 if (scanhex(&base)) {
1398 if (setjmp(bus_error_jmp) == 0) {
1399 catch_memory_errors = 1;
1401 regs = *(struct pt_regs *)base;
1405 catch_memory_errors = 0;
1406 printf("*** Error reading registers from "REG"\n",
1410 catch_memory_errors = 0;
1415 if (FULL_REGS(fp)) {
1416 for (n = 0; n < 16; ++n)
1417 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1418 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1420 for (n = 0; n < 7; ++n)
1421 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1422 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1425 for (n = 0; n < 32; ++n) {
1426 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1427 (n & 3) == 3? "\n": " ");
1428 if (n == 12 && !FULL_REGS(fp)) {
1435 xmon_print_symbol(fp->nip, " ", "\n");
1437 xmon_print_symbol(fp->link, " ", "\n");
1438 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1439 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1440 fp->ctr, fp->xer, fp->trap);
1442 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1443 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1446 void cacheflush(void)
1449 unsigned long nflush;
1454 scanhex((void *)&adrs);
1459 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1460 if (setjmp(bus_error_jmp) == 0) {
1461 catch_memory_errors = 1;
1465 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1466 cflush((void *) adrs);
1468 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1469 cinval((void *) adrs);
1472 /* wait a little while to see if we get a machine check */
1475 catch_memory_errors = 0;
1481 unsigned int instrs[2];
1482 unsigned long (*code)(void);
1483 unsigned long ret = -1UL;
1485 unsigned long opd[3];
1487 opd[0] = (unsigned long)instrs;
1490 code = (unsigned long (*)(void)) opd;
1492 code = (unsigned long (*)(void)) instrs;
1495 /* mfspr r3,n; blr */
1496 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1497 instrs[1] = 0x4e800020;
1499 store_inst(instrs+1);
1501 if (setjmp(bus_error_jmp) == 0) {
1502 catch_memory_errors = 1;
1508 /* wait a little while to see if we get a machine check */
1517 write_spr(int n, unsigned long val)
1519 unsigned int instrs[2];
1520 unsigned long (*code)(unsigned long);
1522 unsigned long opd[3];
1524 opd[0] = (unsigned long)instrs;
1527 code = (unsigned long (*)(unsigned long)) opd;
1529 code = (unsigned long (*)(unsigned long)) instrs;
1532 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1533 instrs[1] = 0x4e800020;
1535 store_inst(instrs+1);
1537 if (setjmp(bus_error_jmp) == 0) {
1538 catch_memory_errors = 1;
1544 /* wait a little while to see if we get a machine check */
1550 static unsigned long regno;
1551 extern char exc_prolog;
1552 extern char dec_exc;
1554 void super_regs(void)
1558 #ifdef CONFIG_PPC_ISERIES
1559 struct paca_struct *ptrPaca = NULL;
1560 struct lppaca *ptrLpPaca = NULL;
1561 struct ItLpRegSave *ptrLpRegSave = NULL;
1566 unsigned long sp, toc;
1567 asm("mr %0,1" : "=r" (sp) :);
1568 asm("mr %0,2" : "=r" (toc) :);
1570 printf("msr = "REG" sprg0= "REG"\n",
1571 mfmsr(), mfspr(SPRN_SPRG0));
1572 printf("pvr = "REG" sprg1= "REG"\n",
1573 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1574 printf("dec = "REG" sprg2= "REG"\n",
1575 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1576 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1577 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1578 #ifdef CONFIG_PPC_ISERIES
1579 // Dump out relevant Paca data areas.
1581 ptrPaca = get_paca();
1583 printf(" Local Processor Control Area (LpPaca): \n");
1584 ptrLpPaca = ptrPaca->lppaca_ptr;
1585 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1586 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1587 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1588 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1589 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1591 printf(" Local Processor Register Save Area (LpRegSave): \n");
1592 ptrLpRegSave = ptrPaca->reg_save_ptr;
1593 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1594 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1595 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1596 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1597 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1598 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1607 val = read_spr(regno);
1609 write_spr(regno, val);
1612 printf("spr %lx = %lx\n", regno, read_spr(regno));
1619 * Stuff for reading and writing memory safely
1622 mread(unsigned long adrs, void *buf, int size)
1628 if (setjmp(bus_error_jmp) == 0) {
1629 catch_memory_errors = 1;
1635 *(u16 *)q = *(u16 *)p;
1638 *(u32 *)q = *(u32 *)p;
1641 *(u64 *)q = *(u64 *)p;
1644 for( ; n < size; ++n) {
1650 /* wait a little while to see if we get a machine check */
1654 catch_memory_errors = 0;
1659 mwrite(unsigned long adrs, void *buf, int size)
1665 if (setjmp(bus_error_jmp) == 0) {
1666 catch_memory_errors = 1;
1672 *(u16 *)p = *(u16 *)q;
1675 *(u32 *)p = *(u32 *)q;
1678 *(u64 *)p = *(u64 *)q;
1681 for ( ; n < size; ++n) {
1687 /* wait a little while to see if we get a machine check */
1691 printf("*** Error writing address %x\n", adrs + n);
1693 catch_memory_errors = 0;
1697 static int fault_type;
1698 static int fault_except;
1699 static char *fault_chars[] = { "--", "**", "##" };
1701 static int handle_fault(struct pt_regs *regs)
1703 fault_except = TRAP(regs);
1704 switch (TRAP(regs)) {
1716 longjmp(bus_error_jmp, 1);
1721 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1724 byterev(unsigned char *val, int size)
1730 SWAP(val[0], val[1], t);
1733 SWAP(val[0], val[3], t);
1734 SWAP(val[1], val[2], t);
1736 case 8: /* is there really any use for this? */
1737 SWAP(val[0], val[7], t);
1738 SWAP(val[1], val[6], t);
1739 SWAP(val[2], val[5], t);
1740 SWAP(val[3], val[4], t);
1748 static char *memex_help_string =
1749 "Memory examine command usage:\n"
1750 "m [addr] [flags] examine/change memory\n"
1751 " addr is optional. will start where left off.\n"
1752 " flags may include chars from this set:\n"
1753 " b modify by bytes (default)\n"
1754 " w modify by words (2 byte)\n"
1755 " l modify by longs (4 byte)\n"
1756 " d modify by doubleword (8 byte)\n"
1757 " r toggle reverse byte order mode\n"
1758 " n do not read memory (for i/o spaces)\n"
1759 " . ok to read (default)\n"
1760 "NOTE: flags are saved as defaults\n"
1763 static char *memex_subcmd_help_string =
1764 "Memory examine subcommands:\n"
1765 " hexval write this val to current location\n"
1766 " 'string' write chars from string to this location\n"
1767 " ' increment address\n"
1768 " ^ decrement address\n"
1769 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1770 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1771 " ` clear no-read flag\n"
1772 " ; stay at this addr\n"
1773 " v change to byte mode\n"
1774 " w change to word (2 byte) mode\n"
1775 " l change to long (4 byte) mode\n"
1776 " u change to doubleword (8 byte) mode\n"
1777 " m addr change current addr\n"
1778 " n toggle no-read flag\n"
1779 " r toggle byte reverse flag\n"
1780 " < count back up count bytes\n"
1781 " > count skip forward count bytes\n"
1782 " x exit this mode\n"
1788 int cmd, inc, i, nslash;
1790 unsigned char val[16];
1792 scanhex((void *)&adrs);
1795 printf(memex_help_string);
1801 while ((cmd = skipbl()) != '\n') {
1803 case 'b': size = 1; break;
1804 case 'w': size = 2; break;
1805 case 'l': size = 4; break;
1806 case 'd': size = 8; break;
1807 case 'r': brev = !brev; break;
1808 case 'n': mnoread = 1; break;
1809 case '.': mnoread = 0; break;
1818 n = mread(adrs, val, size);
1819 printf(REG"%c", adrs, brev? 'r': ' ');
1824 for (i = 0; i < n; ++i)
1825 printf("%.2x", val[i]);
1826 for (; i < size; ++i)
1827 printf("%s", fault_chars[fault_type]);
1834 for (i = 0; i < size; ++i)
1835 val[i] = n >> (i * 8);
1838 mwrite(adrs, val, size);
1851 else if( n == '\'' )
1853 for (i = 0; i < size; ++i)
1854 val[i] = n >> (i * 8);
1857 mwrite(adrs, val, size);
1894 adrs -= 1 << nslash;
1898 adrs += 1 << nslash;
1902 adrs += 1 << -nslash;
1906 adrs -= 1 << -nslash;
1909 scanhex((void *)&adrs);
1928 printf(memex_subcmd_help_string);
1943 case 'n': c = '\n'; break;
1944 case 'r': c = '\r'; break;
1945 case 'b': c = '\b'; break;
1946 case 't': c = '\t'; break;
1951 static void xmon_rawdump (unsigned long adrs, long ndump)
1954 unsigned char temp[16];
1956 for (n = ndump; n > 0;) {
1958 nr = mread(adrs, temp, r);
1960 for (m = 0; m < r; ++m) {
1962 printf("%.2x", temp[m]);
1964 printf("%s", fault_chars[fault_type]);
1973 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1974 || ('a' <= (c) && (c) <= 'f') \
1975 || ('A' <= (c) && (c) <= 'F'))
1982 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1984 scanhex((void *)&adrs);
1991 else if (nidump > MAX_DUMP)
1993 adrs += ppc_inst_dump(adrs, nidump, 1);
1995 } else if (c == 'r') {
1999 xmon_rawdump(adrs, ndump);
2006 else if (ndump > MAX_DUMP)
2008 prdump(adrs, ndump);
2015 prdump(unsigned long adrs, long ndump)
2017 long n, m, c, r, nr;
2018 unsigned char temp[16];
2020 for (n = ndump; n > 0;) {
2024 nr = mread(adrs, temp, r);
2026 for (m = 0; m < r; ++m) {
2027 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2030 printf("%.2x", temp[m]);
2032 printf("%s", fault_chars[fault_type]);
2034 for (; m < 16; ++m) {
2035 if ((m & (sizeof(long) - 1)) == 0)
2040 for (m = 0; m < r; ++m) {
2043 putchar(' ' <= c && c <= '~'? c: '.');
2057 ppc_inst_dump(unsigned long adr, long count, int praddr)
2060 unsigned long first_adr;
2061 unsigned long inst, last_inst = 0;
2062 unsigned char val[4];
2065 for (first_adr = adr; count > 0; --count, adr += 4) {
2066 nr = mread(adr, val, 4);
2069 const char *x = fault_chars[fault_type];
2070 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2074 inst = GETWORD(val);
2075 if (adr > first_adr && inst == last_inst) {
2085 printf(REG" %.8x", adr, inst);
2087 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2090 return adr - first_adr;
2094 print_address(unsigned long addr)
2096 xmon_print_symbol(addr, "\t# ", "");
2101 * Memory operations - move, set, print differences
2103 static unsigned long mdest; /* destination address */
2104 static unsigned long msrc; /* source address */
2105 static unsigned long mval; /* byte value to set memory to */
2106 static unsigned long mcount; /* # bytes to affect */
2107 static unsigned long mdiffs; /* max # differences to print */
2112 scanhex((void *)&mdest);
2113 if( termch != '\n' )
2115 scanhex((void *)(cmd == 's'? &mval: &msrc));
2116 if( termch != '\n' )
2118 scanhex((void *)&mcount);
2121 memmove((void *)mdest, (void *)msrc, mcount);
2124 memset((void *)mdest, mval, mcount);
2127 if( termch != '\n' )
2129 scanhex((void *)&mdiffs);
2130 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2136 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2141 for( n = nb; n > 0; --n )
2142 if( *p1++ != *p2++ )
2143 if( ++prt <= maxpr )
2144 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2145 p1[-1], p2 - 1, p2[-1]);
2147 printf("Total of %d differences\n", prt);
2150 static unsigned mend;
2151 static unsigned mask;
2157 unsigned char val[4];
2160 scanhex((void *)&mdest);
2161 if (termch != '\n') {
2163 scanhex((void *)&mend);
2164 if (termch != '\n') {
2166 scanhex((void *)&mval);
2168 if (termch != '\n') termch = 0;
2169 scanhex((void *)&mask);
2173 for (a = mdest; a < mend; a += 4) {
2174 if (mread(a, val, 4) == 4
2175 && ((GETWORD(val) ^ mval) & mask) == 0) {
2176 printf("%.16x: %.16x\n", a, GETWORD(val));
2183 static unsigned long mskip = 0x1000;
2184 static unsigned long mlim = 0xffffffff;
2194 if (termch != '\n') termch = 0;
2196 if (termch != '\n') termch = 0;
2199 for (a = mdest; a < mlim; a += mskip) {
2200 ok = mread(a, &v, 1);
2202 printf("%.8x .. ", a);
2203 } else if (!ok && ook)
2204 printf("%.8x\n", a - mskip);
2210 printf("%.8x\n", a - mskip);
2215 unsigned long args[8];
2218 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2219 unsigned long, unsigned long, unsigned long,
2220 unsigned long, unsigned long, unsigned long);
2223 if (!scanhex(&adrs))
2227 for (i = 0; i < 8; ++i)
2229 for (i = 0; i < 8; ++i) {
2230 if (!scanhex(&args[i]) || termch == '\n')
2234 func = (callfunc_t) adrs;
2236 if (setjmp(bus_error_jmp) == 0) {
2237 catch_memory_errors = 1;
2239 ret = func(args[0], args[1], args[2], args[3],
2240 args[4], args[5], args[6], args[7]);
2242 printf("return value is %x\n", ret);
2244 printf("*** %x exception occurred\n", fault_except);
2246 catch_memory_errors = 0;
2249 /* Input scanning routines */
2260 while( c == ' ' || c == '\t' )
2266 static char *regnames[N_PTREGS] = {
2267 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2268 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2269 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2270 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2271 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2277 "trap", "dar", "dsisr", "res"
2281 scanhex(unsigned long *vp)
2288 /* parse register name */
2292 for (i = 0; i < sizeof(regname) - 1; ++i) {
2301 for (i = 0; i < N_PTREGS; ++i) {
2302 if (strcmp(regnames[i], regname) == 0) {
2303 if (xmon_regs == NULL) {
2304 printf("regs not available\n");
2307 *vp = ((unsigned long *)xmon_regs)[i];
2311 printf("invalid register name '%%%s'\n", regname);
2315 /* skip leading "0x" if any */
2329 } else if (c == '$') {
2331 for (i=0; i<63; i++) {
2341 if (setjmp(bus_error_jmp) == 0) {
2342 catch_memory_errors = 1;
2344 *vp = kallsyms_lookup_name(tmpstr);
2347 catch_memory_errors = 0;
2349 printf("unknown symbol '%s'\n", tmpstr);
2384 if( '0' <= c && c <= '9' )
2386 if( 'A' <= c && c <= 'F' )
2387 return c - ('A' - 10);
2388 if( 'a' <= c && c <= 'f' )
2389 return c - ('a' - 10);
2394 getstring(char *s, int size)
2405 } while( c != ' ' && c != '\t' && c != '\n' );
2410 static char line[256];
2411 static char *lineptr;
2422 if (lineptr == NULL || *lineptr == 0) {
2423 if (xmon_gets(line, sizeof(line)) == NULL) {
2433 take_input(char *str)
2442 int type = inchar();
2444 static char tmp[64];
2449 xmon_print_symbol(addr, ": ", "\n");
2454 if (setjmp(bus_error_jmp) == 0) {
2455 catch_memory_errors = 1;
2457 addr = kallsyms_lookup_name(tmp);
2459 printf("%s: %lx\n", tmp, addr);
2461 printf("Symbol '%s' not found.\n", tmp);
2464 catch_memory_errors = 0;
2471 /* Print an address in numeric and symbolic form (if possible) */
2472 static void xmon_print_symbol(unsigned long address, const char *mid,
2476 const char *name = NULL;
2477 unsigned long offset, size;
2479 printf(REG, address);
2480 if (setjmp(bus_error_jmp) == 0) {
2481 catch_memory_errors = 1;
2483 name = kallsyms_lookup(address, &size, &offset, &modname,
2486 /* wait a little while to see if we get a machine check */
2490 catch_memory_errors = 0;
2493 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2495 printf(" [%s]", modname);
2497 printf("%s", after);
2501 static void dump_slb(void)
2506 printf("SLB contents of cpu %x\n", smp_processor_id());
2508 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2509 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2510 printf("%02d %016lx ", i, tmp);
2512 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2513 printf("%016lx\n", tmp);
2517 static void dump_stab(void)
2520 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2522 printf("Segment table contents of cpu %x\n", smp_processor_id());
2524 for (i = 0; i < PAGE_SIZE/16; i++) {
2531 printf("%03d %016lx ", i, a);
2532 printf("%016lx\n", b);
2537 void dump_segments(void)
2539 if (cpu_has_feature(CPU_FTR_SLB))
2546 #ifdef CONFIG_PPC_STD_MMU_32
2547 void dump_segments(void)
2552 for (i = 0; i < 16; ++i)
2553 printf(" %x", mfsrin(i));
2558 void xmon_init(int enable)
2562 __debugger_ipi = xmon_ipi;
2563 __debugger_bpt = xmon_bpt;
2564 __debugger_sstep = xmon_sstep;
2565 __debugger_iabr_match = xmon_iabr_match;
2566 __debugger_dabr_match = xmon_dabr_match;
2567 __debugger_fault_handler = xmon_fault_handler;
2570 __debugger_ipi = NULL;
2571 __debugger_bpt = NULL;
2572 __debugger_sstep = NULL;
2573 __debugger_iabr_match = NULL;
2574 __debugger_dabr_match = NULL;
2575 __debugger_fault_handler = NULL;
2580 #ifdef CONFIG_MAGIC_SYSRQ
2581 static void sysrq_handle_xmon(int key, struct tty_struct *tty)
2583 /* ensure xmon is enabled */
2585 debugger(get_irq_regs());
2588 static struct sysrq_key_op sysrq_xmon_op =
2590 .handler = sysrq_handle_xmon,
2592 .action_msg = "Entering xmon",
2595 static int __init setup_xmon_sysrq(void)
2597 register_sysrq_key('x', &sysrq_xmon_op);
2600 __initcall(setup_xmon_sysrq);
2601 #endif /* CONFIG_MAGIC_SYSRQ */
2603 int __initdata xmon_early, xmon_off;
2605 static int __init early_parse_xmon(char *p)
2607 if (!p || strncmp(p, "early", 5) == 0) {
2608 /* just "xmon" is equivalent to "xmon=early" */
2611 } else if (strncmp(p, "on", 2) == 0)
2613 else if (strncmp(p, "off", 3) == 0)
2615 else if (strncmp(p, "nobt", 4) == 0)
2616 xmon_no_auto_backtrace = 1;
2622 early_param("xmon", early_parse_xmon);
2624 void __init xmon_setup(void)
2626 #ifdef CONFIG_XMON_DEFAULT