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>
25 #include <asm/ptrace.h>
26 #include <asm/string.h>
28 #include <asm/machdep.h>
30 #include <asm/processor.h>
31 #include <asm/pgtable.h>
33 #include <asm/mmu_context.h>
34 #include <asm/cputable.h>
36 #include <asm/sstep.h>
40 #include <asm/hvcall.h>
46 #define scanhex xmon_scanhex
47 #define skipbl xmon_skipbl
50 cpumask_t cpus_in_xmon = CPU_MASK_NONE;
51 static unsigned long xmon_taken = 1;
52 static int xmon_owner;
54 #endif /* CONFIG_SMP */
56 static unsigned long in_xmon = 0;
58 static unsigned long adrs;
60 #define MAX_DUMP (128 * 1024)
61 static unsigned long ndump = 64;
62 static unsigned long nidump = 16;
63 static unsigned long ncsum = 4096;
65 static char tmpstr[128];
67 #define JMP_BUF_LEN 23
68 static long bus_error_jmp[JMP_BUF_LEN];
69 static int catch_memory_errors;
70 static long *xmon_fault_jmp[NR_CPUS];
71 #define setjmp xmon_setjmp
72 #define longjmp xmon_longjmp
74 /* Breakpoint stuff */
76 unsigned long address;
77 unsigned int instr[2];
83 /* Bits in bpt.enabled */
84 #define BP_IABR_TE 1 /* IABR translation enabled */
90 static struct bpt bpts[NBPTS];
91 static struct bpt dabr;
92 static struct bpt *iabr;
93 static unsigned bpinstr = 0x7fe00008; /* trap */
95 #define BP_NUM(bp) ((bp) - bpts + 1)
98 static int cmds(struct pt_regs *);
99 static int mread(unsigned long, void *, int);
100 static int mwrite(unsigned long, void *, int);
101 static int handle_fault(struct pt_regs *);
102 static void byterev(unsigned char *, int);
103 static void memex(void);
104 static int bsesc(void);
105 static void dump(void);
106 static void prdump(unsigned long, long);
107 static int ppc_inst_dump(unsigned long, long, int);
108 void print_address(unsigned long);
109 static void backtrace(struct pt_regs *);
110 static void excprint(struct pt_regs *);
111 static void prregs(struct pt_regs *);
112 static void memops(int);
113 static void memlocate(void);
114 static void memzcan(void);
115 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
117 int scanhex(unsigned long *valp);
118 static void scannl(void);
119 static int hexdigit(int);
120 void getstring(char *, int);
121 static void flush_input(void);
122 static int inchar(void);
123 static void take_input(char *);
124 static unsigned long read_spr(int);
125 static void write_spr(int, unsigned long);
126 static void super_regs(void);
127 static void remove_bpts(void);
128 static void insert_bpts(void);
129 static void remove_cpu_bpts(void);
130 static void insert_cpu_bpts(void);
131 static struct bpt *at_breakpoint(unsigned long pc);
132 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
133 static int do_step(struct pt_regs *);
134 static void bpt_cmds(void);
135 static void cacheflush(void);
136 static int cpu_cmd(void);
137 static void csum(void);
138 static void bootcmds(void);
139 static void proccall(void);
140 void dump_segments(void);
141 static void symbol_lookup(void);
142 static void xmon_show_stack(unsigned long sp, unsigned long lr,
144 static void xmon_print_symbol(unsigned long address, const char *mid,
146 static const char *getvecname(unsigned long vec);
148 int xmon_no_auto_backtrace;
150 extern int print_insn_powerpc(unsigned long, unsigned long, int);
152 extern void xmon_enter(void);
153 extern void xmon_leave(void);
155 extern long setjmp(long *);
156 extern void longjmp(long *, long);
157 extern void xmon_save_regs(struct pt_regs *);
161 #define REGS_PER_LINE 4
162 #define LAST_VOLATILE 13
165 #define REGS_PER_LINE 8
166 #define LAST_VOLATILE 12
169 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
171 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
172 || ('a' <= (c) && (c) <= 'f') \
173 || ('A' <= (c) && (c) <= 'F'))
174 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
175 || ('a' <= (c) && (c) <= 'z') \
176 || ('A' <= (c) && (c) <= 'Z'))
177 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
179 static char *help_string = "\
181 b show breakpoints\n\
182 bd set data breakpoint\n\
183 bi set instruction breakpoint\n\
184 bc clear breakpoint\n"
187 c print cpus stopped in xmon\n\
188 c# try to switch to cpu number h (in hex)\n"
193 di dump instructions\n\
194 df dump float values\n\
195 dd dump double values\n\
196 dr dump stream of raw bytes\n\
197 e print exception information\n\
199 la lookup symbol+offset of specified address\n\
200 ls lookup address of specified symbol\n\
201 m examine/change memory\n\
202 mm move a block of memory\n\
203 ms set a block of memory\n\
204 md compare two blocks of memory\n\
205 ml locate a block of memory\n\
206 mz zero a block of memory\n\
207 mi show information about memory allocation\n\
208 p call a procedure\n\
211 S print special registers\n\
213 x exit monitor and recover\n\
214 X exit monitor and dont recover\n"
216 " u dump segment table or SLB\n"
218 #ifdef CONFIG_PPC_STD_MMU_32
219 " u dump segment registers\n"
226 static struct pt_regs *xmon_regs;
228 static inline void sync(void)
230 asm volatile("sync; isync");
233 static inline void store_inst(void *p)
235 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
238 static inline void cflush(void *p)
240 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
243 static inline void cinval(void *p)
245 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
249 * Disable surveillance (the service processor watchdog function)
250 * while we are in xmon.
251 * XXX we should re-enable it when we leave. :)
253 #define SURVEILLANCE_TOKEN 9000
255 static inline void disable_surveillance(void)
257 #ifdef CONFIG_PPC_PSERIES
258 /* Since this can't be a module, args should end up below 4GB. */
259 static struct rtas_args args;
262 * At this point we have got all the cpus we can into
263 * xmon, so there is hopefully no other cpu calling RTAS
264 * at the moment, even though we don't take rtas.lock.
265 * If we did try to take rtas.lock there would be a
266 * real possibility of deadlock.
268 args.token = rtas_token("set-indicator");
269 if (args.token == RTAS_UNKNOWN_SERVICE)
273 args.rets = &args.args[3];
274 args.args[0] = SURVEILLANCE_TOKEN;
277 enter_rtas(__pa(&args));
278 #endif /* CONFIG_PPC_PSERIES */
282 static int xmon_speaker;
284 static void get_output_lock(void)
286 int me = smp_processor_id() + 0x100;
287 int last_speaker = 0, prev;
290 if (xmon_speaker == me)
293 if (xmon_speaker == 0) {
294 last_speaker = cmpxchg(&xmon_speaker, 0, me);
295 if (last_speaker == 0)
299 while (xmon_speaker == last_speaker) {
302 /* hostile takeover */
303 prev = cmpxchg(&xmon_speaker, last_speaker, me);
304 if (prev == last_speaker)
311 static void release_output_lock(void)
317 static int xmon_core(struct pt_regs *regs, int fromipi)
322 long recurse_jmp[JMP_BUF_LEN];
323 unsigned long offset;
327 unsigned long timeout;
331 mtmsr(msr & ~MSR_EE); /* disable interrupts */
333 bp = in_breakpoint_table(regs->nip, &offset);
335 regs->nip = bp->address + offset;
336 atomic_dec(&bp->ref_count);
342 cpu = smp_processor_id();
343 if (cpu_isset(cpu, cpus_in_xmon)) {
346 printf("cpu 0x%x: Exception %lx %s in xmon, "
347 "returning to main loop\n",
348 cpu, regs->trap, getvecname(TRAP(regs)));
349 release_output_lock();
350 longjmp(xmon_fault_jmp[cpu], 1);
353 if (setjmp(recurse_jmp) != 0) {
354 if (!in_xmon || !xmon_gate) {
356 printf("xmon: WARNING: bad recursive fault "
357 "on cpu 0x%x\n", cpu);
358 release_output_lock();
361 secondary = !(xmon_taken && cpu == xmon_owner);
365 xmon_fault_jmp[cpu] = recurse_jmp;
366 cpu_set(cpu, cpus_in_xmon);
369 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
370 bp = at_breakpoint(regs->nip);
371 if (bp || (regs->msr & MSR_RI) == 0)
378 printf("cpu 0x%x stopped at breakpoint 0x%x (",
380 xmon_print_symbol(regs->nip, " ", ")\n");
382 if ((regs->msr & MSR_RI) == 0)
383 printf("WARNING: exception is not recoverable, "
385 release_output_lock();
390 while (secondary && !xmon_gate) {
394 secondary = test_and_set_bit(0, &in_xmon);
399 if (!secondary && !xmon_gate) {
400 /* we are the first cpu to come in */
401 /* interrupt other cpu(s) */
402 int ncpus = num_online_cpus();
407 smp_send_debugger_break(MSG_ALL_BUT_SELF);
408 /* wait for other cpus to come in */
409 for (timeout = 100000000; timeout != 0; --timeout) {
410 if (cpus_weight(cpus_in_xmon) >= ncpus)
416 disable_surveillance();
417 /* for breakpoint or single step, print the current instr. */
418 if (bp || TRAP(regs) == 0xd00)
419 ppc_inst_dump(regs->nip, 1, 0);
420 printf("enter ? for help\n");
429 if (cpu == xmon_owner) {
430 if (!test_and_set_bit(0, &xmon_taken)) {
435 while (cpu == xmon_owner)
449 /* have switched to some other cpu */
454 cpu_clear(cpu, cpus_in_xmon);
455 xmon_fault_jmp[cpu] = NULL;
457 /* UP is simple... */
459 printf("Exception %lx %s in xmon, returning to main loop\n",
460 regs->trap, getvecname(TRAP(regs)));
461 longjmp(xmon_fault_jmp[0], 1);
463 if (setjmp(recurse_jmp) == 0) {
464 xmon_fault_jmp[0] = recurse_jmp;
468 bp = at_breakpoint(regs->nip);
470 printf("Stopped at breakpoint %x (", BP_NUM(bp));
471 xmon_print_symbol(regs->nip, " ", ")\n");
473 if ((regs->msr & MSR_RI) == 0)
474 printf("WARNING: exception is not recoverable, "
477 disable_surveillance();
478 /* for breakpoint or single step, print the current instr. */
479 if (bp || TRAP(regs) == 0xd00)
480 ppc_inst_dump(regs->nip, 1, 0);
481 printf("enter ? for help\n");
490 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
491 bp = at_breakpoint(regs->nip);
493 int stepped = emulate_step(regs, bp->instr[0]);
495 regs->nip = (unsigned long) &bp->instr[0];
496 atomic_inc(&bp->ref_count);
497 } else if (stepped < 0) {
498 printf("Couldn't single-step %s instruction\n",
499 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
506 mtmsr(msr); /* restore interrupt enable */
508 return cmd != 'X' && cmd != EOF;
511 int xmon(struct pt_regs *excp)
516 xmon_save_regs(®s);
519 return xmon_core(excp, 0);
524 xmon_irq(int irq, void *d, struct pt_regs *regs)
527 local_irq_save(flags);
528 printf("Keyboard interrupt\n");
530 local_irq_restore(flags);
534 static int xmon_bpt(struct pt_regs *regs)
537 unsigned long offset;
539 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
542 /* Are we at the trap at bp->instr[1] for some bp? */
543 bp = in_breakpoint_table(regs->nip, &offset);
544 if (bp != NULL && offset == 4) {
545 regs->nip = bp->address + 4;
546 atomic_dec(&bp->ref_count);
550 /* Are we at a breakpoint? */
551 bp = at_breakpoint(regs->nip);
560 static int xmon_sstep(struct pt_regs *regs)
568 static int xmon_dabr_match(struct pt_regs *regs)
570 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
572 if (dabr.enabled == 0)
578 static int xmon_iabr_match(struct pt_regs *regs)
580 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
588 static int xmon_ipi(struct pt_regs *regs)
591 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
597 static int xmon_fault_handler(struct pt_regs *regs)
600 unsigned long offset;
602 if (in_xmon && catch_memory_errors)
603 handle_fault(regs); /* doesn't return */
605 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
606 bp = in_breakpoint_table(regs->nip, &offset);
608 regs->nip = bp->address + offset;
609 atomic_dec(&bp->ref_count);
616 static struct bpt *at_breakpoint(unsigned long pc)
622 for (i = 0; i < NBPTS; ++i, ++bp)
623 if (bp->enabled && pc == bp->address)
628 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
632 off = nip - (unsigned long) bpts;
633 if (off >= sizeof(bpts))
635 off %= sizeof(struct bpt);
636 if (off != offsetof(struct bpt, instr[0])
637 && off != offsetof(struct bpt, instr[1]))
639 *offp = off - offsetof(struct bpt, instr[0]);
640 return (struct bpt *) (nip - off);
643 static struct bpt *new_breakpoint(unsigned long a)
648 bp = at_breakpoint(a);
652 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
653 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
655 bp->instr[1] = bpinstr;
656 store_inst(&bp->instr[1]);
661 printf("Sorry, no free breakpoints. Please clear one first.\n");
665 static void insert_bpts(void)
671 for (i = 0; i < NBPTS; ++i, ++bp) {
672 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
674 if (mread(bp->address, &bp->instr[0], 4) != 4) {
675 printf("Couldn't read instruction at %lx, "
676 "disabling breakpoint there\n", bp->address);
680 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
681 printf("Breakpoint at %lx is on an mtmsrd or rfid "
682 "instruction, disabling it\n", bp->address);
686 store_inst(&bp->instr[0]);
687 if (bp->enabled & BP_IABR)
689 if (mwrite(bp->address, &bpinstr, 4) != 4) {
690 printf("Couldn't write instruction at %lx, "
691 "disabling breakpoint there\n", bp->address);
692 bp->enabled &= ~BP_TRAP;
695 store_inst((void *)bp->address);
699 static void insert_cpu_bpts(void)
702 set_dabr(dabr.address | (dabr.enabled & 7));
703 if (iabr && cpu_has_feature(CPU_FTR_IABR))
704 mtspr(SPRN_IABR, iabr->address
705 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
708 static void remove_bpts(void)
715 for (i = 0; i < NBPTS; ++i, ++bp) {
716 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
718 if (mread(bp->address, &instr, 4) == 4
720 && mwrite(bp->address, &bp->instr, 4) != 4)
721 printf("Couldn't remove breakpoint at %lx\n",
724 store_inst((void *)bp->address);
728 static void remove_cpu_bpts(void)
731 if (cpu_has_feature(CPU_FTR_IABR))
735 /* Command interpreting routine */
736 static char *last_cmd;
739 cmds(struct pt_regs *excp)
746 if (!xmon_no_auto_backtrace) {
747 xmon_no_auto_backtrace = 1;
748 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
753 printf("%x:", smp_processor_id());
754 #endif /* CONFIG_SMP */
760 if (last_cmd == NULL)
762 take_input(last_cmd);
796 prregs(excp); /* print regs */
818 printf(" <no input ...>\n");
840 #ifdef CONFIG_PPC_STD_MMU
846 printf("Unrecognized command: ");
848 if (' ' < cmd && cmd <= '~')
851 printf("\\x%x", cmd);
853 } while (cmd != '\n');
854 printf(" (type ? for help)\n");
861 * Step a single instruction.
862 * Some instructions we emulate, others we execute with MSR_SE set.
864 static int do_step(struct pt_regs *regs)
869 /* check we are in 64-bit kernel mode, translation enabled */
870 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
871 if (mread(regs->nip, &instr, 4) == 4) {
872 stepped = emulate_step(regs, instr);
874 printf("Couldn't single-step %s instruction\n",
875 (IS_RFID(instr)? "rfid": "mtmsrd"));
879 regs->trap = 0xd00 | (regs->trap & 1);
880 printf("stepped to ");
881 xmon_print_symbol(regs->nip, " ", "\n");
882 ppc_inst_dump(regs->nip, 1, 0);
891 static void bootcmds(void)
897 ppc_md.restart(NULL);
904 static int cpu_cmd(void)
911 if (!scanhex(&cpu)) {
912 /* print cpus waiting or in xmon */
913 printf("cpus stopped:");
915 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
916 if (cpu_isset(cpu, cpus_in_xmon)) {
922 printf("-%x", cpu - 1);
927 printf("-%x", NR_CPUS - 1);
931 /* try to switch to cpu specified */
932 if (!cpu_isset(cpu, cpus_in_xmon)) {
933 printf("cpu 0x%x isn't in xmon\n", cpu);
940 while (!xmon_taken) {
941 if (--timeout == 0) {
942 if (test_and_set_bit(0, &xmon_taken))
944 /* take control back */
946 xmon_owner = smp_processor_id();
947 printf("cpu %u didn't take control\n", cpu);
955 #endif /* CONFIG_SMP */
958 static unsigned short fcstab[256] = {
959 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
960 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
961 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
962 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
963 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
964 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
965 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
966 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
967 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
968 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
969 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
970 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
971 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
972 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
973 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
974 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
975 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
976 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
977 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
978 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
979 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
980 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
981 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
982 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
983 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
984 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
985 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
986 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
987 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
988 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
989 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
990 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
993 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1002 if (!scanhex(&adrs))
1004 if (!scanhex(&ncsum))
1007 for (i = 0; i < ncsum; ++i) {
1008 if (mread(adrs+i, &v, 1) == 0) {
1009 printf("csum stopped at %x\n", adrs+i);
1014 printf("%x\n", fcs);
1018 * Check if this is a suitable place to put a breakpoint.
1020 static long check_bp_loc(unsigned long addr)
1025 if (!is_kernel_addr(addr)) {
1026 printf("Breakpoints may only be placed at kernel addresses\n");
1029 if (!mread(addr, &instr, sizeof(instr))) {
1030 printf("Can't read instruction at address %lx\n", addr);
1033 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1034 printf("Breakpoints may not be placed on mtmsrd or rfid "
1041 static char *breakpoint_help_string =
1042 "Breakpoint command usage:\n"
1043 "b show breakpoints\n"
1044 "b <addr> [cnt] set breakpoint at given instr addr\n"
1045 "bc clear all breakpoints\n"
1046 "bc <n/addr> clear breakpoint number n or at addr\n"
1047 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1048 "bd <addr> [cnt] set hardware data breakpoint\n"
1058 const char badaddr[] = "Only kernel addresses are permitted "
1059 "for breakpoints\n";
1064 case 'd': /* bd - hardware data breakpoint */
1069 else if (cmd == 'w')
1075 if (scanhex(&dabr.address)) {
1076 if (!is_kernel_addr(dabr.address)) {
1081 dabr.enabled = mode | BP_DABR;
1085 case 'i': /* bi - hardware instr breakpoint */
1086 if (!cpu_has_feature(CPU_FTR_IABR)) {
1087 printf("Hardware instruction breakpoint "
1088 "not supported on this cpu\n");
1092 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1097 if (!check_bp_loc(a))
1099 bp = new_breakpoint(a);
1101 bp->enabled |= BP_IABR | BP_IABR_TE;
1109 /* clear all breakpoints */
1110 for (i = 0; i < NBPTS; ++i)
1111 bpts[i].enabled = 0;
1114 printf("All breakpoints cleared\n");
1118 if (a <= NBPTS && a >= 1) {
1119 /* assume a breakpoint number */
1120 bp = &bpts[a-1]; /* bp nums are 1 based */
1122 /* assume a breakpoint address */
1123 bp = at_breakpoint(a);
1125 printf("No breakpoint at %x\n", a);
1130 printf("Cleared breakpoint %x (", BP_NUM(bp));
1131 xmon_print_symbol(bp->address, " ", ")\n");
1139 printf(breakpoint_help_string);
1144 /* print all breakpoints */
1145 printf(" type address\n");
1147 printf(" data "REG" [", dabr.address);
1148 if (dabr.enabled & 1)
1150 if (dabr.enabled & 2)
1154 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1157 printf("%2x %s ", BP_NUM(bp),
1158 (bp->enabled & BP_IABR)? "inst": "trap");
1159 xmon_print_symbol(bp->address, " ", "\n");
1164 if (!check_bp_loc(a))
1166 bp = new_breakpoint(a);
1168 bp->enabled |= BP_TRAP;
1173 /* Very cheap human name for vector lookup. */
1175 const char *getvecname(unsigned long vec)
1180 case 0x100: ret = "(System Reset)"; break;
1181 case 0x200: ret = "(Machine Check)"; break;
1182 case 0x300: ret = "(Data Access)"; break;
1183 case 0x380: ret = "(Data SLB Access)"; break;
1184 case 0x400: ret = "(Instruction Access)"; break;
1185 case 0x480: ret = "(Instruction SLB Access)"; break;
1186 case 0x500: ret = "(Hardware Interrupt)"; break;
1187 case 0x600: ret = "(Alignment)"; break;
1188 case 0x700: ret = "(Program Check)"; break;
1189 case 0x800: ret = "(FPU Unavailable)"; break;
1190 case 0x900: ret = "(Decrementer)"; break;
1191 case 0xc00: ret = "(System Call)"; break;
1192 case 0xd00: ret = "(Single Step)"; break;
1193 case 0xf00: ret = "(Performance Monitor)"; break;
1194 case 0xf20: ret = "(Altivec Unavailable)"; break;
1195 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1201 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1202 unsigned long *endp)
1204 unsigned long size, offset;
1208 *startp = *endp = 0;
1211 if (setjmp(bus_error_jmp) == 0) {
1212 catch_memory_errors = 1;
1214 name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
1216 *startp = pc - offset;
1217 *endp = pc - offset + size;
1221 catch_memory_errors = 0;
1224 static int xmon_depth_to_print = 64;
1227 #define LRSAVE_OFFSET 0x10
1228 #define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
1229 #define MARKER_OFFSET 0x60
1230 #define REGS_OFFSET 0x70
1232 #define LRSAVE_OFFSET 4
1233 #define REG_FRAME_MARKER 0x72656773
1234 #define MARKER_OFFSET 8
1235 #define REGS_OFFSET 16
1238 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1242 unsigned long newsp;
1243 unsigned long marker;
1245 struct pt_regs regs;
1248 if (sp < PAGE_OFFSET) {
1250 printf("SP (%lx) is in userspace\n", sp);
1254 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1255 || !mread(sp, &newsp, sizeof(unsigned long))) {
1256 printf("Couldn't read stack frame at %lx\n", sp);
1261 * For the first stack frame, try to work out if
1262 * LR and/or the saved LR value in the bottommost
1263 * stack frame are valid.
1265 if ((pc | lr) != 0) {
1266 unsigned long fnstart, fnend;
1267 unsigned long nextip;
1270 get_function_bounds(pc, &fnstart, &fnend);
1273 mread(newsp + LRSAVE_OFFSET, &nextip,
1274 sizeof(unsigned long));
1276 if (lr < PAGE_OFFSET
1277 || (fnstart <= lr && lr < fnend))
1279 } else if (lr == nextip) {
1281 } else if (lr >= PAGE_OFFSET
1282 && !(fnstart <= lr && lr < fnend)) {
1283 printf("[link register ] ");
1284 xmon_print_symbol(lr, " ", "\n");
1287 printf("["REG"] ", sp);
1288 xmon_print_symbol(ip, " ", " (unreliable)\n");
1293 printf("["REG"] ", sp);
1294 xmon_print_symbol(ip, " ", "\n");
1297 /* Look for "regshere" marker to see if this is
1298 an exception frame. */
1299 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1300 && marker == REG_FRAME_MARKER) {
1301 if (mread(sp + REGS_OFFSET, ®s, sizeof(regs))
1303 printf("Couldn't read registers at %lx\n",
1307 printf("--- Exception: %lx %s at ", regs.trap,
1308 getvecname(TRAP(®s)));
1311 xmon_print_symbol(pc, " ", "\n");
1318 } while (count++ < xmon_depth_to_print);
1321 static void backtrace(struct pt_regs *excp)
1326 xmon_show_stack(sp, 0, 0);
1328 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1332 static void print_bug_trap(struct pt_regs *regs)
1334 struct bug_entry *bug;
1337 if (regs->msr & MSR_PR)
1338 return; /* not in kernel */
1339 addr = regs->nip; /* address of trap instruction */
1340 if (addr < PAGE_OFFSET)
1342 bug = find_bug(regs->nip);
1345 if (bug->line & BUG_WARNING_TRAP)
1348 printf("kernel BUG in %s at %s:%d!\n",
1349 bug->function, bug->file, (unsigned int)bug->line);
1352 void excprint(struct pt_regs *fp)
1357 printf("cpu 0x%x: ", smp_processor_id());
1358 #endif /* CONFIG_SMP */
1361 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1363 xmon_print_symbol(fp->nip, ": ", "\n");
1365 printf(" lr: ", fp->link);
1366 xmon_print_symbol(fp->link, ": ", "\n");
1368 printf(" sp: %lx\n", fp->gpr[1]);
1369 printf(" msr: %lx\n", fp->msr);
1371 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1372 printf(" dar: %lx\n", fp->dar);
1374 printf(" dsisr: %lx\n", fp->dsisr);
1377 printf(" current = 0x%lx\n", current);
1379 printf(" paca = 0x%lx\n", get_paca());
1382 printf(" pid = %ld, comm = %s\n",
1383 current->pid, current->comm);
1390 void prregs(struct pt_regs *fp)
1394 struct pt_regs regs;
1396 if (scanhex(&base)) {
1397 if (setjmp(bus_error_jmp) == 0) {
1398 catch_memory_errors = 1;
1400 regs = *(struct pt_regs *)base;
1404 catch_memory_errors = 0;
1405 printf("*** Error reading registers from "REG"\n",
1409 catch_memory_errors = 0;
1414 if (FULL_REGS(fp)) {
1415 for (n = 0; n < 16; ++n)
1416 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1417 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1419 for (n = 0; n < 7; ++n)
1420 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1421 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1424 for (n = 0; n < 32; ++n) {
1425 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1426 (n & 3) == 3? "\n": " ");
1427 if (n == 12 && !FULL_REGS(fp)) {
1434 xmon_print_symbol(fp->nip, " ", "\n");
1436 xmon_print_symbol(fp->link, " ", "\n");
1437 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1438 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1439 fp->ctr, fp->xer, fp->trap);
1441 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1442 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1445 void cacheflush(void)
1448 unsigned long nflush;
1453 scanhex((void *)&adrs);
1458 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1459 if (setjmp(bus_error_jmp) == 0) {
1460 catch_memory_errors = 1;
1464 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1465 cflush((void *) adrs);
1467 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1468 cinval((void *) adrs);
1471 /* wait a little while to see if we get a machine check */
1474 catch_memory_errors = 0;
1480 unsigned int instrs[2];
1481 unsigned long (*code)(void);
1482 unsigned long ret = -1UL;
1484 unsigned long opd[3];
1486 opd[0] = (unsigned long)instrs;
1489 code = (unsigned long (*)(void)) opd;
1491 code = (unsigned long (*)(void)) instrs;
1494 /* mfspr r3,n; blr */
1495 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1496 instrs[1] = 0x4e800020;
1498 store_inst(instrs+1);
1500 if (setjmp(bus_error_jmp) == 0) {
1501 catch_memory_errors = 1;
1507 /* wait a little while to see if we get a machine check */
1516 write_spr(int n, unsigned long val)
1518 unsigned int instrs[2];
1519 unsigned long (*code)(unsigned long);
1521 unsigned long opd[3];
1523 opd[0] = (unsigned long)instrs;
1526 code = (unsigned long (*)(unsigned long)) opd;
1528 code = (unsigned long (*)(unsigned long)) instrs;
1531 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1532 instrs[1] = 0x4e800020;
1534 store_inst(instrs+1);
1536 if (setjmp(bus_error_jmp) == 0) {
1537 catch_memory_errors = 1;
1543 /* wait a little while to see if we get a machine check */
1549 static unsigned long regno;
1550 extern char exc_prolog;
1551 extern char dec_exc;
1553 void super_regs(void)
1557 #ifdef CONFIG_PPC_ISERIES
1558 struct paca_struct *ptrPaca = NULL;
1559 struct lppaca *ptrLpPaca = NULL;
1560 struct ItLpRegSave *ptrLpRegSave = NULL;
1565 unsigned long sp, toc;
1566 asm("mr %0,1" : "=r" (sp) :);
1567 asm("mr %0,2" : "=r" (toc) :);
1569 printf("msr = "REG" sprg0= "REG"\n",
1570 mfmsr(), mfspr(SPRN_SPRG0));
1571 printf("pvr = "REG" sprg1= "REG"\n",
1572 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1573 printf("dec = "REG" sprg2= "REG"\n",
1574 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1575 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1576 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1577 #ifdef CONFIG_PPC_ISERIES
1578 // Dump out relevant Paca data areas.
1580 ptrPaca = get_paca();
1582 printf(" Local Processor Control Area (LpPaca): \n");
1583 ptrLpPaca = ptrPaca->lppaca_ptr;
1584 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1585 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1586 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1587 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1588 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1590 printf(" Local Processor Register Save Area (LpRegSave): \n");
1591 ptrLpRegSave = ptrPaca->reg_save_ptr;
1592 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1593 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1594 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1595 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1596 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1597 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1606 val = read_spr(regno);
1608 write_spr(regno, val);
1611 printf("spr %lx = %lx\n", regno, read_spr(regno));
1618 * Stuff for reading and writing memory safely
1621 mread(unsigned long adrs, void *buf, int size)
1627 if (setjmp(bus_error_jmp) == 0) {
1628 catch_memory_errors = 1;
1634 *(u16 *)q = *(u16 *)p;
1637 *(u32 *)q = *(u32 *)p;
1640 *(u64 *)q = *(u64 *)p;
1643 for( ; n < size; ++n) {
1649 /* wait a little while to see if we get a machine check */
1653 catch_memory_errors = 0;
1658 mwrite(unsigned long adrs, void *buf, int size)
1664 if (setjmp(bus_error_jmp) == 0) {
1665 catch_memory_errors = 1;
1671 *(u16 *)p = *(u16 *)q;
1674 *(u32 *)p = *(u32 *)q;
1677 *(u64 *)p = *(u64 *)q;
1680 for ( ; n < size; ++n) {
1686 /* wait a little while to see if we get a machine check */
1690 printf("*** Error writing address %x\n", adrs + n);
1692 catch_memory_errors = 0;
1696 static int fault_type;
1697 static int fault_except;
1698 static char *fault_chars[] = { "--", "**", "##" };
1700 static int handle_fault(struct pt_regs *regs)
1702 fault_except = TRAP(regs);
1703 switch (TRAP(regs)) {
1715 longjmp(bus_error_jmp, 1);
1720 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1723 byterev(unsigned char *val, int size)
1729 SWAP(val[0], val[1], t);
1732 SWAP(val[0], val[3], t);
1733 SWAP(val[1], val[2], t);
1735 case 8: /* is there really any use for this? */
1736 SWAP(val[0], val[7], t);
1737 SWAP(val[1], val[6], t);
1738 SWAP(val[2], val[5], t);
1739 SWAP(val[3], val[4], t);
1747 static char *memex_help_string =
1748 "Memory examine command usage:\n"
1749 "m [addr] [flags] examine/change memory\n"
1750 " addr is optional. will start where left off.\n"
1751 " flags may include chars from this set:\n"
1752 " b modify by bytes (default)\n"
1753 " w modify by words (2 byte)\n"
1754 " l modify by longs (4 byte)\n"
1755 " d modify by doubleword (8 byte)\n"
1756 " r toggle reverse byte order mode\n"
1757 " n do not read memory (for i/o spaces)\n"
1758 " . ok to read (default)\n"
1759 "NOTE: flags are saved as defaults\n"
1762 static char *memex_subcmd_help_string =
1763 "Memory examine subcommands:\n"
1764 " hexval write this val to current location\n"
1765 " 'string' write chars from string to this location\n"
1766 " ' increment address\n"
1767 " ^ decrement address\n"
1768 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1769 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1770 " ` clear no-read flag\n"
1771 " ; stay at this addr\n"
1772 " v change to byte mode\n"
1773 " w change to word (2 byte) mode\n"
1774 " l change to long (4 byte) mode\n"
1775 " u change to doubleword (8 byte) mode\n"
1776 " m addr change current addr\n"
1777 " n toggle no-read flag\n"
1778 " r toggle byte reverse flag\n"
1779 " < count back up count bytes\n"
1780 " > count skip forward count bytes\n"
1781 " x exit this mode\n"
1787 int cmd, inc, i, nslash;
1789 unsigned char val[16];
1791 scanhex((void *)&adrs);
1794 printf(memex_help_string);
1800 while ((cmd = skipbl()) != '\n') {
1802 case 'b': size = 1; break;
1803 case 'w': size = 2; break;
1804 case 'l': size = 4; break;
1805 case 'd': size = 8; break;
1806 case 'r': brev = !brev; break;
1807 case 'n': mnoread = 1; break;
1808 case '.': mnoread = 0; break;
1817 n = mread(adrs, val, size);
1818 printf(REG"%c", adrs, brev? 'r': ' ');
1823 for (i = 0; i < n; ++i)
1824 printf("%.2x", val[i]);
1825 for (; i < size; ++i)
1826 printf("%s", fault_chars[fault_type]);
1833 for (i = 0; i < size; ++i)
1834 val[i] = n >> (i * 8);
1837 mwrite(adrs, val, size);
1850 else if( n == '\'' )
1852 for (i = 0; i < size; ++i)
1853 val[i] = n >> (i * 8);
1856 mwrite(adrs, val, size);
1893 adrs -= 1 << nslash;
1897 adrs += 1 << nslash;
1901 adrs += 1 << -nslash;
1905 adrs -= 1 << -nslash;
1908 scanhex((void *)&adrs);
1927 printf(memex_subcmd_help_string);
1942 case 'n': c = '\n'; break;
1943 case 'r': c = '\r'; break;
1944 case 'b': c = '\b'; break;
1945 case 't': c = '\t'; break;
1950 static void xmon_rawdump (unsigned long adrs, long ndump)
1953 unsigned char temp[16];
1955 for (n = ndump; n > 0;) {
1957 nr = mread(adrs, temp, r);
1959 for (m = 0; m < r; ++m) {
1961 printf("%.2x", temp[m]);
1963 printf("%s", fault_chars[fault_type]);
1972 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1973 || ('a' <= (c) && (c) <= 'f') \
1974 || ('A' <= (c) && (c) <= 'F'))
1981 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1983 scanhex((void *)&adrs);
1990 else if (nidump > MAX_DUMP)
1992 adrs += ppc_inst_dump(adrs, nidump, 1);
1994 } else if (c == 'r') {
1998 xmon_rawdump(adrs, ndump);
2005 else if (ndump > MAX_DUMP)
2007 prdump(adrs, ndump);
2014 prdump(unsigned long adrs, long ndump)
2016 long n, m, c, r, nr;
2017 unsigned char temp[16];
2019 for (n = ndump; n > 0;) {
2023 nr = mread(adrs, temp, r);
2025 for (m = 0; m < r; ++m) {
2026 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2029 printf("%.2x", temp[m]);
2031 printf("%s", fault_chars[fault_type]);
2033 for (; m < 16; ++m) {
2034 if ((m & (sizeof(long) - 1)) == 0)
2039 for (m = 0; m < r; ++m) {
2042 putchar(' ' <= c && c <= '~'? c: '.');
2056 ppc_inst_dump(unsigned long adr, long count, int praddr)
2059 unsigned long first_adr;
2060 unsigned long inst, last_inst = 0;
2061 unsigned char val[4];
2064 for (first_adr = adr; count > 0; --count, adr += 4) {
2065 nr = mread(adr, val, 4);
2068 const char *x = fault_chars[fault_type];
2069 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2073 inst = GETWORD(val);
2074 if (adr > first_adr && inst == last_inst) {
2084 printf(REG" %.8x", adr, inst);
2086 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2089 return adr - first_adr;
2093 print_address(unsigned long addr)
2095 xmon_print_symbol(addr, "\t# ", "");
2100 * Memory operations - move, set, print differences
2102 static unsigned long mdest; /* destination address */
2103 static unsigned long msrc; /* source address */
2104 static unsigned long mval; /* byte value to set memory to */
2105 static unsigned long mcount; /* # bytes to affect */
2106 static unsigned long mdiffs; /* max # differences to print */
2111 scanhex((void *)&mdest);
2112 if( termch != '\n' )
2114 scanhex((void *)(cmd == 's'? &mval: &msrc));
2115 if( termch != '\n' )
2117 scanhex((void *)&mcount);
2120 memmove((void *)mdest, (void *)msrc, mcount);
2123 memset((void *)mdest, mval, mcount);
2126 if( termch != '\n' )
2128 scanhex((void *)&mdiffs);
2129 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2135 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2140 for( n = nb; n > 0; --n )
2141 if( *p1++ != *p2++ )
2142 if( ++prt <= maxpr )
2143 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2144 p1[-1], p2 - 1, p2[-1]);
2146 printf("Total of %d differences\n", prt);
2149 static unsigned mend;
2150 static unsigned mask;
2156 unsigned char val[4];
2159 scanhex((void *)&mdest);
2160 if (termch != '\n') {
2162 scanhex((void *)&mend);
2163 if (termch != '\n') {
2165 scanhex((void *)&mval);
2167 if (termch != '\n') termch = 0;
2168 scanhex((void *)&mask);
2172 for (a = mdest; a < mend; a += 4) {
2173 if (mread(a, val, 4) == 4
2174 && ((GETWORD(val) ^ mval) & mask) == 0) {
2175 printf("%.16x: %.16x\n", a, GETWORD(val));
2182 static unsigned long mskip = 0x1000;
2183 static unsigned long mlim = 0xffffffff;
2193 if (termch != '\n') termch = 0;
2195 if (termch != '\n') termch = 0;
2198 for (a = mdest; a < mlim; a += mskip) {
2199 ok = mread(a, &v, 1);
2201 printf("%.8x .. ", a);
2202 } else if (!ok && ook)
2203 printf("%.8x\n", a - mskip);
2209 printf("%.8x\n", a - mskip);
2214 unsigned long args[8];
2217 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2218 unsigned long, unsigned long, unsigned long,
2219 unsigned long, unsigned long, unsigned long);
2222 if (!scanhex(&adrs))
2226 for (i = 0; i < 8; ++i)
2228 for (i = 0; i < 8; ++i) {
2229 if (!scanhex(&args[i]) || termch == '\n')
2233 func = (callfunc_t) adrs;
2235 if (setjmp(bus_error_jmp) == 0) {
2236 catch_memory_errors = 1;
2238 ret = func(args[0], args[1], args[2], args[3],
2239 args[4], args[5], args[6], args[7]);
2241 printf("return value is %x\n", ret);
2243 printf("*** %x exception occurred\n", fault_except);
2245 catch_memory_errors = 0;
2248 /* Input scanning routines */
2259 while( c == ' ' || c == '\t' )
2265 static char *regnames[N_PTREGS] = {
2266 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2267 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2268 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2269 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2270 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2276 "trap", "dar", "dsisr", "res"
2280 scanhex(unsigned long *vp)
2287 /* parse register name */
2291 for (i = 0; i < sizeof(regname) - 1; ++i) {
2300 for (i = 0; i < N_PTREGS; ++i) {
2301 if (strcmp(regnames[i], regname) == 0) {
2302 if (xmon_regs == NULL) {
2303 printf("regs not available\n");
2306 *vp = ((unsigned long *)xmon_regs)[i];
2310 printf("invalid register name '%%%s'\n", regname);
2314 /* skip leading "0x" if any */
2328 } else if (c == '$') {
2330 for (i=0; i<63; i++) {
2340 if (setjmp(bus_error_jmp) == 0) {
2341 catch_memory_errors = 1;
2343 *vp = kallsyms_lookup_name(tmpstr);
2346 catch_memory_errors = 0;
2348 printf("unknown symbol '%s'\n", tmpstr);
2383 if( '0' <= c && c <= '9' )
2385 if( 'A' <= c && c <= 'F' )
2386 return c - ('A' - 10);
2387 if( 'a' <= c && c <= 'f' )
2388 return c - ('a' - 10);
2393 getstring(char *s, int size)
2404 } while( c != ' ' && c != '\t' && c != '\n' );
2409 static char line[256];
2410 static char *lineptr;
2421 if (lineptr == NULL || *lineptr == 0) {
2422 if (xmon_gets(line, sizeof(line)) == NULL) {
2432 take_input(char *str)
2441 int type = inchar();
2443 static char tmp[64];
2448 xmon_print_symbol(addr, ": ", "\n");
2453 if (setjmp(bus_error_jmp) == 0) {
2454 catch_memory_errors = 1;
2456 addr = kallsyms_lookup_name(tmp);
2458 printf("%s: %lx\n", tmp, addr);
2460 printf("Symbol '%s' not found.\n", tmp);
2463 catch_memory_errors = 0;
2470 /* Print an address in numeric and symbolic form (if possible) */
2471 static void xmon_print_symbol(unsigned long address, const char *mid,
2475 const char *name = NULL;
2476 unsigned long offset, size;
2478 printf(REG, address);
2479 if (setjmp(bus_error_jmp) == 0) {
2480 catch_memory_errors = 1;
2482 name = kallsyms_lookup(address, &size, &offset, &modname,
2485 /* wait a little while to see if we get a machine check */
2489 catch_memory_errors = 0;
2492 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2494 printf(" [%s]", modname);
2496 printf("%s", after);
2500 static void dump_slb(void)
2505 printf("SLB contents of cpu %x\n", smp_processor_id());
2507 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2508 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2509 printf("%02d %016lx ", i, tmp);
2511 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2512 printf("%016lx\n", tmp);
2516 static void dump_stab(void)
2519 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2521 printf("Segment table contents of cpu %x\n", smp_processor_id());
2523 for (i = 0; i < PAGE_SIZE/16; i++) {
2530 printf("%03d %016lx ", i, a);
2531 printf("%016lx\n", b);
2536 void dump_segments(void)
2538 if (cpu_has_feature(CPU_FTR_SLB))
2545 #ifdef CONFIG_PPC_STD_MMU_32
2546 void dump_segments(void)
2551 for (i = 0; i < 16; ++i)
2552 printf(" %x", mfsrin(i));
2557 void xmon_init(int enable)
2561 __debugger_ipi = xmon_ipi;
2562 __debugger_bpt = xmon_bpt;
2563 __debugger_sstep = xmon_sstep;
2564 __debugger_iabr_match = xmon_iabr_match;
2565 __debugger_dabr_match = xmon_dabr_match;
2566 __debugger_fault_handler = xmon_fault_handler;
2569 __debugger_ipi = NULL;
2570 __debugger_bpt = NULL;
2571 __debugger_sstep = NULL;
2572 __debugger_iabr_match = NULL;
2573 __debugger_dabr_match = NULL;
2574 __debugger_fault_handler = NULL;
2579 #ifdef CONFIG_MAGIC_SYSRQ
2580 static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2581 struct tty_struct *tty)
2583 /* ensure xmon is enabled */
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