sync hh.org
[hh.org.git] / arch / ppc / xmon / xmon.c
blobb1a91744fd2db09086d79af4846e74d3c9ba518a
1 /*
2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996 Paul Mackerras.
5 */
6 #include <linux/errno.h>
7 #include <linux/sched.h>
8 #include <linux/smp.h>
9 #include <linux/interrupt.h>
10 #include <linux/bitops.h>
11 #include <linux/kallsyms.h>
12 #include <asm/ptrace.h>
13 #include <asm/string.h>
14 #include <asm/machdep.h>
15 #include <asm/xmon.h>
16 #include "nonstdio.h"
17 #include "privinst.h"
19 #define scanhex xmon_scanhex
20 #define skipbl xmon_skipbl
22 #ifdef CONFIG_SMP
23 static unsigned long cpus_in_xmon = 0;
24 static unsigned long got_xmon = 0;
25 static volatile int take_xmon = -1;
26 #endif /* CONFIG_SMP */
28 static unsigned adrs;
29 static int size = 1;
30 static unsigned ndump = 64;
31 static unsigned nidump = 16;
32 static unsigned ncsum = 4096;
33 static int termch;
35 static u_int bus_error_jmp[100];
36 #define setjmp xmon_setjmp
37 #define longjmp xmon_longjmp
39 /* Breakpoint stuff */
40 struct bpt {
41 unsigned address;
42 unsigned instr;
43 unsigned count;
44 unsigned char enabled;
47 #define NBPTS 16
48 static struct bpt bpts[NBPTS];
49 static struct bpt dabr;
50 static struct bpt iabr;
51 static unsigned bpinstr = 0x7fe00008; /* trap */
53 /* Prototypes */
54 extern void (*debugger_fault_handler)(struct pt_regs *);
55 static int cmds(struct pt_regs *);
56 static int mread(unsigned, void *, int);
57 static int mwrite(unsigned, void *, int);
58 static void handle_fault(struct pt_regs *);
59 static void byterev(unsigned char *, int);
60 static void memex(void);
61 static int bsesc(void);
62 static void dump(void);
63 static void prdump(unsigned, int);
64 #ifdef __MWERKS__
65 static void prndump(unsigned, int);
66 static int nvreadb(unsigned);
67 #endif
68 static int ppc_inst_dump(unsigned, int);
69 void print_address(unsigned);
70 static int getsp(void);
71 static void dump_hash_table(void);
72 static void backtrace(struct pt_regs *);
73 static void excprint(struct pt_regs *);
74 static void prregs(struct pt_regs *);
75 static void memops(int);
76 static void memlocate(void);
77 static void memzcan(void);
78 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
79 int skipbl(void);
80 int scanhex(unsigned *valp);
81 static void scannl(void);
82 static int hexdigit(int);
83 void getstring(char *, int);
84 static void flush_input(void);
85 static int inchar(void);
86 static void take_input(char *);
87 /* static void openforth(void); */
88 static unsigned read_spr(int);
89 static void write_spr(int, unsigned);
90 static void super_regs(void);
91 static void symbol_lookup(void);
92 static void remove_bpts(void);
93 static void insert_bpts(void);
94 static struct bpt *at_breakpoint(unsigned pc);
95 static void bpt_cmds(void);
96 void cacheflush(void);
97 #ifdef CONFIG_SMP
98 static void cpu_cmd(void);
99 #endif /* CONFIG_SMP */
100 static void csum(void);
101 static void bootcmds(void);
102 static void proccall(void);
103 static void printtime(void);
105 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
106 extern void printf(const char *fmt, ...);
107 extern int putchar(int ch);
108 extern int setjmp(u_int *);
109 extern void longjmp(u_int *, int);
111 extern void xmon_enter(void);
112 extern void xmon_leave(void);
114 static unsigned start_tb[NR_CPUS][2];
115 static unsigned stop_tb[NR_CPUS][2];
117 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
119 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
120 || ('a' <= (c) && (c) <= 'f') \
121 || ('A' <= (c) && (c) <= 'F'))
122 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
123 || ('a' <= (c) && (c) <= 'z') \
124 || ('A' <= (c) && (c) <= 'Z'))
125 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
127 static char *help_string = "\
128 Commands:\n\
129 d dump bytes\n\
130 di dump instructions\n\
131 df dump float values\n\
132 dd dump double values\n\
133 e print exception information\n\
134 h dump hash table\n\
135 m examine/change memory\n\
136 mm move a block of memory\n\
137 ms set a block of memory\n\
138 md compare two blocks of memory\n\
139 r print registers\n\
140 S print special registers\n\
141 t print backtrace\n\
142 la lookup address\n\
143 ls lookup symbol\n\
144 C checksum\n\
145 p call function with arguments\n\
146 T print time\n\
147 x exit monitor\n\
148 zr reboot\n\
149 zh halt\n\
152 static int xmon_trace[NR_CPUS];
153 #define SSTEP 1 /* stepping because of 's' command */
154 #define BRSTEP 2 /* stepping over breakpoint */
156 #ifdef CONFIG_4xx
157 #define MSR_SSTEP_ENABLE 0x200
158 #else
159 #define MSR_SSTEP_ENABLE 0x400
160 #endif
162 static struct pt_regs *xmon_regs[NR_CPUS];
164 extern inline void sync(void)
166 asm volatile("sync; isync");
169 extern inline void __delay(unsigned int loops)
171 if (loops != 0)
172 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
173 "r" (loops) : "ctr");
176 /* Print an address in numeric and symbolic form (if possible) */
177 static void xmon_print_symbol(unsigned long address, const char *mid,
178 const char *after)
180 char *modname;
181 const char *name = NULL;
182 unsigned long offset, size;
183 static char tmpstr[128];
185 printf("%.8lx", address);
186 if (setjmp(bus_error_jmp) == 0) {
187 debugger_fault_handler = handle_fault;
188 sync();
189 name = kallsyms_lookup(address, &size, &offset, &modname,
190 tmpstr);
191 sync();
192 /* wait a little while to see if we get a machine check */
193 __delay(200);
195 debugger_fault_handler = NULL;
197 if (name) {
198 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
199 if (modname)
200 printf(" [%s]", modname);
202 printf("%s", after);
205 static void get_tb(unsigned *p)
207 unsigned hi, lo, hiagain;
209 if ((get_pvr() >> 16) == 1)
210 return;
212 do {
213 asm volatile("mftbu %0; mftb %1; mftbu %2"
214 : "=r" (hi), "=r" (lo), "=r" (hiagain));
215 } while (hi != hiagain);
216 p[0] = hi;
217 p[1] = lo;
220 static inline void xmon_enable_sstep(struct pt_regs *regs)
222 regs->msr |= MSR_SSTEP_ENABLE;
223 #ifdef CONFIG_4xx
224 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
225 #endif
228 int xmon(struct pt_regs *excp)
230 struct pt_regs regs;
231 int msr, cmd;
233 get_tb(stop_tb[smp_processor_id()]);
234 if (excp == NULL) {
235 asm volatile ("stw 0,0(%0)\n\
236 lwz 0,0(1)\n\
237 stw 0,4(%0)\n\
238 stmw 2,8(%0)" : : "b" (&regs));
239 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
240 regs.msr = get_msr();
241 regs.ctr = get_ctr();
242 regs.xer = get_xer();
243 regs.ccr = get_cr();
244 regs.trap = 0;
245 excp = &regs;
248 msr = get_msr();
249 set_msr(msr & ~0x8000); /* disable interrupts */
250 xmon_regs[smp_processor_id()] = excp;
251 xmon_enter();
252 excprint(excp);
253 #ifdef CONFIG_SMP
254 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
255 for (;;)
257 while (test_and_set_bit(0, &got_xmon)) {
258 if (take_xmon == smp_processor_id()) {
259 take_xmon = -1;
260 break;
264 * XXX: breakpoints are removed while any cpu is in xmon
266 #endif /* CONFIG_SMP */
267 remove_bpts();
268 cmd = cmds(excp);
269 if (cmd == 's') {
270 xmon_trace[smp_processor_id()] = SSTEP;
271 xmon_enable_sstep(excp);
272 } else if (at_breakpoint(excp->nip)) {
273 xmon_trace[smp_processor_id()] = BRSTEP;
274 xmon_enable_sstep(excp);
275 } else {
276 xmon_trace[smp_processor_id()] = 0;
277 insert_bpts();
279 xmon_leave();
280 xmon_regs[smp_processor_id()] = NULL;
281 #ifdef CONFIG_SMP
282 clear_bit(0, &got_xmon);
283 clear_bit(smp_processor_id(), &cpus_in_xmon);
284 #endif /* CONFIG_SMP */
285 set_msr(msr); /* restore interrupt enable */
286 get_tb(start_tb[smp_processor_id()]);
288 return cmd != 'X';
291 irqreturn_t
292 xmon_irq(int irq, void *d, struct pt_regs *regs)
294 unsigned long flags;
295 local_irq_save(flags);
296 printf("Keyboard interrupt\n");
297 xmon(regs);
298 local_irq_restore(flags);
299 return IRQ_HANDLED;
303 xmon_bpt(struct pt_regs *regs)
305 struct bpt *bp;
307 bp = at_breakpoint(regs->nip);
308 if (!bp)
309 return 0;
310 if (bp->count) {
311 --bp->count;
312 remove_bpts();
313 excprint(regs);
314 xmon_trace[smp_processor_id()] = BRSTEP;
315 xmon_enable_sstep(regs);
316 } else {
317 xmon(regs);
319 return 1;
323 xmon_sstep(struct pt_regs *regs)
325 if (!xmon_trace[smp_processor_id()])
326 return 0;
327 if (xmon_trace[smp_processor_id()] == BRSTEP) {
328 xmon_trace[smp_processor_id()] = 0;
329 insert_bpts();
330 } else {
331 xmon(regs);
333 return 1;
337 xmon_dabr_match(struct pt_regs *regs)
339 if (dabr.enabled && dabr.count) {
340 --dabr.count;
341 remove_bpts();
342 excprint(regs);
343 xmon_trace[smp_processor_id()] = BRSTEP;
344 regs->msr |= 0x400;
345 } else {
346 dabr.instr = regs->nip;
347 xmon(regs);
349 return 1;
353 xmon_iabr_match(struct pt_regs *regs)
355 if (iabr.enabled && iabr.count) {
356 --iabr.count;
357 remove_bpts();
358 excprint(regs);
359 xmon_trace[smp_processor_id()] = BRSTEP;
360 regs->msr |= 0x400;
361 } else {
362 xmon(regs);
364 return 1;
367 static struct bpt *
368 at_breakpoint(unsigned pc)
370 int i;
371 struct bpt *bp;
373 if (dabr.enabled && pc == dabr.instr)
374 return &dabr;
375 if (iabr.enabled && pc == iabr.address)
376 return &iabr;
377 bp = bpts;
378 for (i = 0; i < NBPTS; ++i, ++bp)
379 if (bp->enabled && pc == bp->address)
380 return bp;
381 return NULL;
384 static void
385 insert_bpts(void)
387 int i;
388 struct bpt *bp;
390 bp = bpts;
391 for (i = 0; i < NBPTS; ++i, ++bp) {
392 if (!bp->enabled)
393 continue;
394 if (mread(bp->address, &bp->instr, 4) != 4
395 || mwrite(bp->address, &bpinstr, 4) != 4) {
396 printf("Couldn't insert breakpoint at %x, disabling\n",
397 bp->address);
398 bp->enabled = 0;
400 store_inst((void *) bp->address);
402 #if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
403 if (dabr.enabled)
404 set_dabr(dabr.address);
405 if (iabr.enabled)
406 set_iabr(iabr.address);
407 #endif
410 static void
411 remove_bpts(void)
413 int i;
414 struct bpt *bp;
415 unsigned instr;
417 #if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
418 set_dabr(0);
419 set_iabr(0);
420 #endif
421 bp = bpts;
422 for (i = 0; i < NBPTS; ++i, ++bp) {
423 if (!bp->enabled)
424 continue;
425 if (mread(bp->address, &instr, 4) == 4
426 && instr == bpinstr
427 && mwrite(bp->address, &bp->instr, 4) != 4)
428 printf("Couldn't remove breakpoint at %x\n",
429 bp->address);
430 store_inst((void *) bp->address);
434 static char *last_cmd;
436 /* Command interpreting routine */
437 static int
438 cmds(struct pt_regs *excp)
440 int cmd;
442 last_cmd = NULL;
443 for(;;) {
444 #ifdef CONFIG_SMP
445 printf("%d:", smp_processor_id());
446 #endif /* CONFIG_SMP */
447 printf("mon> ");
448 fflush(stdout);
449 flush_input();
450 termch = 0;
451 cmd = skipbl();
452 if( cmd == '\n' ) {
453 if (last_cmd == NULL)
454 continue;
455 take_input(last_cmd);
456 last_cmd = NULL;
457 cmd = inchar();
459 switch (cmd) {
460 case 'm':
461 cmd = inchar();
462 switch (cmd) {
463 case 'm':
464 case 's':
465 case 'd':
466 memops(cmd);
467 break;
468 case 'l':
469 memlocate();
470 break;
471 case 'z':
472 memzcan();
473 break;
474 default:
475 termch = cmd;
476 memex();
478 break;
479 case 'd':
480 dump();
481 break;
482 case 'l':
483 symbol_lookup();
484 break;
485 case 'r':
486 if (excp != NULL)
487 prregs(excp); /* print regs */
488 break;
489 case 'e':
490 if (excp == NULL)
491 printf("No exception information\n");
492 else
493 excprint(excp);
494 break;
495 case 'S':
496 super_regs();
497 break;
498 case 't':
499 backtrace(excp);
500 break;
501 case 'f':
502 cacheflush();
503 break;
504 case 'h':
505 dump_hash_table();
506 break;
507 case 's':
508 case 'x':
509 case EOF:
510 return cmd;
511 case '?':
512 printf(help_string);
513 break;
514 default:
515 printf("Unrecognized command: ");
516 if( ' ' < cmd && cmd <= '~' )
517 putchar(cmd);
518 else
519 printf("\\x%x", cmd);
520 printf(" (type ? for help)\n");
521 break;
522 case 'b':
523 bpt_cmds();
524 break;
525 case 'C':
526 csum();
527 break;
528 #ifdef CONFIG_SMP
529 case 'c':
530 cpu_cmd();
531 break;
532 #endif /* CONFIG_SMP */
533 case 'z':
534 bootcmds();
535 break;
536 case 'p':
537 proccall();
538 break;
539 case 'T':
540 printtime();
541 break;
546 extern unsigned tb_to_us;
548 #define mulhwu(x,y) \
549 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
551 static void printtime(void)
553 unsigned int delta;
555 delta = stop_tb[smp_processor_id()][1]
556 - start_tb[smp_processor_id()][1];
557 delta = mulhwu(tb_to_us, delta);
558 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
561 static void bootcmds(void)
563 int cmd;
565 cmd = inchar();
566 if (cmd == 'r')
567 ppc_md.restart(NULL);
568 else if (cmd == 'h')
569 ppc_md.halt();
570 else if (cmd == 'p')
571 ppc_md.power_off();
574 #ifdef CONFIG_SMP
575 static void cpu_cmd(void)
577 unsigned cpu;
578 int timeout;
579 int cmd;
581 cmd = inchar();
582 if (cmd == 'i') {
583 /* interrupt other cpu(s) */
584 cpu = MSG_ALL_BUT_SELF;
585 if (scanhex(&cpu))
586 smp_send_xmon_break(cpu);
587 return;
589 termch = cmd;
590 if (!scanhex(&cpu)) {
591 /* print cpus waiting or in xmon */
592 printf("cpus stopped:");
593 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
594 if (test_bit(cpu, &cpus_in_xmon)) {
595 printf(" %d", cpu);
596 if (cpu == smp_processor_id())
597 printf("*", cpu);
600 printf("\n");
601 return;
603 /* try to switch to cpu specified */
604 take_xmon = cpu;
605 timeout = 10000000;
606 while (take_xmon >= 0) {
607 if (--timeout == 0) {
608 /* yes there's a race here */
609 take_xmon = -1;
610 printf("cpu %u didn't take control\n", cpu);
611 return;
614 /* now have to wait to be given control back */
615 while (test_and_set_bit(0, &got_xmon)) {
616 if (take_xmon == smp_processor_id()) {
617 take_xmon = -1;
618 break;
622 #endif /* CONFIG_SMP */
625 static unsigned short fcstab[256] = {
626 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
627 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
628 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
629 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
630 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
631 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
632 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
633 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
634 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
635 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
636 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
637 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
638 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
639 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
640 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
641 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
642 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
643 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
644 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
645 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
646 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
647 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
648 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
649 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
650 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
651 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
652 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
653 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
654 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
655 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
656 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
657 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
660 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
662 static void
663 csum(void)
665 unsigned int i;
666 unsigned short fcs;
667 unsigned char v;
669 if (!scanhex(&adrs))
670 return;
671 if (!scanhex(&ncsum))
672 return;
673 fcs = 0xffff;
674 for (i = 0; i < ncsum; ++i) {
675 if (mread(adrs+i, &v, 1) == 0) {
676 printf("csum stopped at %x\n", adrs+i);
677 break;
679 fcs = FCS(fcs, v);
681 printf("%x\n", fcs);
684 static void
685 bpt_cmds(void)
687 int cmd;
688 unsigned a;
689 int mode, i;
690 struct bpt *bp;
692 cmd = inchar();
693 switch (cmd) {
694 #if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
695 case 'd':
696 mode = 7;
697 cmd = inchar();
698 if (cmd == 'r')
699 mode = 5;
700 else if (cmd == 'w')
701 mode = 6;
702 else
703 termch = cmd;
704 cmd = inchar();
705 if (cmd == 'p')
706 mode &= ~4;
707 else
708 termch = cmd;
709 dabr.address = 0;
710 dabr.count = 0;
711 dabr.enabled = scanhex(&dabr.address);
712 scanhex(&dabr.count);
713 if (dabr.enabled)
714 dabr.address = (dabr.address & ~7) | mode;
715 break;
716 case 'i':
717 cmd = inchar();
718 if (cmd == 'p')
719 mode = 2;
720 else
721 mode = 3;
722 iabr.address = 0;
723 iabr.count = 0;
724 iabr.enabled = scanhex(&iabr.address);
725 if (iabr.enabled)
726 iabr.address |= mode;
727 scanhex(&iabr.count);
728 break;
729 #endif
730 case 'c':
731 if (!scanhex(&a)) {
732 /* clear all breakpoints */
733 for (i = 0; i < NBPTS; ++i)
734 bpts[i].enabled = 0;
735 iabr.enabled = 0;
736 dabr.enabled = 0;
737 printf("All breakpoints cleared\n");
738 } else {
739 bp = at_breakpoint(a);
740 if (bp == 0) {
741 printf("No breakpoint at %x\n", a);
742 } else {
743 bp->enabled = 0;
746 break;
747 default:
748 termch = cmd;
749 if (!scanhex(&a)) {
750 /* print all breakpoints */
751 printf("type address count\n");
752 if (dabr.enabled) {
753 printf("data %.8x %8x [", dabr.address & ~7,
754 dabr.count);
755 if (dabr.address & 1)
756 printf("r");
757 if (dabr.address & 2)
758 printf("w");
759 if (!(dabr.address & 4))
760 printf("p");
761 printf("]\n");
763 if (iabr.enabled)
764 printf("inst %.8x %8x\n", iabr.address & ~3,
765 iabr.count);
766 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
767 if (bp->enabled)
768 printf("trap %.8x %8x\n", bp->address,
769 bp->count);
770 break;
772 bp = at_breakpoint(a);
773 if (bp == 0) {
774 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
775 if (!bp->enabled)
776 break;
777 if (bp >= &bpts[NBPTS]) {
778 printf("Sorry, no free breakpoints\n");
779 break;
782 bp->enabled = 1;
783 bp->address = a;
784 bp->count = 0;
785 scanhex(&bp->count);
786 break;
790 static void
791 backtrace(struct pt_regs *excp)
793 unsigned sp;
794 unsigned stack[2];
795 struct pt_regs regs;
796 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
798 printf("backtrace:\n");
800 if (excp != NULL)
801 sp = excp->gpr[1];
802 else
803 sp = getsp();
804 scanhex(&sp);
805 scannl();
806 for (; sp != 0; sp = stack[0]) {
807 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
808 break;
809 printf("[%.8lx] ", stack[0]);
810 xmon_print_symbol(stack[1], " ", "\n");
811 if (stack[1] == (unsigned) &ret_from_except
812 || stack[1] == (unsigned) &ret_from_except_full
813 || stack[1] == (unsigned) &ret_from_syscall) {
814 if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
815 break;
816 printf("exception:%x [%x] %x\n", regs.trap, sp+16,
817 regs.nip);
818 sp = regs.gpr[1];
819 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
820 break;
826 getsp(void)
828 int x;
830 asm("mr %0,1" : "=r" (x) :);
831 return x;
834 void
835 excprint(struct pt_regs *fp)
837 int trap;
839 #ifdef CONFIG_SMP
840 printf("cpu %d: ", smp_processor_id());
841 #endif /* CONFIG_SMP */
842 printf("vector: %x at pc=", fp->trap);
843 xmon_print_symbol(fp->nip, ": ", ", lr=");
844 xmon_print_symbol(fp->link, ": ", "\n");
845 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
846 trap = TRAP(fp);
847 if (trap == 0x300 || trap == 0x600)
848 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
849 if (current)
850 printf("current = %x, pid = %d, comm = %s\n",
851 current, current->pid, current->comm);
854 void
855 prregs(struct pt_regs *fp)
857 int n;
858 unsigned base;
860 if (scanhex(&base))
861 fp = (struct pt_regs *) base;
862 for (n = 0; n < 32; ++n) {
863 printf("R%.2d = %.8x%s", n, fp->gpr[n],
864 (n & 3) == 3? "\n": " ");
865 if (n == 12 && !FULL_REGS(fp)) {
866 printf("\n");
867 break;
870 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
871 fp->nip, fp->msr, fp->link, fp->ccr);
872 printf("ctr = %.8x xer = %.8x trap = %4x\n",
873 fp->ctr, fp->xer, fp->trap);
876 void
877 cacheflush(void)
879 int cmd;
880 unsigned nflush;
882 cmd = inchar();
883 if (cmd != 'i')
884 termch = cmd;
885 scanhex(&adrs);
886 if (termch != '\n')
887 termch = 0;
888 nflush = 1;
889 scanhex(&nflush);
890 nflush = (nflush + 31) / 32;
891 if (cmd != 'i') {
892 for (; nflush > 0; --nflush, adrs += 0x20)
893 cflush((void *) adrs);
894 } else {
895 for (; nflush > 0; --nflush, adrs += 0x20)
896 cinval((void *) adrs);
900 unsigned int
901 read_spr(int n)
903 unsigned int instrs[2];
904 int (*code)(void);
906 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
907 instrs[1] = 0x4e800020;
908 store_inst(instrs);
909 store_inst(instrs+1);
910 code = (int (*)(void)) instrs;
911 return code();
914 void
915 write_spr(int n, unsigned int val)
917 unsigned int instrs[2];
918 int (*code)(unsigned int);
920 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
921 instrs[1] = 0x4e800020;
922 store_inst(instrs);
923 store_inst(instrs+1);
924 code = (int (*)(unsigned int)) instrs;
925 code(val);
928 static unsigned int regno;
929 extern char exc_prolog;
930 extern char dec_exc;
932 void
933 super_regs(void)
935 int i, cmd;
936 unsigned val;
938 cmd = skipbl();
939 if (cmd == '\n') {
940 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
941 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
942 get_sprg2(), get_sprg3());
943 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
944 #ifdef CONFIG_PPC_STD_MMU
945 printf("sr0-15 =");
946 for (i = 0; i < 16; ++i)
947 printf(" %x", get_sr(i));
948 printf("\n");
949 #endif
950 asm("mr %0,1" : "=r" (i) :);
951 printf("sp = %x ", i);
952 asm("mr %0,2" : "=r" (i) :);
953 printf("toc = %x\n", i);
954 return;
957 scanhex(&regno);
958 switch (cmd) {
959 case 'w':
960 val = read_spr(regno);
961 scanhex(&val);
962 write_spr(regno, val);
963 /* fall through */
964 case 'r':
965 printf("spr %x = %x\n", regno, read_spr(regno));
966 break;
967 case 's':
968 val = get_sr(regno);
969 scanhex(&val);
970 set_sr(regno, val);
971 break;
972 case 'm':
973 val = get_msr();
974 scanhex(&val);
975 set_msr(val);
976 break;
978 scannl();
981 #ifndef CONFIG_PPC_STD_MMU
982 static void
983 dump_hash_table(void)
985 printf("This CPU doesn't have a hash table.\n");
987 #else
989 static void
990 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
992 extern void *Hash;
993 extern unsigned long Hash_size;
994 unsigned *htab = Hash;
995 unsigned hsize = Hash_size;
996 unsigned v, hmask, va, last_va = 0;
997 int found, last_found, i;
998 unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
1000 last_found = 0;
1001 hmask = hsize / 64 - 1;
1002 va = start;
1003 start = (start >> 12) & 0xffff;
1004 end = (end >> 12) & 0xffff;
1005 for (v = start; v < end; ++v) {
1006 found = 0;
1007 hg = htab + (((v ^ seg) & hmask) * 16);
1008 w1 = 0x80000000 | (seg << 7) | (v >> 10);
1009 for (i = 0; i < 8; ++i, hg += 2) {
1010 if (*hg == w1) {
1011 found = 1;
1012 break;
1015 if (!found) {
1016 w1 ^= 0x40;
1017 hg = htab + ((~(v ^ seg) & hmask) * 16);
1018 for (i = 0; i < 8; ++i, hg += 2) {
1019 if (*hg == w1) {
1020 found = 1;
1021 break;
1025 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1026 if (last_found) {
1027 if (last_va != last_va0)
1028 printf(" ... %x", last_va);
1029 printf("\n");
1031 if (found) {
1032 printf("%x to %x", va, hg[1]);
1033 last_va0 = va;
1035 last_found = found;
1037 if (found) {
1038 last_w2 = hg[1] & ~0x180;
1039 last_va = va;
1041 va += 4096;
1043 if (last_found)
1044 printf(" ... %x\n", last_va);
1047 static unsigned hash_ctx;
1048 static unsigned hash_start;
1049 static unsigned hash_end;
1051 static void
1052 dump_hash_table(void)
1054 int seg;
1055 unsigned seg_start, seg_end;
1057 hash_ctx = 0;
1058 hash_start = 0;
1059 hash_end = 0xfffff000;
1060 scanhex(&hash_ctx);
1061 scanhex(&hash_start);
1062 scanhex(&hash_end);
1063 printf("Mappings for context %x\n", hash_ctx);
1064 seg_start = hash_start;
1065 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1066 seg_end = (seg << 28) | 0x0ffff000;
1067 if (seg_end > hash_end)
1068 seg_end = hash_end;
1069 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1070 seg_start, seg_end);
1071 seg_start = seg_end + 0x1000;
1074 #endif /* CONFIG_PPC_STD_MMU */
1077 * Stuff for reading and writing memory safely
1081 mread(unsigned adrs, void *buf, int size)
1083 volatile int n;
1084 char *p, *q;
1086 n = 0;
1087 if( setjmp(bus_error_jmp) == 0 ){
1088 debugger_fault_handler = handle_fault;
1089 sync();
1090 p = (char *) adrs;
1091 q = (char *) buf;
1092 switch (size) {
1093 case 2: *(short *)q = *(short *)p; break;
1094 case 4: *(int *)q = *(int *)p; break;
1095 default:
1096 for( ; n < size; ++n ) {
1097 *q++ = *p++;
1098 sync();
1101 sync();
1102 /* wait a little while to see if we get a machine check */
1103 __delay(200);
1104 n = size;
1106 debugger_fault_handler = NULL;
1107 return n;
1111 mwrite(unsigned adrs, void *buf, int size)
1113 volatile int n;
1114 char *p, *q;
1116 n = 0;
1117 if( setjmp(bus_error_jmp) == 0 ){
1118 debugger_fault_handler = handle_fault;
1119 sync();
1120 p = (char *) adrs;
1121 q = (char *) buf;
1122 switch (size) {
1123 case 2: *(short *)p = *(short *)q; break;
1124 case 4: *(int *)p = *(int *)q; break;
1125 default:
1126 for( ; n < size; ++n ) {
1127 *p++ = *q++;
1128 sync();
1131 sync();
1132 n = size;
1133 } else {
1134 printf("*** Error writing address %x\n", adrs + n);
1136 debugger_fault_handler = NULL;
1137 return n;
1140 static int fault_type;
1141 static int fault_except;
1142 static char *fault_chars[] = { "--", "**", "##" };
1144 static void
1145 handle_fault(struct pt_regs *regs)
1147 fault_except = TRAP(regs);
1148 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1149 longjmp(bus_error_jmp, 1);
1152 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1154 void
1155 byterev(unsigned char *val, int size)
1157 int t;
1159 switch (size) {
1160 case 2:
1161 SWAP(val[0], val[1], t);
1162 break;
1163 case 4:
1164 SWAP(val[0], val[3], t);
1165 SWAP(val[1], val[2], t);
1166 break;
1170 static int brev;
1171 static int mnoread;
1173 void
1174 memex(void)
1176 int cmd, inc, i, nslash;
1177 unsigned n;
1178 unsigned char val[4];
1180 last_cmd = "m\n";
1181 scanhex(&adrs);
1182 while ((cmd = skipbl()) != '\n') {
1183 switch( cmd ){
1184 case 'b': size = 1; break;
1185 case 'w': size = 2; break;
1186 case 'l': size = 4; break;
1187 case 'r': brev = !brev; break;
1188 case 'n': mnoread = 1; break;
1189 case '.': mnoread = 0; break;
1192 if( size <= 0 )
1193 size = 1;
1194 else if( size > 4 )
1195 size = 4;
1196 for(;;){
1197 if (!mnoread)
1198 n = mread(adrs, val, size);
1199 printf("%.8x%c", adrs, brev? 'r': ' ');
1200 if (!mnoread) {
1201 if (brev)
1202 byterev(val, size);
1203 putchar(' ');
1204 for (i = 0; i < n; ++i)
1205 printf("%.2x", val[i]);
1206 for (; i < size; ++i)
1207 printf("%s", fault_chars[fault_type]);
1209 putchar(' ');
1210 inc = size;
1211 nslash = 0;
1212 for(;;){
1213 if( scanhex(&n) ){
1214 for (i = 0; i < size; ++i)
1215 val[i] = n >> (i * 8);
1216 if (!brev)
1217 byterev(val, size);
1218 mwrite(adrs, val, size);
1219 inc = size;
1221 cmd = skipbl();
1222 if (cmd == '\n')
1223 break;
1224 inc = 0;
1225 switch (cmd) {
1226 case '\'':
1227 for(;;){
1228 n = inchar();
1229 if( n == '\\' )
1230 n = bsesc();
1231 else if( n == '\'' )
1232 break;
1233 for (i = 0; i < size; ++i)
1234 val[i] = n >> (i * 8);
1235 if (!brev)
1236 byterev(val, size);
1237 mwrite(adrs, val, size);
1238 adrs += size;
1240 adrs -= size;
1241 inc = size;
1242 break;
1243 case ',':
1244 adrs += size;
1245 break;
1246 case '.':
1247 mnoread = 0;
1248 break;
1249 case ';':
1250 break;
1251 case 'x':
1252 case EOF:
1253 scannl();
1254 return;
1255 case 'b':
1256 case 'v':
1257 size = 1;
1258 break;
1259 case 'w':
1260 size = 2;
1261 break;
1262 case 'l':
1263 size = 4;
1264 break;
1265 case '^':
1266 adrs -= size;
1267 break;
1268 break;
1269 case '/':
1270 if (nslash > 0)
1271 adrs -= 1 << nslash;
1272 else
1273 nslash = 0;
1274 nslash += 4;
1275 adrs += 1 << nslash;
1276 break;
1277 case '\\':
1278 if (nslash < 0)
1279 adrs += 1 << -nslash;
1280 else
1281 nslash = 0;
1282 nslash -= 4;
1283 adrs -= 1 << -nslash;
1284 break;
1285 case 'm':
1286 scanhex(&adrs);
1287 break;
1288 case 'n':
1289 mnoread = 1;
1290 break;
1291 case 'r':
1292 brev = !brev;
1293 break;
1294 case '<':
1295 n = size;
1296 scanhex(&n);
1297 adrs -= n;
1298 break;
1299 case '>':
1300 n = size;
1301 scanhex(&n);
1302 adrs += n;
1303 break;
1306 adrs += inc;
1311 bsesc(void)
1313 int c;
1315 c = inchar();
1316 switch( c ){
1317 case 'n': c = '\n'; break;
1318 case 'r': c = '\r'; break;
1319 case 'b': c = '\b'; break;
1320 case 't': c = '\t'; break;
1322 return c;
1325 void
1326 dump(void)
1328 int c;
1330 c = inchar();
1331 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1332 termch = c;
1333 scanhex(&adrs);
1334 if( termch != '\n')
1335 termch = 0;
1336 if( c == 'i' ){
1337 scanhex(&nidump);
1338 if( nidump == 0 )
1339 nidump = 16;
1340 adrs += ppc_inst_dump(adrs, nidump);
1341 last_cmd = "di\n";
1342 } else {
1343 scanhex(&ndump);
1344 if( ndump == 0 )
1345 ndump = 64;
1346 prdump(adrs, ndump);
1347 adrs += ndump;
1348 last_cmd = "d\n";
1352 void
1353 prdump(unsigned adrs, int ndump)
1355 register int n, m, c, r, nr;
1356 unsigned char temp[16];
1358 for( n = ndump; n > 0; ){
1359 printf("%.8x", adrs);
1360 putchar(' ');
1361 r = n < 16? n: 16;
1362 nr = mread(adrs, temp, r);
1363 adrs += nr;
1364 for( m = 0; m < r; ++m ){
1365 putchar((m & 3) == 0 && m > 0? '.': ' ');
1366 if( m < nr )
1367 printf("%.2x", temp[m]);
1368 else
1369 printf("%s", fault_chars[fault_type]);
1371 for(; m < 16; ++m )
1372 printf(" ");
1373 printf(" |");
1374 for( m = 0; m < r; ++m ){
1375 if( m < nr ){
1376 c = temp[m];
1377 putchar(' ' <= c && c <= '~'? c: '.');
1378 } else
1379 putchar(' ');
1381 n -= r;
1382 for(; m < 16; ++m )
1383 putchar(' ');
1384 printf("|\n");
1385 if( nr < r )
1386 break;
1391 ppc_inst_dump(unsigned adr, int count)
1393 int nr, dotted;
1394 unsigned first_adr;
1395 unsigned long inst, last_inst = 0;
1396 unsigned char val[4];
1398 dotted = 0;
1399 for (first_adr = adr; count > 0; --count, adr += 4){
1400 nr = mread(adr, val, 4);
1401 if( nr == 0 ){
1402 const char *x = fault_chars[fault_type];
1403 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1404 break;
1406 inst = GETWORD(val);
1407 if (adr > first_adr && inst == last_inst) {
1408 if (!dotted) {
1409 printf(" ...\n");
1410 dotted = 1;
1412 continue;
1414 dotted = 0;
1415 last_inst = inst;
1416 printf("%.8x ", adr);
1417 printf("%.8x\t", inst);
1418 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1419 printf("\n");
1421 return adr - first_adr;
1424 void
1425 print_address(unsigned addr)
1427 printf("0x%x", addr);
1431 * Memory operations - move, set, print differences
1433 static unsigned mdest; /* destination address */
1434 static unsigned msrc; /* source address */
1435 static unsigned mval; /* byte value to set memory to */
1436 static unsigned mcount; /* # bytes to affect */
1437 static unsigned mdiffs; /* max # differences to print */
1439 void
1440 memops(int cmd)
1442 scanhex(&mdest);
1443 if( termch != '\n' )
1444 termch = 0;
1445 scanhex(cmd == 's'? &mval: &msrc);
1446 if( termch != '\n' )
1447 termch = 0;
1448 scanhex(&mcount);
1449 switch( cmd ){
1450 case 'm':
1451 memmove((void *)mdest, (void *)msrc, mcount);
1452 break;
1453 case 's':
1454 memset((void *)mdest, mval, mcount);
1455 break;
1456 case 'd':
1457 if( termch != '\n' )
1458 termch = 0;
1459 scanhex(&mdiffs);
1460 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1461 break;
1465 void
1466 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1468 unsigned n, prt;
1470 prt = 0;
1471 for( n = nb; n > 0; --n )
1472 if( *p1++ != *p2++ )
1473 if( ++prt <= maxpr )
1474 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1475 p1[-1], (unsigned)p2 - 1, p2[-1]);
1476 if( prt > maxpr )
1477 printf("Total of %d differences\n", prt);
1480 static unsigned mend;
1481 static unsigned mask;
1483 void
1484 memlocate(void)
1486 unsigned a, n;
1487 unsigned char val[4];
1489 last_cmd = "ml";
1490 scanhex(&mdest);
1491 if (termch != '\n') {
1492 termch = 0;
1493 scanhex(&mend);
1494 if (termch != '\n') {
1495 termch = 0;
1496 scanhex(&mval);
1497 mask = ~0;
1498 if (termch != '\n') termch = 0;
1499 scanhex(&mask);
1502 n = 0;
1503 for (a = mdest; a < mend; a += 4) {
1504 if (mread(a, val, 4) == 4
1505 && ((GETWORD(val) ^ mval) & mask) == 0) {
1506 printf("%.8x: %.8x\n", a, GETWORD(val));
1507 if (++n >= 10)
1508 break;
1513 static unsigned mskip = 0x1000;
1514 static unsigned mlim = 0xffffffff;
1516 void
1517 memzcan(void)
1519 unsigned char v;
1520 unsigned a;
1521 int ok, ook;
1523 scanhex(&mdest);
1524 if (termch != '\n') termch = 0;
1525 scanhex(&mskip);
1526 if (termch != '\n') termch = 0;
1527 scanhex(&mlim);
1528 ook = 0;
1529 for (a = mdest; a < mlim; a += mskip) {
1530 ok = mread(a, &v, 1);
1531 if (ok && !ook) {
1532 printf("%.8x .. ", a);
1533 fflush(stdout);
1534 } else if (!ok && ook)
1535 printf("%.8x\n", a - mskip);
1536 ook = ok;
1537 if (a + mskip < a)
1538 break;
1540 if (ook)
1541 printf("%.8x\n", a - mskip);
1544 void proccall(void)
1546 unsigned int args[8];
1547 unsigned int ret;
1548 int i;
1549 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1550 unsigned int, unsigned int, unsigned int,
1551 unsigned int, unsigned int, unsigned int);
1552 callfunc_t func;
1554 scanhex(&adrs);
1555 if (termch != '\n')
1556 termch = 0;
1557 for (i = 0; i < 8; ++i)
1558 args[i] = 0;
1559 for (i = 0; i < 8; ++i) {
1560 if (!scanhex(&args[i]) || termch == '\n')
1561 break;
1562 termch = 0;
1564 func = (callfunc_t) adrs;
1565 ret = 0;
1566 if (setjmp(bus_error_jmp) == 0) {
1567 debugger_fault_handler = handle_fault;
1568 sync();
1569 ret = func(args[0], args[1], args[2], args[3],
1570 args[4], args[5], args[6], args[7]);
1571 sync();
1572 printf("return value is %x\n", ret);
1573 } else {
1574 printf("*** %x exception occurred\n", fault_except);
1576 debugger_fault_handler = NULL;
1579 /* Input scanning routines */
1581 skipbl(void)
1583 int c;
1585 if( termch != 0 ){
1586 c = termch;
1587 termch = 0;
1588 } else
1589 c = inchar();
1590 while( c == ' ' || c == '\t' )
1591 c = inchar();
1592 return c;
1595 #define N_PTREGS 44
1596 static char *regnames[N_PTREGS] = {
1597 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1598 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1599 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1600 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1601 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1602 "trap", "dar", "dsisr", "res"
1606 scanhex(unsigned *vp)
1608 int c, d;
1609 unsigned v;
1611 c = skipbl();
1612 if (c == '%') {
1613 /* parse register name */
1614 char regname[8];
1615 int i;
1617 for (i = 0; i < sizeof(regname) - 1; ++i) {
1618 c = inchar();
1619 if (!isalnum(c)) {
1620 termch = c;
1621 break;
1623 regname[i] = c;
1625 regname[i] = 0;
1626 for (i = 0; i < N_PTREGS; ++i) {
1627 if (strcmp(regnames[i], regname) == 0) {
1628 unsigned *rp = (unsigned *)
1629 xmon_regs[smp_processor_id()];
1630 if (rp == NULL) {
1631 printf("regs not available\n");
1632 return 0;
1634 *vp = rp[i];
1635 return 1;
1638 printf("invalid register name '%%%s'\n", regname);
1639 return 0;
1640 } else if (c == '$') {
1641 static char symname[128];
1642 int i;
1643 for (i=0; i<63; i++) {
1644 c = inchar();
1645 if (isspace(c)) {
1646 termch = c;
1647 break;
1649 symname[i] = c;
1651 symname[i++] = 0;
1652 *vp = 0;
1653 if (setjmp(bus_error_jmp) == 0) {
1654 debugger_fault_handler = handle_fault;
1655 sync();
1656 *vp = kallsyms_lookup_name(symname);
1657 sync();
1659 debugger_fault_handler = NULL;
1660 if (!(*vp)) {
1661 printf("unknown symbol\n");
1662 return 0;
1664 return 1;
1667 d = hexdigit(c);
1668 if( d == EOF ){
1669 termch = c;
1670 return 0;
1672 v = 0;
1673 do {
1674 v = (v << 4) + d;
1675 c = inchar();
1676 d = hexdigit(c);
1677 } while( d != EOF );
1678 termch = c;
1679 *vp = v;
1680 return 1;
1683 void
1684 scannl(void)
1686 int c;
1688 c = termch;
1689 termch = 0;
1690 while( c != '\n' )
1691 c = inchar();
1694 int hexdigit(int c)
1696 if( '0' <= c && c <= '9' )
1697 return c - '0';
1698 if( 'A' <= c && c <= 'F' )
1699 return c - ('A' - 10);
1700 if( 'a' <= c && c <= 'f' )
1701 return c - ('a' - 10);
1702 return EOF;
1705 void
1706 getstring(char *s, int size)
1708 int c;
1710 c = skipbl();
1711 do {
1712 if( size > 1 ){
1713 *s++ = c;
1714 --size;
1716 c = inchar();
1717 } while( c != ' ' && c != '\t' && c != '\n' );
1718 termch = c;
1719 *s = 0;
1722 static char line[256];
1723 static char *lineptr;
1725 void
1726 flush_input(void)
1728 lineptr = NULL;
1732 inchar(void)
1734 if (lineptr == NULL || *lineptr == 0) {
1735 if (fgets(line, sizeof(line), stdin) == NULL) {
1736 lineptr = NULL;
1737 return EOF;
1739 lineptr = line;
1741 return *lineptr++;
1744 void
1745 take_input(char *str)
1747 lineptr = str;
1750 static void
1751 symbol_lookup(void)
1753 int type = inchar();
1754 unsigned addr;
1755 static char tmp[128];
1757 switch (type) {
1758 case 'a':
1759 if (scanhex(&addr))
1760 xmon_print_symbol(addr, ": ", "\n");
1761 termch = 0;
1762 break;
1763 case 's':
1764 getstring(tmp, 64);
1765 if (setjmp(bus_error_jmp) == 0) {
1766 debugger_fault_handler = handle_fault;
1767 sync();
1768 addr = kallsyms_lookup_name(tmp);
1769 if (addr)
1770 printf("%s: %lx\n", tmp, addr);
1771 else
1772 printf("Symbol '%s' not found.\n", tmp);
1773 sync();
1775 debugger_fault_handler = NULL;
1776 termch = 0;
1777 break;