Linux 2.6.17.7
[linux/fpc-iii.git] / arch / ppc / xmon / xmon.c
blob06fa44b5c647130e7beb65514d2573e15016cb02
1 /*
2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996 Paul Mackerras.
5 */
6 #include <linux/config.h>
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <linux/smp.h>
10 #include <linux/interrupt.h>
11 #include <linux/bitops.h>
12 #include <linux/kallsyms.h>
13 #include <asm/ptrace.h>
14 #include <asm/string.h>
15 #include <asm/machdep.h>
16 #include <asm/xmon.h>
17 #include "nonstdio.h"
18 #include "privinst.h"
20 #define scanhex xmon_scanhex
21 #define skipbl xmon_skipbl
23 #ifdef CONFIG_SMP
24 static unsigned long cpus_in_xmon = 0;
25 static unsigned long got_xmon = 0;
26 static volatile int take_xmon = -1;
27 #endif /* CONFIG_SMP */
29 static unsigned adrs;
30 static int size = 1;
31 static unsigned ndump = 64;
32 static unsigned nidump = 16;
33 static unsigned ncsum = 4096;
34 static int termch;
36 static u_int bus_error_jmp[100];
37 #define setjmp xmon_setjmp
38 #define longjmp xmon_longjmp
40 /* Breakpoint stuff */
41 struct bpt {
42 unsigned address;
43 unsigned instr;
44 unsigned count;
45 unsigned char enabled;
48 #define NBPTS 16
49 static struct bpt bpts[NBPTS];
50 static struct bpt dabr;
51 static struct bpt iabr;
52 static unsigned bpinstr = 0x7fe00008; /* trap */
54 /* Prototypes */
55 extern void (*debugger_fault_handler)(struct pt_regs *);
56 static int cmds(struct pt_regs *);
57 static int mread(unsigned, void *, int);
58 static int mwrite(unsigned, void *, int);
59 static void handle_fault(struct pt_regs *);
60 static void byterev(unsigned char *, int);
61 static void memex(void);
62 static int bsesc(void);
63 static void dump(void);
64 static void prdump(unsigned, int);
65 #ifdef __MWERKS__
66 static void prndump(unsigned, int);
67 static int nvreadb(unsigned);
68 #endif
69 static int ppc_inst_dump(unsigned, int);
70 void print_address(unsigned);
71 static int getsp(void);
72 static void dump_hash_table(void);
73 static void backtrace(struct pt_regs *);
74 static void excprint(struct pt_regs *);
75 static void prregs(struct pt_regs *);
76 static void memops(int);
77 static void memlocate(void);
78 static void memzcan(void);
79 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
80 int skipbl(void);
81 int scanhex(unsigned *valp);
82 static void scannl(void);
83 static int hexdigit(int);
84 void getstring(char *, int);
85 static void flush_input(void);
86 static int inchar(void);
87 static void take_input(char *);
88 /* static void openforth(void); */
89 static unsigned read_spr(int);
90 static void write_spr(int, unsigned);
91 static void super_regs(void);
92 static void symbol_lookup(void);
93 static void remove_bpts(void);
94 static void insert_bpts(void);
95 static struct bpt *at_breakpoint(unsigned pc);
96 static void bpt_cmds(void);
97 void cacheflush(void);
98 #ifdef CONFIG_SMP
99 static void cpu_cmd(void);
100 #endif /* CONFIG_SMP */
101 static void csum(void);
102 static void bootcmds(void);
103 static void proccall(void);
104 static void printtime(void);
106 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
107 extern void printf(const char *fmt, ...);
108 extern int putchar(int ch);
109 extern int setjmp(u_int *);
110 extern void longjmp(u_int *, int);
112 extern void xmon_enter(void);
113 extern void xmon_leave(void);
115 static unsigned start_tb[NR_CPUS][2];
116 static unsigned stop_tb[NR_CPUS][2];
118 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
120 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
121 || ('a' <= (c) && (c) <= 'f') \
122 || ('A' <= (c) && (c) <= 'F'))
123 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
124 || ('a' <= (c) && (c) <= 'z') \
125 || ('A' <= (c) && (c) <= 'Z'))
126 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
128 static char *help_string = "\
129 Commands:\n\
130 d dump bytes\n\
131 di dump instructions\n\
132 df dump float values\n\
133 dd dump double values\n\
134 e print exception information\n\
135 h dump hash table\n\
136 m examine/change memory\n\
137 mm move a block of memory\n\
138 ms set a block of memory\n\
139 md compare two blocks of memory\n\
140 r print registers\n\
141 S print special registers\n\
142 t print backtrace\n\
143 la lookup address\n\
144 ls lookup symbol\n\
145 C checksum\n\
146 p call function with arguments\n\
147 T print time\n\
148 x exit monitor\n\
149 zr reboot\n\
150 zh halt\n\
153 static int xmon_trace[NR_CPUS];
154 #define SSTEP 1 /* stepping because of 's' command */
155 #define BRSTEP 2 /* stepping over breakpoint */
157 static struct pt_regs *xmon_regs[NR_CPUS];
159 extern inline void sync(void)
161 asm volatile("sync; isync");
164 extern inline void __delay(unsigned int loops)
166 if (loops != 0)
167 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
168 "r" (loops) : "ctr");
171 /* Print an address in numeric and symbolic form (if possible) */
172 static void xmon_print_symbol(unsigned long address, const char *mid,
173 const char *after)
175 char *modname;
176 const char *name = NULL;
177 unsigned long offset, size;
178 static char tmpstr[128];
180 printf("%.8lx", address);
181 if (setjmp(bus_error_jmp) == 0) {
182 debugger_fault_handler = handle_fault;
183 sync();
184 name = kallsyms_lookup(address, &size, &offset, &modname,
185 tmpstr);
186 sync();
187 /* wait a little while to see if we get a machine check */
188 __delay(200);
190 debugger_fault_handler = NULL;
192 if (name) {
193 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
194 if (modname)
195 printf(" [%s]", modname);
197 printf("%s", after);
200 static void get_tb(unsigned *p)
202 unsigned hi, lo, hiagain;
204 if ((get_pvr() >> 16) == 1)
205 return;
207 do {
208 asm volatile("mftbu %0; mftb %1; mftbu %2"
209 : "=r" (hi), "=r" (lo), "=r" (hiagain));
210 } while (hi != hiagain);
211 p[0] = hi;
212 p[1] = lo;
215 int xmon(struct pt_regs *excp)
217 struct pt_regs regs;
218 int msr, cmd;
220 get_tb(stop_tb[smp_processor_id()]);
221 if (excp == NULL) {
222 asm volatile ("stw 0,0(%0)\n\
223 lwz 0,0(1)\n\
224 stw 0,4(%0)\n\
225 stmw 2,8(%0)" : : "b" (&regs));
226 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
227 regs.msr = get_msr();
228 regs.ctr = get_ctr();
229 regs.xer = get_xer();
230 regs.ccr = get_cr();
231 regs.trap = 0;
232 excp = &regs;
235 msr = get_msr();
236 set_msr(msr & ~0x8000); /* disable interrupts */
237 xmon_regs[smp_processor_id()] = excp;
238 xmon_enter();
239 excprint(excp);
240 #ifdef CONFIG_SMP
241 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
242 for (;;)
244 while (test_and_set_bit(0, &got_xmon)) {
245 if (take_xmon == smp_processor_id()) {
246 take_xmon = -1;
247 break;
251 * XXX: breakpoints are removed while any cpu is in xmon
253 #endif /* CONFIG_SMP */
254 remove_bpts();
255 cmd = cmds(excp);
256 if (cmd == 's') {
257 xmon_trace[smp_processor_id()] = SSTEP;
258 excp->msr |= 0x400;
259 } else if (at_breakpoint(excp->nip)) {
260 xmon_trace[smp_processor_id()] = BRSTEP;
261 excp->msr |= 0x400;
262 } else {
263 xmon_trace[smp_processor_id()] = 0;
264 insert_bpts();
266 xmon_leave();
267 xmon_regs[smp_processor_id()] = NULL;
268 #ifdef CONFIG_SMP
269 clear_bit(0, &got_xmon);
270 clear_bit(smp_processor_id(), &cpus_in_xmon);
271 #endif /* CONFIG_SMP */
272 set_msr(msr); /* restore interrupt enable */
273 get_tb(start_tb[smp_processor_id()]);
275 return cmd != 'X';
278 irqreturn_t
279 xmon_irq(int irq, void *d, struct pt_regs *regs)
281 unsigned long flags;
282 local_irq_save(flags);
283 printf("Keyboard interrupt\n");
284 xmon(regs);
285 local_irq_restore(flags);
286 return IRQ_HANDLED;
290 xmon_bpt(struct pt_regs *regs)
292 struct bpt *bp;
294 bp = at_breakpoint(regs->nip);
295 if (!bp)
296 return 0;
297 if (bp->count) {
298 --bp->count;
299 remove_bpts();
300 excprint(regs);
301 xmon_trace[smp_processor_id()] = BRSTEP;
302 regs->msr |= 0x400;
303 } else {
304 xmon(regs);
306 return 1;
310 xmon_sstep(struct pt_regs *regs)
312 if (!xmon_trace[smp_processor_id()])
313 return 0;
314 if (xmon_trace[smp_processor_id()] == BRSTEP) {
315 xmon_trace[smp_processor_id()] = 0;
316 insert_bpts();
317 } else {
318 xmon(regs);
320 return 1;
324 xmon_dabr_match(struct pt_regs *regs)
326 if (dabr.enabled && dabr.count) {
327 --dabr.count;
328 remove_bpts();
329 excprint(regs);
330 xmon_trace[smp_processor_id()] = BRSTEP;
331 regs->msr |= 0x400;
332 } else {
333 dabr.instr = regs->nip;
334 xmon(regs);
336 return 1;
340 xmon_iabr_match(struct pt_regs *regs)
342 if (iabr.enabled && iabr.count) {
343 --iabr.count;
344 remove_bpts();
345 excprint(regs);
346 xmon_trace[smp_processor_id()] = BRSTEP;
347 regs->msr |= 0x400;
348 } else {
349 xmon(regs);
351 return 1;
354 static struct bpt *
355 at_breakpoint(unsigned pc)
357 int i;
358 struct bpt *bp;
360 if (dabr.enabled && pc == dabr.instr)
361 return &dabr;
362 if (iabr.enabled && pc == iabr.address)
363 return &iabr;
364 bp = bpts;
365 for (i = 0; i < NBPTS; ++i, ++bp)
366 if (bp->enabled && pc == bp->address)
367 return bp;
368 return NULL;
371 static void
372 insert_bpts(void)
374 int i;
375 struct bpt *bp;
377 bp = bpts;
378 for (i = 0; i < NBPTS; ++i, ++bp) {
379 if (!bp->enabled)
380 continue;
381 if (mread(bp->address, &bp->instr, 4) != 4
382 || mwrite(bp->address, &bpinstr, 4) != 4) {
383 printf("Couldn't insert breakpoint at %x, disabling\n",
384 bp->address);
385 bp->enabled = 0;
387 store_inst((void *) bp->address);
389 #if !defined(CONFIG_8xx)
390 if (dabr.enabled)
391 set_dabr(dabr.address);
392 if (iabr.enabled)
393 set_iabr(iabr.address);
394 #endif
397 static void
398 remove_bpts(void)
400 int i;
401 struct bpt *bp;
402 unsigned instr;
404 #if !defined(CONFIG_8xx)
405 set_dabr(0);
406 set_iabr(0);
407 #endif
408 bp = bpts;
409 for (i = 0; i < NBPTS; ++i, ++bp) {
410 if (!bp->enabled)
411 continue;
412 if (mread(bp->address, &instr, 4) == 4
413 && instr == bpinstr
414 && mwrite(bp->address, &bp->instr, 4) != 4)
415 printf("Couldn't remove breakpoint at %x\n",
416 bp->address);
417 store_inst((void *) bp->address);
421 static char *last_cmd;
423 /* Command interpreting routine */
424 static int
425 cmds(struct pt_regs *excp)
427 int cmd;
429 last_cmd = NULL;
430 for(;;) {
431 #ifdef CONFIG_SMP
432 printf("%d:", smp_processor_id());
433 #endif /* CONFIG_SMP */
434 printf("mon> ");
435 fflush(stdout);
436 flush_input();
437 termch = 0;
438 cmd = skipbl();
439 if( cmd == '\n' ) {
440 if (last_cmd == NULL)
441 continue;
442 take_input(last_cmd);
443 last_cmd = NULL;
444 cmd = inchar();
446 switch (cmd) {
447 case 'm':
448 cmd = inchar();
449 switch (cmd) {
450 case 'm':
451 case 's':
452 case 'd':
453 memops(cmd);
454 break;
455 case 'l':
456 memlocate();
457 break;
458 case 'z':
459 memzcan();
460 break;
461 default:
462 termch = cmd;
463 memex();
465 break;
466 case 'd':
467 dump();
468 break;
469 case 'l':
470 symbol_lookup();
471 break;
472 case 'r':
473 if (excp != NULL)
474 prregs(excp); /* print regs */
475 break;
476 case 'e':
477 if (excp == NULL)
478 printf("No exception information\n");
479 else
480 excprint(excp);
481 break;
482 case 'S':
483 super_regs();
484 break;
485 case 't':
486 backtrace(excp);
487 break;
488 case 'f':
489 cacheflush();
490 break;
491 case 'h':
492 dump_hash_table();
493 break;
494 case 's':
495 case 'x':
496 case EOF:
497 return cmd;
498 case '?':
499 printf(help_string);
500 break;
501 default:
502 printf("Unrecognized command: ");
503 if( ' ' < cmd && cmd <= '~' )
504 putchar(cmd);
505 else
506 printf("\\x%x", cmd);
507 printf(" (type ? for help)\n");
508 break;
509 case 'b':
510 bpt_cmds();
511 break;
512 case 'C':
513 csum();
514 break;
515 #ifdef CONFIG_SMP
516 case 'c':
517 cpu_cmd();
518 break;
519 #endif /* CONFIG_SMP */
520 case 'z':
521 bootcmds();
522 break;
523 case 'p':
524 proccall();
525 break;
526 case 'T':
527 printtime();
528 break;
533 extern unsigned tb_to_us;
535 #define mulhwu(x,y) \
536 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
538 static void printtime(void)
540 unsigned int delta;
542 delta = stop_tb[smp_processor_id()][1]
543 - start_tb[smp_processor_id()][1];
544 delta = mulhwu(tb_to_us, delta);
545 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
548 static void bootcmds(void)
550 int cmd;
552 cmd = inchar();
553 if (cmd == 'r')
554 ppc_md.restart(NULL);
555 else if (cmd == 'h')
556 ppc_md.halt();
557 else if (cmd == 'p')
558 ppc_md.power_off();
561 #ifdef CONFIG_SMP
562 static void cpu_cmd(void)
564 unsigned cpu;
565 int timeout;
566 int cmd;
568 cmd = inchar();
569 if (cmd == 'i') {
570 /* interrupt other cpu(s) */
571 cpu = MSG_ALL_BUT_SELF;
572 if (scanhex(&cpu))
573 smp_send_xmon_break(cpu);
574 return;
576 termch = cmd;
577 if (!scanhex(&cpu)) {
578 /* print cpus waiting or in xmon */
579 printf("cpus stopped:");
580 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
581 if (test_bit(cpu, &cpus_in_xmon)) {
582 printf(" %d", cpu);
583 if (cpu == smp_processor_id())
584 printf("*", cpu);
587 printf("\n");
588 return;
590 /* try to switch to cpu specified */
591 take_xmon = cpu;
592 timeout = 10000000;
593 while (take_xmon >= 0) {
594 if (--timeout == 0) {
595 /* yes there's a race here */
596 take_xmon = -1;
597 printf("cpu %u didn't take control\n", cpu);
598 return;
601 /* now have to wait to be given control back */
602 while (test_and_set_bit(0, &got_xmon)) {
603 if (take_xmon == smp_processor_id()) {
604 take_xmon = -1;
605 break;
609 #endif /* CONFIG_SMP */
612 static unsigned short fcstab[256] = {
613 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
614 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
615 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
616 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
617 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
618 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
619 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
620 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
621 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
622 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
623 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
624 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
625 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
626 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
627 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
628 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
629 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
630 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
631 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
632 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
633 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
634 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
635 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
636 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
637 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
638 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
639 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
640 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
641 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
642 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
643 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
644 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
647 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
649 static void
650 csum(void)
652 unsigned int i;
653 unsigned short fcs;
654 unsigned char v;
656 if (!scanhex(&adrs))
657 return;
658 if (!scanhex(&ncsum))
659 return;
660 fcs = 0xffff;
661 for (i = 0; i < ncsum; ++i) {
662 if (mread(adrs+i, &v, 1) == 0) {
663 printf("csum stopped at %x\n", adrs+i);
664 break;
666 fcs = FCS(fcs, v);
668 printf("%x\n", fcs);
671 static void
672 bpt_cmds(void)
674 int cmd;
675 unsigned a;
676 int mode, i;
677 struct bpt *bp;
679 cmd = inchar();
680 switch (cmd) {
681 #if !defined(CONFIG_8xx)
682 case 'd':
683 mode = 7;
684 cmd = inchar();
685 if (cmd == 'r')
686 mode = 5;
687 else if (cmd == 'w')
688 mode = 6;
689 else
690 termch = cmd;
691 cmd = inchar();
692 if (cmd == 'p')
693 mode &= ~4;
694 else
695 termch = cmd;
696 dabr.address = 0;
697 dabr.count = 0;
698 dabr.enabled = scanhex(&dabr.address);
699 scanhex(&dabr.count);
700 if (dabr.enabled)
701 dabr.address = (dabr.address & ~7) | mode;
702 break;
703 case 'i':
704 cmd = inchar();
705 if (cmd == 'p')
706 mode = 2;
707 else
708 mode = 3;
709 iabr.address = 0;
710 iabr.count = 0;
711 iabr.enabled = scanhex(&iabr.address);
712 if (iabr.enabled)
713 iabr.address |= mode;
714 scanhex(&iabr.count);
715 break;
716 #endif
717 case 'c':
718 if (!scanhex(&a)) {
719 /* clear all breakpoints */
720 for (i = 0; i < NBPTS; ++i)
721 bpts[i].enabled = 0;
722 iabr.enabled = 0;
723 dabr.enabled = 0;
724 printf("All breakpoints cleared\n");
725 } else {
726 bp = at_breakpoint(a);
727 if (bp == 0) {
728 printf("No breakpoint at %x\n", a);
729 } else {
730 bp->enabled = 0;
733 break;
734 default:
735 termch = cmd;
736 if (!scanhex(&a)) {
737 /* print all breakpoints */
738 printf("type address count\n");
739 if (dabr.enabled) {
740 printf("data %.8x %8x [", dabr.address & ~7,
741 dabr.count);
742 if (dabr.address & 1)
743 printf("r");
744 if (dabr.address & 2)
745 printf("w");
746 if (!(dabr.address & 4))
747 printf("p");
748 printf("]\n");
750 if (iabr.enabled)
751 printf("inst %.8x %8x\n", iabr.address & ~3,
752 iabr.count);
753 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
754 if (bp->enabled)
755 printf("trap %.8x %8x\n", bp->address,
756 bp->count);
757 break;
759 bp = at_breakpoint(a);
760 if (bp == 0) {
761 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
762 if (!bp->enabled)
763 break;
764 if (bp >= &bpts[NBPTS]) {
765 printf("Sorry, no free breakpoints\n");
766 break;
769 bp->enabled = 1;
770 bp->address = a;
771 bp->count = 0;
772 scanhex(&bp->count);
773 break;
777 static void
778 backtrace(struct pt_regs *excp)
780 unsigned sp;
781 unsigned stack[2];
782 struct pt_regs regs;
783 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
785 printf("backtrace:\n");
787 if (excp != NULL)
788 sp = excp->gpr[1];
789 else
790 sp = getsp();
791 scanhex(&sp);
792 scannl();
793 for (; sp != 0; sp = stack[0]) {
794 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
795 break;
796 printf("[%.8lx] ", stack);
797 xmon_print_symbol(stack[1], " ", "\n");
798 if (stack[1] == (unsigned) &ret_from_except
799 || stack[1] == (unsigned) &ret_from_except_full
800 || stack[1] == (unsigned) &ret_from_syscall) {
801 if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
802 break;
803 printf("exception:%x [%x] %x\n", regs.trap, sp+16,
804 regs.nip);
805 sp = regs.gpr[1];
806 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
807 break;
813 getsp(void)
815 int x;
817 asm("mr %0,1" : "=r" (x) :);
818 return x;
821 void
822 excprint(struct pt_regs *fp)
824 int trap;
826 #ifdef CONFIG_SMP
827 printf("cpu %d: ", smp_processor_id());
828 #endif /* CONFIG_SMP */
829 printf("vector: %x at pc=", fp->trap);
830 xmon_print_symbol(fp->nip, ": ", ", lr=");
831 xmon_print_symbol(fp->link, ": ", "\n");
832 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
833 trap = TRAP(fp);
834 if (trap == 0x300 || trap == 0x600)
835 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
836 if (current)
837 printf("current = %x, pid = %d, comm = %s\n",
838 current, current->pid, current->comm);
841 void
842 prregs(struct pt_regs *fp)
844 int n;
845 unsigned base;
847 if (scanhex(&base))
848 fp = (struct pt_regs *) base;
849 for (n = 0; n < 32; ++n) {
850 printf("R%.2d = %.8x%s", n, fp->gpr[n],
851 (n & 3) == 3? "\n": " ");
852 if (n == 12 && !FULL_REGS(fp)) {
853 printf("\n");
854 break;
857 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
858 fp->nip, fp->msr, fp->link, fp->ccr);
859 printf("ctr = %.8x xer = %.8x trap = %4x\n",
860 fp->ctr, fp->xer, fp->trap);
863 void
864 cacheflush(void)
866 int cmd;
867 unsigned nflush;
869 cmd = inchar();
870 if (cmd != 'i')
871 termch = cmd;
872 scanhex(&adrs);
873 if (termch != '\n')
874 termch = 0;
875 nflush = 1;
876 scanhex(&nflush);
877 nflush = (nflush + 31) / 32;
878 if (cmd != 'i') {
879 for (; nflush > 0; --nflush, adrs += 0x20)
880 cflush((void *) adrs);
881 } else {
882 for (; nflush > 0; --nflush, adrs += 0x20)
883 cinval((void *) adrs);
887 unsigned int
888 read_spr(int n)
890 unsigned int instrs[2];
891 int (*code)(void);
893 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
894 instrs[1] = 0x4e800020;
895 store_inst(instrs);
896 store_inst(instrs+1);
897 code = (int (*)(void)) instrs;
898 return code();
901 void
902 write_spr(int n, unsigned int val)
904 unsigned int instrs[2];
905 int (*code)(unsigned int);
907 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
908 instrs[1] = 0x4e800020;
909 store_inst(instrs);
910 store_inst(instrs+1);
911 code = (int (*)(unsigned int)) instrs;
912 code(val);
915 static unsigned int regno;
916 extern char exc_prolog;
917 extern char dec_exc;
919 void
920 super_regs(void)
922 int i, cmd;
923 unsigned val;
925 cmd = skipbl();
926 if (cmd == '\n') {
927 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
928 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
929 get_sprg2(), get_sprg3());
930 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
931 #ifdef CONFIG_PPC_STD_MMU
932 printf("sr0-15 =");
933 for (i = 0; i < 16; ++i)
934 printf(" %x", get_sr(i));
935 printf("\n");
936 #endif
937 asm("mr %0,1" : "=r" (i) :);
938 printf("sp = %x ", i);
939 asm("mr %0,2" : "=r" (i) :);
940 printf("toc = %x\n", i);
941 return;
944 scanhex(&regno);
945 switch (cmd) {
946 case 'w':
947 val = read_spr(regno);
948 scanhex(&val);
949 write_spr(regno, val);
950 /* fall through */
951 case 'r':
952 printf("spr %x = %x\n", regno, read_spr(regno));
953 break;
954 case 's':
955 val = get_sr(regno);
956 scanhex(&val);
957 set_sr(regno, val);
958 break;
959 case 'm':
960 val = get_msr();
961 scanhex(&val);
962 set_msr(val);
963 break;
965 scannl();
968 #ifndef CONFIG_PPC_STD_MMU
969 static void
970 dump_hash_table(void)
972 printf("This CPU doesn't have a hash table.\n");
974 #else
976 static void
977 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
979 extern void *Hash;
980 extern unsigned long Hash_size;
981 unsigned *htab = Hash;
982 unsigned hsize = Hash_size;
983 unsigned v, hmask, va, last_va = 0;
984 int found, last_found, i;
985 unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
987 last_found = 0;
988 hmask = hsize / 64 - 1;
989 va = start;
990 start = (start >> 12) & 0xffff;
991 end = (end >> 12) & 0xffff;
992 for (v = start; v < end; ++v) {
993 found = 0;
994 hg = htab + (((v ^ seg) & hmask) * 16);
995 w1 = 0x80000000 | (seg << 7) | (v >> 10);
996 for (i = 0; i < 8; ++i, hg += 2) {
997 if (*hg == w1) {
998 found = 1;
999 break;
1002 if (!found) {
1003 w1 ^= 0x40;
1004 hg = htab + ((~(v ^ seg) & hmask) * 16);
1005 for (i = 0; i < 8; ++i, hg += 2) {
1006 if (*hg == w1) {
1007 found = 1;
1008 break;
1012 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1013 if (last_found) {
1014 if (last_va != last_va0)
1015 printf(" ... %x", last_va);
1016 printf("\n");
1018 if (found) {
1019 printf("%x to %x", va, hg[1]);
1020 last_va0 = va;
1022 last_found = found;
1024 if (found) {
1025 last_w2 = hg[1] & ~0x180;
1026 last_va = va;
1028 va += 4096;
1030 if (last_found)
1031 printf(" ... %x\n", last_va);
1034 static unsigned hash_ctx;
1035 static unsigned hash_start;
1036 static unsigned hash_end;
1038 static void
1039 dump_hash_table(void)
1041 int seg;
1042 unsigned seg_start, seg_end;
1044 hash_ctx = 0;
1045 hash_start = 0;
1046 hash_end = 0xfffff000;
1047 scanhex(&hash_ctx);
1048 scanhex(&hash_start);
1049 scanhex(&hash_end);
1050 printf("Mappings for context %x\n", hash_ctx);
1051 seg_start = hash_start;
1052 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1053 seg_end = (seg << 28) | 0x0ffff000;
1054 if (seg_end > hash_end)
1055 seg_end = hash_end;
1056 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1057 seg_start, seg_end);
1058 seg_start = seg_end + 0x1000;
1061 #endif /* CONFIG_PPC_STD_MMU */
1064 * Stuff for reading and writing memory safely
1068 mread(unsigned adrs, void *buf, int size)
1070 volatile int n;
1071 char *p, *q;
1073 n = 0;
1074 if( setjmp(bus_error_jmp) == 0 ){
1075 debugger_fault_handler = handle_fault;
1076 sync();
1077 p = (char *) adrs;
1078 q = (char *) buf;
1079 switch (size) {
1080 case 2: *(short *)q = *(short *)p; break;
1081 case 4: *(int *)q = *(int *)p; break;
1082 default:
1083 for( ; n < size; ++n ) {
1084 *q++ = *p++;
1085 sync();
1088 sync();
1089 /* wait a little while to see if we get a machine check */
1090 __delay(200);
1091 n = size;
1093 debugger_fault_handler = NULL;
1094 return n;
1098 mwrite(unsigned adrs, void *buf, int size)
1100 volatile int n;
1101 char *p, *q;
1103 n = 0;
1104 if( setjmp(bus_error_jmp) == 0 ){
1105 debugger_fault_handler = handle_fault;
1106 sync();
1107 p = (char *) adrs;
1108 q = (char *) buf;
1109 switch (size) {
1110 case 2: *(short *)p = *(short *)q; break;
1111 case 4: *(int *)p = *(int *)q; break;
1112 default:
1113 for( ; n < size; ++n ) {
1114 *p++ = *q++;
1115 sync();
1118 sync();
1119 n = size;
1120 } else {
1121 printf("*** Error writing address %x\n", adrs + n);
1123 debugger_fault_handler = NULL;
1124 return n;
1127 static int fault_type;
1128 static int fault_except;
1129 static char *fault_chars[] = { "--", "**", "##" };
1131 static void
1132 handle_fault(struct pt_regs *regs)
1134 fault_except = TRAP(regs);
1135 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1136 longjmp(bus_error_jmp, 1);
1139 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1141 void
1142 byterev(unsigned char *val, int size)
1144 int t;
1146 switch (size) {
1147 case 2:
1148 SWAP(val[0], val[1], t);
1149 break;
1150 case 4:
1151 SWAP(val[0], val[3], t);
1152 SWAP(val[1], val[2], t);
1153 break;
1157 static int brev;
1158 static int mnoread;
1160 void
1161 memex(void)
1163 int cmd, inc, i, nslash;
1164 unsigned n;
1165 unsigned char val[4];
1167 last_cmd = "m\n";
1168 scanhex(&adrs);
1169 while ((cmd = skipbl()) != '\n') {
1170 switch( cmd ){
1171 case 'b': size = 1; break;
1172 case 'w': size = 2; break;
1173 case 'l': size = 4; break;
1174 case 'r': brev = !brev; break;
1175 case 'n': mnoread = 1; break;
1176 case '.': mnoread = 0; break;
1179 if( size <= 0 )
1180 size = 1;
1181 else if( size > 4 )
1182 size = 4;
1183 for(;;){
1184 if (!mnoread)
1185 n = mread(adrs, val, size);
1186 printf("%.8x%c", adrs, brev? 'r': ' ');
1187 if (!mnoread) {
1188 if (brev)
1189 byterev(val, size);
1190 putchar(' ');
1191 for (i = 0; i < n; ++i)
1192 printf("%.2x", val[i]);
1193 for (; i < size; ++i)
1194 printf("%s", fault_chars[fault_type]);
1196 putchar(' ');
1197 inc = size;
1198 nslash = 0;
1199 for(;;){
1200 if( scanhex(&n) ){
1201 for (i = 0; i < size; ++i)
1202 val[i] = n >> (i * 8);
1203 if (!brev)
1204 byterev(val, size);
1205 mwrite(adrs, val, size);
1206 inc = size;
1208 cmd = skipbl();
1209 if (cmd == '\n')
1210 break;
1211 inc = 0;
1212 switch (cmd) {
1213 case '\'':
1214 for(;;){
1215 n = inchar();
1216 if( n == '\\' )
1217 n = bsesc();
1218 else if( n == '\'' )
1219 break;
1220 for (i = 0; i < size; ++i)
1221 val[i] = n >> (i * 8);
1222 if (!brev)
1223 byterev(val, size);
1224 mwrite(adrs, val, size);
1225 adrs += size;
1227 adrs -= size;
1228 inc = size;
1229 break;
1230 case ',':
1231 adrs += size;
1232 break;
1233 case '.':
1234 mnoread = 0;
1235 break;
1236 case ';':
1237 break;
1238 case 'x':
1239 case EOF:
1240 scannl();
1241 return;
1242 case 'b':
1243 case 'v':
1244 size = 1;
1245 break;
1246 case 'w':
1247 size = 2;
1248 break;
1249 case 'l':
1250 size = 4;
1251 break;
1252 case '^':
1253 adrs -= size;
1254 break;
1255 break;
1256 case '/':
1257 if (nslash > 0)
1258 adrs -= 1 << nslash;
1259 else
1260 nslash = 0;
1261 nslash += 4;
1262 adrs += 1 << nslash;
1263 break;
1264 case '\\':
1265 if (nslash < 0)
1266 adrs += 1 << -nslash;
1267 else
1268 nslash = 0;
1269 nslash -= 4;
1270 adrs -= 1 << -nslash;
1271 break;
1272 case 'm':
1273 scanhex(&adrs);
1274 break;
1275 case 'n':
1276 mnoread = 1;
1277 break;
1278 case 'r':
1279 brev = !brev;
1280 break;
1281 case '<':
1282 n = size;
1283 scanhex(&n);
1284 adrs -= n;
1285 break;
1286 case '>':
1287 n = size;
1288 scanhex(&n);
1289 adrs += n;
1290 break;
1293 adrs += inc;
1298 bsesc(void)
1300 int c;
1302 c = inchar();
1303 switch( c ){
1304 case 'n': c = '\n'; break;
1305 case 'r': c = '\r'; break;
1306 case 'b': c = '\b'; break;
1307 case 't': c = '\t'; break;
1309 return c;
1312 void
1313 dump(void)
1315 int c;
1317 c = inchar();
1318 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1319 termch = c;
1320 scanhex(&adrs);
1321 if( termch != '\n')
1322 termch = 0;
1323 if( c == 'i' ){
1324 scanhex(&nidump);
1325 if( nidump == 0 )
1326 nidump = 16;
1327 adrs += ppc_inst_dump(adrs, nidump);
1328 last_cmd = "di\n";
1329 } else {
1330 scanhex(&ndump);
1331 if( ndump == 0 )
1332 ndump = 64;
1333 prdump(adrs, ndump);
1334 adrs += ndump;
1335 last_cmd = "d\n";
1339 void
1340 prdump(unsigned adrs, int ndump)
1342 register int n, m, c, r, nr;
1343 unsigned char temp[16];
1345 for( n = ndump; n > 0; ){
1346 printf("%.8x", adrs);
1347 putchar(' ');
1348 r = n < 16? n: 16;
1349 nr = mread(adrs, temp, r);
1350 adrs += nr;
1351 for( m = 0; m < r; ++m ){
1352 putchar((m & 3) == 0 && m > 0? '.': ' ');
1353 if( m < nr )
1354 printf("%.2x", temp[m]);
1355 else
1356 printf("%s", fault_chars[fault_type]);
1358 for(; m < 16; ++m )
1359 printf(" ");
1360 printf(" |");
1361 for( m = 0; m < r; ++m ){
1362 if( m < nr ){
1363 c = temp[m];
1364 putchar(' ' <= c && c <= '~'? c: '.');
1365 } else
1366 putchar(' ');
1368 n -= r;
1369 for(; m < 16; ++m )
1370 putchar(' ');
1371 printf("|\n");
1372 if( nr < r )
1373 break;
1378 ppc_inst_dump(unsigned adr, int count)
1380 int nr, dotted;
1381 unsigned first_adr;
1382 unsigned long inst, last_inst = 0;
1383 unsigned char val[4];
1385 dotted = 0;
1386 for (first_adr = adr; count > 0; --count, adr += 4){
1387 nr = mread(adr, val, 4);
1388 if( nr == 0 ){
1389 const char *x = fault_chars[fault_type];
1390 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1391 break;
1393 inst = GETWORD(val);
1394 if (adr > first_adr && inst == last_inst) {
1395 if (!dotted) {
1396 printf(" ...\n");
1397 dotted = 1;
1399 continue;
1401 dotted = 0;
1402 last_inst = inst;
1403 printf("%.8x ", adr);
1404 printf("%.8x\t", inst);
1405 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1406 printf("\n");
1408 return adr - first_adr;
1411 void
1412 print_address(unsigned addr)
1414 printf("0x%x", addr);
1418 * Memory operations - move, set, print differences
1420 static unsigned mdest; /* destination address */
1421 static unsigned msrc; /* source address */
1422 static unsigned mval; /* byte value to set memory to */
1423 static unsigned mcount; /* # bytes to affect */
1424 static unsigned mdiffs; /* max # differences to print */
1426 void
1427 memops(int cmd)
1429 scanhex(&mdest);
1430 if( termch != '\n' )
1431 termch = 0;
1432 scanhex(cmd == 's'? &mval: &msrc);
1433 if( termch != '\n' )
1434 termch = 0;
1435 scanhex(&mcount);
1436 switch( cmd ){
1437 case 'm':
1438 memmove((void *)mdest, (void *)msrc, mcount);
1439 break;
1440 case 's':
1441 memset((void *)mdest, mval, mcount);
1442 break;
1443 case 'd':
1444 if( termch != '\n' )
1445 termch = 0;
1446 scanhex(&mdiffs);
1447 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1448 break;
1452 void
1453 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1455 unsigned n, prt;
1457 prt = 0;
1458 for( n = nb; n > 0; --n )
1459 if( *p1++ != *p2++ )
1460 if( ++prt <= maxpr )
1461 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1462 p1[-1], (unsigned)p2 - 1, p2[-1]);
1463 if( prt > maxpr )
1464 printf("Total of %d differences\n", prt);
1467 static unsigned mend;
1468 static unsigned mask;
1470 void
1471 memlocate(void)
1473 unsigned a, n;
1474 unsigned char val[4];
1476 last_cmd = "ml";
1477 scanhex(&mdest);
1478 if (termch != '\n') {
1479 termch = 0;
1480 scanhex(&mend);
1481 if (termch != '\n') {
1482 termch = 0;
1483 scanhex(&mval);
1484 mask = ~0;
1485 if (termch != '\n') termch = 0;
1486 scanhex(&mask);
1489 n = 0;
1490 for (a = mdest; a < mend; a += 4) {
1491 if (mread(a, val, 4) == 4
1492 && ((GETWORD(val) ^ mval) & mask) == 0) {
1493 printf("%.8x: %.8x\n", a, GETWORD(val));
1494 if (++n >= 10)
1495 break;
1500 static unsigned mskip = 0x1000;
1501 static unsigned mlim = 0xffffffff;
1503 void
1504 memzcan(void)
1506 unsigned char v;
1507 unsigned a;
1508 int ok, ook;
1510 scanhex(&mdest);
1511 if (termch != '\n') termch = 0;
1512 scanhex(&mskip);
1513 if (termch != '\n') termch = 0;
1514 scanhex(&mlim);
1515 ook = 0;
1516 for (a = mdest; a < mlim; a += mskip) {
1517 ok = mread(a, &v, 1);
1518 if (ok && !ook) {
1519 printf("%.8x .. ", a);
1520 fflush(stdout);
1521 } else if (!ok && ook)
1522 printf("%.8x\n", a - mskip);
1523 ook = ok;
1524 if (a + mskip < a)
1525 break;
1527 if (ook)
1528 printf("%.8x\n", a - mskip);
1531 void proccall(void)
1533 unsigned int args[8];
1534 unsigned int ret;
1535 int i;
1536 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1537 unsigned int, unsigned int, unsigned int,
1538 unsigned int, unsigned int, unsigned int);
1539 callfunc_t func;
1541 scanhex(&adrs);
1542 if (termch != '\n')
1543 termch = 0;
1544 for (i = 0; i < 8; ++i)
1545 args[i] = 0;
1546 for (i = 0; i < 8; ++i) {
1547 if (!scanhex(&args[i]) || termch == '\n')
1548 break;
1549 termch = 0;
1551 func = (callfunc_t) adrs;
1552 ret = 0;
1553 if (setjmp(bus_error_jmp) == 0) {
1554 debugger_fault_handler = handle_fault;
1555 sync();
1556 ret = func(args[0], args[1], args[2], args[3],
1557 args[4], args[5], args[6], args[7]);
1558 sync();
1559 printf("return value is %x\n", ret);
1560 } else {
1561 printf("*** %x exception occurred\n", fault_except);
1563 debugger_fault_handler = NULL;
1566 /* Input scanning routines */
1568 skipbl(void)
1570 int c;
1572 if( termch != 0 ){
1573 c = termch;
1574 termch = 0;
1575 } else
1576 c = inchar();
1577 while( c == ' ' || c == '\t' )
1578 c = inchar();
1579 return c;
1582 #define N_PTREGS 44
1583 static char *regnames[N_PTREGS] = {
1584 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1585 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1586 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1587 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1588 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1589 "trap", "dar", "dsisr", "res"
1593 scanhex(unsigned *vp)
1595 int c, d;
1596 unsigned v;
1598 c = skipbl();
1599 if (c == '%') {
1600 /* parse register name */
1601 char regname[8];
1602 int i;
1604 for (i = 0; i < sizeof(regname) - 1; ++i) {
1605 c = inchar();
1606 if (!isalnum(c)) {
1607 termch = c;
1608 break;
1610 regname[i] = c;
1612 regname[i] = 0;
1613 for (i = 0; i < N_PTREGS; ++i) {
1614 if (strcmp(regnames[i], regname) == 0) {
1615 unsigned *rp = (unsigned *)
1616 xmon_regs[smp_processor_id()];
1617 if (rp == NULL) {
1618 printf("regs not available\n");
1619 return 0;
1621 *vp = rp[i];
1622 return 1;
1625 printf("invalid register name '%%%s'\n", regname);
1626 return 0;
1627 } else if (c == '$') {
1628 static char symname[128];
1629 int i;
1630 for (i=0; i<63; i++) {
1631 c = inchar();
1632 if (isspace(c)) {
1633 termch = c;
1634 break;
1636 symname[i] = c;
1638 symname[i++] = 0;
1639 *vp = 0;
1640 if (setjmp(bus_error_jmp) == 0) {
1641 debugger_fault_handler = handle_fault;
1642 sync();
1643 *vp = kallsyms_lookup_name(symname);
1644 sync();
1646 debugger_fault_handler = NULL;
1647 if (!(*vp)) {
1648 printf("unknown symbol\n");
1649 return 0;
1651 return 1;
1654 d = hexdigit(c);
1655 if( d == EOF ){
1656 termch = c;
1657 return 0;
1659 v = 0;
1660 do {
1661 v = (v << 4) + d;
1662 c = inchar();
1663 d = hexdigit(c);
1664 } while( d != EOF );
1665 termch = c;
1666 *vp = v;
1667 return 1;
1670 void
1671 scannl(void)
1673 int c;
1675 c = termch;
1676 termch = 0;
1677 while( c != '\n' )
1678 c = inchar();
1681 int hexdigit(int c)
1683 if( '0' <= c && c <= '9' )
1684 return c - '0';
1685 if( 'A' <= c && c <= 'F' )
1686 return c - ('A' - 10);
1687 if( 'a' <= c && c <= 'f' )
1688 return c - ('a' - 10);
1689 return EOF;
1692 void
1693 getstring(char *s, int size)
1695 int c;
1697 c = skipbl();
1698 do {
1699 if( size > 1 ){
1700 *s++ = c;
1701 --size;
1703 c = inchar();
1704 } while( c != ' ' && c != '\t' && c != '\n' );
1705 termch = c;
1706 *s = 0;
1709 static char line[256];
1710 static char *lineptr;
1712 void
1713 flush_input(void)
1715 lineptr = NULL;
1719 inchar(void)
1721 if (lineptr == NULL || *lineptr == 0) {
1722 if (fgets(line, sizeof(line), stdin) == NULL) {
1723 lineptr = NULL;
1724 return EOF;
1726 lineptr = line;
1728 return *lineptr++;
1731 void
1732 take_input(char *str)
1734 lineptr = str;
1737 static void
1738 symbol_lookup(void)
1740 int type = inchar();
1741 unsigned addr;
1742 static char tmp[128];
1744 switch (type) {
1745 case 'a':
1746 if (scanhex(&addr))
1747 xmon_print_symbol(addr, ": ", "\n");
1748 termch = 0;
1749 break;
1750 case 's':
1751 getstring(tmp, 64);
1752 if (setjmp(bus_error_jmp) == 0) {
1753 debugger_fault_handler = handle_fault;
1754 sync();
1755 addr = kallsyms_lookup_name(tmp);
1756 if (addr)
1757 printf("%s: %lx\n", tmp, addr);
1758 else
1759 printf("Symbol '%s' not found.\n", tmp);
1760 sync();
1762 debugger_fault_handler = NULL;
1763 termch = 0;
1764 break;