[PATCH] RPC: rename the sockstate field
[linux-2.6/verdex.git] / arch / ppc / xmon / xmon.c
blobbe7869e394651eea0647e0234ef08798e6b33488
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/prom.h>
16 #include <asm/bootx.h>
17 #include <asm/machdep.h>
18 #include <asm/xmon.h>
19 #ifdef CONFIG_PMAC_BACKLIGHT
20 #include <asm/backlight.h>
21 #endif
22 #include "nonstdio.h"
23 #include "privinst.h"
25 #define scanhex xmon_scanhex
26 #define skipbl xmon_skipbl
28 #ifdef CONFIG_SMP
29 static unsigned long cpus_in_xmon = 0;
30 static unsigned long got_xmon = 0;
31 static volatile int take_xmon = -1;
32 #endif /* CONFIG_SMP */
34 static unsigned adrs;
35 static int size = 1;
36 static unsigned ndump = 64;
37 static unsigned nidump = 16;
38 static unsigned ncsum = 4096;
39 static int termch;
41 static u_int bus_error_jmp[100];
42 #define setjmp xmon_setjmp
43 #define longjmp xmon_longjmp
45 /* Breakpoint stuff */
46 struct bpt {
47 unsigned address;
48 unsigned instr;
49 unsigned count;
50 unsigned char enabled;
53 #define NBPTS 16
54 static struct bpt bpts[NBPTS];
55 static struct bpt dabr;
56 static struct bpt iabr;
57 static unsigned bpinstr = 0x7fe00008; /* trap */
59 /* Prototypes */
60 extern void (*debugger_fault_handler)(struct pt_regs *);
61 static int cmds(struct pt_regs *);
62 static int mread(unsigned, void *, int);
63 static int mwrite(unsigned, void *, int);
64 static void handle_fault(struct pt_regs *);
65 static void byterev(unsigned char *, int);
66 static void memex(void);
67 static int bsesc(void);
68 static void dump(void);
69 static void prdump(unsigned, int);
70 #ifdef __MWERKS__
71 static void prndump(unsigned, int);
72 static int nvreadb(unsigned);
73 #endif
74 static int ppc_inst_dump(unsigned, int);
75 void print_address(unsigned);
76 static int getsp(void);
77 static void dump_hash_table(void);
78 static void backtrace(struct pt_regs *);
79 static void excprint(struct pt_regs *);
80 static void prregs(struct pt_regs *);
81 static void memops(int);
82 static void memlocate(void);
83 static void memzcan(void);
84 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
85 int skipbl(void);
86 int scanhex(unsigned *valp);
87 static void scannl(void);
88 static int hexdigit(int);
89 void getstring(char *, int);
90 static void flush_input(void);
91 static int inchar(void);
92 static void take_input(char *);
93 /* static void openforth(void); */
94 static unsigned read_spr(int);
95 static void write_spr(int, unsigned);
96 static void super_regs(void);
97 static void symbol_lookup(void);
98 static void remove_bpts(void);
99 static void insert_bpts(void);
100 static struct bpt *at_breakpoint(unsigned pc);
101 static void bpt_cmds(void);
102 static void cacheflush(void);
103 #ifdef CONFIG_SMP
104 static void cpu_cmd(void);
105 #endif /* CONFIG_SMP */
106 static void csum(void);
107 #ifdef CONFIG_BOOTX_TEXT
108 static void vidcmds(void);
109 #endif
110 static void bootcmds(void);
111 static void proccall(void);
112 static void printtime(void);
114 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
115 extern void printf(const char *fmt, ...);
116 extern int putchar(int ch);
117 extern int setjmp(u_int *);
118 extern void longjmp(u_int *, int);
120 extern void xmon_enter(void);
121 extern void xmon_leave(void);
123 static unsigned start_tb[NR_CPUS][2];
124 static unsigned stop_tb[NR_CPUS][2];
126 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
128 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
129 || ('a' <= (c) && (c) <= 'f') \
130 || ('A' <= (c) && (c) <= 'F'))
131 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
132 || ('a' <= (c) && (c) <= 'z') \
133 || ('A' <= (c) && (c) <= 'Z'))
134 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
136 static char *help_string = "\
137 Commands:\n\
138 d dump bytes\n\
139 di dump instructions\n\
140 df dump float values\n\
141 dd dump double values\n\
142 e print exception information\n\
143 h dump hash table\n\
144 m examine/change memory\n\
145 mm move a block of memory\n\
146 ms set a block of memory\n\
147 md compare two blocks of memory\n\
148 r print registers\n\
149 S print special registers\n\
150 t print backtrace\n\
151 la lookup address in system.map\n\
152 ls lookup symbol in system.map\n\
153 x exit monitor\n\
156 static int xmon_trace[NR_CPUS];
157 #define SSTEP 1 /* stepping because of 's' command */
158 #define BRSTEP 2 /* stepping over breakpoint */
160 static struct pt_regs *xmon_regs[NR_CPUS];
162 extern inline void sync(void)
164 asm volatile("sync; isync");
167 extern inline void __delay(unsigned int loops)
169 if (loops != 0)
170 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
171 "r" (loops) : "ctr");
174 /* Print an address in numeric and symbolic form (if possible) */
175 static void xmon_print_symbol(unsigned long address, const char *mid,
176 const char *after)
178 char *modname;
179 const char *name = NULL;
180 unsigned long offset, size;
181 static char tmpstr[128];
183 printf("%.8lx", address);
184 if (setjmp(bus_error_jmp) == 0) {
185 debugger_fault_handler = handle_fault;
186 sync();
187 name = kallsyms_lookup(address, &size, &offset, &modname,
188 tmpstr);
189 sync();
190 /* wait a little while to see if we get a machine check */
191 __delay(200);
193 debugger_fault_handler = NULL;
195 if (name) {
196 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
197 if (modname)
198 printf(" [%s]", modname);
200 printf("%s", after);
203 static void get_tb(unsigned *p)
205 unsigned hi, lo, hiagain;
207 if ((get_pvr() >> 16) == 1)
208 return;
210 do {
211 asm volatile("mftbu %0; mftb %1; mftbu %2"
212 : "=r" (hi), "=r" (lo), "=r" (hiagain));
213 } while (hi != hiagain);
214 p[0] = hi;
215 p[1] = lo;
218 void
219 xmon(struct pt_regs *excp)
221 struct pt_regs regs;
222 int msr, cmd;
224 get_tb(stop_tb[smp_processor_id()]);
225 if (excp == NULL) {
226 asm volatile ("stw 0,0(%0)\n\
227 lwz 0,0(1)\n\
228 stw 0,4(%0)\n\
229 stmw 2,8(%0)" : : "b" (&regs));
230 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
231 regs.msr = get_msr();
232 regs.ctr = get_ctr();
233 regs.xer = get_xer();
234 regs.ccr = get_cr();
235 regs.trap = 0;
236 excp = &regs;
239 msr = get_msr();
240 set_msr(msr & ~0x8000); /* disable interrupts */
241 xmon_regs[smp_processor_id()] = excp;
242 xmon_enter();
243 excprint(excp);
244 #ifdef CONFIG_SMP
245 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
246 for (;;)
248 while (test_and_set_bit(0, &got_xmon)) {
249 if (take_xmon == smp_processor_id()) {
250 take_xmon = -1;
251 break;
255 * XXX: breakpoints are removed while any cpu is in xmon
257 #endif /* CONFIG_SMP */
258 remove_bpts();
259 #ifdef CONFIG_PMAC_BACKLIGHT
260 if( setjmp(bus_error_jmp) == 0 ) {
261 debugger_fault_handler = handle_fault;
262 sync();
263 set_backlight_enable(1);
264 set_backlight_level(BACKLIGHT_MAX);
265 sync();
267 debugger_fault_handler = NULL;
268 #endif /* CONFIG_PMAC_BACKLIGHT */
269 cmd = cmds(excp);
270 if (cmd == 's') {
271 xmon_trace[smp_processor_id()] = SSTEP;
272 excp->msr |= 0x400;
273 } else if (at_breakpoint(excp->nip)) {
274 xmon_trace[smp_processor_id()] = BRSTEP;
275 excp->msr |= 0x400;
276 } else {
277 xmon_trace[smp_processor_id()] = 0;
278 insert_bpts();
280 xmon_leave();
281 xmon_regs[smp_processor_id()] = NULL;
282 #ifdef CONFIG_SMP
283 clear_bit(0, &got_xmon);
284 clear_bit(smp_processor_id(), &cpus_in_xmon);
285 #endif /* CONFIG_SMP */
286 set_msr(msr); /* restore interrupt enable */
287 get_tb(start_tb[smp_processor_id()]);
290 irqreturn_t
291 xmon_irq(int irq, void *d, struct pt_regs *regs)
293 unsigned long flags;
294 local_irq_save(flags);
295 printf("Keyboard interrupt\n");
296 xmon(regs);
297 local_irq_restore(flags);
298 return IRQ_HANDLED;
302 xmon_bpt(struct pt_regs *regs)
304 struct bpt *bp;
306 bp = at_breakpoint(regs->nip);
307 if (!bp)
308 return 0;
309 if (bp->count) {
310 --bp->count;
311 remove_bpts();
312 excprint(regs);
313 xmon_trace[smp_processor_id()] = BRSTEP;
314 regs->msr |= 0x400;
315 } else {
316 xmon(regs);
318 return 1;
322 xmon_sstep(struct pt_regs *regs)
324 if (!xmon_trace[smp_processor_id()])
325 return 0;
326 if (xmon_trace[smp_processor_id()] == BRSTEP) {
327 xmon_trace[smp_processor_id()] = 0;
328 insert_bpts();
329 } else {
330 xmon(regs);
332 return 1;
336 xmon_dabr_match(struct pt_regs *regs)
338 if (dabr.enabled && dabr.count) {
339 --dabr.count;
340 remove_bpts();
341 excprint(regs);
342 xmon_trace[smp_processor_id()] = BRSTEP;
343 regs->msr |= 0x400;
344 } else {
345 dabr.instr = regs->nip;
346 xmon(regs);
348 return 1;
352 xmon_iabr_match(struct pt_regs *regs)
354 if (iabr.enabled && iabr.count) {
355 --iabr.count;
356 remove_bpts();
357 excprint(regs);
358 xmon_trace[smp_processor_id()] = BRSTEP;
359 regs->msr |= 0x400;
360 } else {
361 xmon(regs);
363 return 1;
366 static struct bpt *
367 at_breakpoint(unsigned pc)
369 int i;
370 struct bpt *bp;
372 if (dabr.enabled && pc == dabr.instr)
373 return &dabr;
374 if (iabr.enabled && pc == iabr.address)
375 return &iabr;
376 bp = bpts;
377 for (i = 0; i < NBPTS; ++i, ++bp)
378 if (bp->enabled && pc == bp->address)
379 return bp;
380 return NULL;
383 static void
384 insert_bpts(void)
386 int i;
387 struct bpt *bp;
389 bp = bpts;
390 for (i = 0; i < NBPTS; ++i, ++bp) {
391 if (!bp->enabled)
392 continue;
393 if (mread(bp->address, &bp->instr, 4) != 4
394 || mwrite(bp->address, &bpinstr, 4) != 4) {
395 printf("Couldn't insert breakpoint at %x, disabling\n",
396 bp->address);
397 bp->enabled = 0;
399 store_inst((void *) bp->address);
401 #if !defined(CONFIG_8xx)
402 if (dabr.enabled)
403 set_dabr(dabr.address);
404 if (iabr.enabled)
405 set_iabr(iabr.address);
406 #endif
409 static void
410 remove_bpts(void)
412 int i;
413 struct bpt *bp;
414 unsigned instr;
416 #if !defined(CONFIG_8xx)
417 set_dabr(0);
418 set_iabr(0);
419 #endif
420 bp = bpts;
421 for (i = 0; i < NBPTS; ++i, ++bp) {
422 if (!bp->enabled)
423 continue;
424 if (mread(bp->address, &instr, 4) == 4
425 && instr == bpinstr
426 && mwrite(bp->address, &bp->instr, 4) != 4)
427 printf("Couldn't remove breakpoint at %x\n",
428 bp->address);
429 store_inst((void *) bp->address);
433 static char *last_cmd;
435 /* Command interpreting routine */
436 static int
437 cmds(struct pt_regs *excp)
439 int cmd;
441 last_cmd = NULL;
442 for(;;) {
443 #ifdef CONFIG_SMP
444 printf("%d:", smp_processor_id());
445 #endif /* CONFIG_SMP */
446 printf("mon> ");
447 fflush(stdout);
448 flush_input();
449 termch = 0;
450 cmd = skipbl();
451 if( cmd == '\n' ) {
452 if (last_cmd == NULL)
453 continue;
454 take_input(last_cmd);
455 last_cmd = NULL;
456 cmd = inchar();
458 switch (cmd) {
459 case 'm':
460 cmd = inchar();
461 switch (cmd) {
462 case 'm':
463 case 's':
464 case 'd':
465 memops(cmd);
466 break;
467 case 'l':
468 memlocate();
469 break;
470 case 'z':
471 memzcan();
472 break;
473 default:
474 termch = cmd;
475 memex();
477 break;
478 case 'd':
479 dump();
480 break;
481 case 'l':
482 symbol_lookup();
483 break;
484 case 'r':
485 if (excp != NULL)
486 prregs(excp); /* print regs */
487 break;
488 case 'e':
489 if (excp == NULL)
490 printf("No exception information\n");
491 else
492 excprint(excp);
493 break;
494 case 'S':
495 super_regs();
496 break;
497 case 't':
498 backtrace(excp);
499 break;
500 case 'f':
501 cacheflush();
502 break;
503 case 'h':
504 dump_hash_table();
505 break;
506 case 's':
507 case 'x':
508 case EOF:
509 return cmd;
510 case '?':
511 printf(help_string);
512 break;
513 default:
514 printf("Unrecognized command: ");
515 if( ' ' < cmd && cmd <= '~' )
516 putchar(cmd);
517 else
518 printf("\\x%x", cmd);
519 printf(" (type ? for help)\n");
520 break;
521 case 'b':
522 bpt_cmds();
523 break;
524 case 'C':
525 csum();
526 break;
527 #ifdef CONFIG_SMP
528 case 'c':
529 cpu_cmd();
530 break;
531 #endif /* CONFIG_SMP */
532 #ifdef CONFIG_BOOTX_TEXT
533 case 'v':
534 vidcmds();
535 break;
536 #endif
537 case 'z':
538 bootcmds();
539 break;
540 case 'p':
541 proccall();
542 break;
543 case 'T':
544 printtime();
545 break;
550 extern unsigned tb_to_us;
552 #define mulhwu(x,y) \
553 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
555 static void printtime(void)
557 unsigned int delta;
559 delta = stop_tb[smp_processor_id()][1]
560 - start_tb[smp_processor_id()][1];
561 delta = mulhwu(tb_to_us, delta);
562 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
565 static void bootcmds(void)
567 int cmd;
569 cmd = inchar();
570 if (cmd == 'r')
571 ppc_md.restart(NULL);
572 else if (cmd == 'h')
573 ppc_md.halt();
574 else if (cmd == 'p')
575 ppc_md.power_off();
578 #ifdef CONFIG_SMP
579 static void cpu_cmd(void)
581 unsigned cpu;
582 int timeout;
583 int cmd;
585 cmd = inchar();
586 if (cmd == 'i') {
587 /* interrupt other cpu(s) */
588 cpu = MSG_ALL_BUT_SELF;
589 if (scanhex(&cpu))
590 smp_send_xmon_break(cpu);
591 return;
593 termch = cmd;
594 if (!scanhex(&cpu)) {
595 /* print cpus waiting or in xmon */
596 printf("cpus stopped:");
597 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
598 if (test_bit(cpu, &cpus_in_xmon)) {
599 printf(" %d", cpu);
600 if (cpu == smp_processor_id())
601 printf("*", cpu);
604 printf("\n");
605 return;
607 /* try to switch to cpu specified */
608 take_xmon = cpu;
609 timeout = 10000000;
610 while (take_xmon >= 0) {
611 if (--timeout == 0) {
612 /* yes there's a race here */
613 take_xmon = -1;
614 printf("cpu %u didn't take control\n", cpu);
615 return;
618 /* now have to wait to be given control back */
619 while (test_and_set_bit(0, &got_xmon)) {
620 if (take_xmon == smp_processor_id()) {
621 take_xmon = -1;
622 break;
626 #endif /* CONFIG_SMP */
628 #ifdef CONFIG_BOOTX_TEXT
629 extern boot_infos_t disp_bi;
631 static void vidcmds(void)
633 int c = inchar();
634 unsigned int val, w;
635 extern int boot_text_mapped;
637 if (!boot_text_mapped)
638 return;
639 if (c != '\n' && scanhex(&val)) {
640 switch (c) {
641 case 'd':
642 w = disp_bi.dispDeviceRowBytes
643 / (disp_bi.dispDeviceDepth >> 3);
644 disp_bi.dispDeviceDepth = val;
645 disp_bi.dispDeviceRowBytes = w * (val >> 3);
646 return;
647 case 'p':
648 disp_bi.dispDeviceRowBytes = val;
649 return;
650 case 'w':
651 disp_bi.dispDeviceRect[2] = val;
652 return;
653 case 'h':
654 disp_bi.dispDeviceRect[3] = val;
655 return;
658 printf("W = %d (0x%x) H = %d (0x%x) D = %d (0x%x) P = %d (0x%x)\n",
659 disp_bi.dispDeviceRect[2], disp_bi.dispDeviceRect[2],
660 disp_bi.dispDeviceRect[3], disp_bi.dispDeviceRect[3],
661 disp_bi.dispDeviceDepth, disp_bi.dispDeviceDepth,
662 disp_bi.dispDeviceRowBytes, disp_bi.dispDeviceRowBytes);
664 #endif /* CONFIG_BOOTX_TEXT */
666 static unsigned short fcstab[256] = {
667 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
668 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
669 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
670 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
671 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
672 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
673 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
674 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
675 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
676 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
677 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
678 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
679 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
680 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
681 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
682 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
683 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
684 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
685 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
686 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
687 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
688 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
689 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
690 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
691 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
692 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
693 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
694 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
695 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
696 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
697 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
698 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
701 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
703 static void
704 csum(void)
706 unsigned int i;
707 unsigned short fcs;
708 unsigned char v;
710 if (!scanhex(&adrs))
711 return;
712 if (!scanhex(&ncsum))
713 return;
714 fcs = 0xffff;
715 for (i = 0; i < ncsum; ++i) {
716 if (mread(adrs+i, &v, 1) == 0) {
717 printf("csum stopped at %x\n", adrs+i);
718 break;
720 fcs = FCS(fcs, v);
722 printf("%x\n", fcs);
725 static void
726 bpt_cmds(void)
728 int cmd;
729 unsigned a;
730 int mode, i;
731 struct bpt *bp;
733 cmd = inchar();
734 switch (cmd) {
735 #if !defined(CONFIG_8xx)
736 case 'd':
737 mode = 7;
738 cmd = inchar();
739 if (cmd == 'r')
740 mode = 5;
741 else if (cmd == 'w')
742 mode = 6;
743 else
744 termch = cmd;
745 cmd = inchar();
746 if (cmd == 'p')
747 mode &= ~4;
748 else
749 termch = cmd;
750 dabr.address = 0;
751 dabr.count = 0;
752 dabr.enabled = scanhex(&dabr.address);
753 scanhex(&dabr.count);
754 if (dabr.enabled)
755 dabr.address = (dabr.address & ~7) | mode;
756 break;
757 case 'i':
758 cmd = inchar();
759 if (cmd == 'p')
760 mode = 2;
761 else
762 mode = 3;
763 iabr.address = 0;
764 iabr.count = 0;
765 iabr.enabled = scanhex(&iabr.address);
766 if (iabr.enabled)
767 iabr.address |= mode;
768 scanhex(&iabr.count);
769 break;
770 #endif
771 case 'c':
772 if (!scanhex(&a)) {
773 /* clear all breakpoints */
774 for (i = 0; i < NBPTS; ++i)
775 bpts[i].enabled = 0;
776 iabr.enabled = 0;
777 dabr.enabled = 0;
778 printf("All breakpoints cleared\n");
779 } else {
780 bp = at_breakpoint(a);
781 if (bp == 0) {
782 printf("No breakpoint at %x\n", a);
783 } else {
784 bp->enabled = 0;
787 break;
788 default:
789 termch = cmd;
790 if (!scanhex(&a)) {
791 /* print all breakpoints */
792 printf("type address count\n");
793 if (dabr.enabled) {
794 printf("data %.8x %8x [", dabr.address & ~7,
795 dabr.count);
796 if (dabr.address & 1)
797 printf("r");
798 if (dabr.address & 2)
799 printf("w");
800 if (!(dabr.address & 4))
801 printf("p");
802 printf("]\n");
804 if (iabr.enabled)
805 printf("inst %.8x %8x\n", iabr.address & ~3,
806 iabr.count);
807 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
808 if (bp->enabled)
809 printf("trap %.8x %8x\n", bp->address,
810 bp->count);
811 break;
813 bp = at_breakpoint(a);
814 if (bp == 0) {
815 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
816 if (!bp->enabled)
817 break;
818 if (bp >= &bpts[NBPTS]) {
819 printf("Sorry, no free breakpoints\n");
820 break;
823 bp->enabled = 1;
824 bp->address = a;
825 bp->count = 0;
826 scanhex(&bp->count);
827 break;
831 static void
832 backtrace(struct pt_regs *excp)
834 unsigned sp;
835 unsigned stack[2];
836 struct pt_regs regs;
837 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
839 printf("backtrace:\n");
841 if (excp != NULL)
842 sp = excp->gpr[1];
843 else
844 sp = getsp();
845 scanhex(&sp);
846 scannl();
847 for (; sp != 0; sp = stack[0]) {
848 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
849 break;
850 printf("[%.8lx] ", stack);
851 xmon_print_symbol(stack[1], " ", "\n");
852 if (stack[1] == (unsigned) &ret_from_except
853 || stack[1] == (unsigned) &ret_from_except_full
854 || stack[1] == (unsigned) &ret_from_syscall) {
855 if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
856 break;
857 printf("exception:%x [%x] %x\n", regs.trap, sp+16,
858 regs.nip);
859 sp = regs.gpr[1];
860 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
861 break;
867 getsp(void)
869 int x;
871 asm("mr %0,1" : "=r" (x) :);
872 return x;
875 void
876 excprint(struct pt_regs *fp)
878 int trap;
880 #ifdef CONFIG_SMP
881 printf("cpu %d: ", smp_processor_id());
882 #endif /* CONFIG_SMP */
883 printf("vector: %x at pc=", fp->trap);
884 xmon_print_symbol(fp->nip, ": ", ", lr=");
885 xmon_print_symbol(fp->link, ": ", "\n");
886 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
887 trap = TRAP(fp);
888 if (trap == 0x300 || trap == 0x600)
889 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
890 if (current)
891 printf("current = %x, pid = %d, comm = %s\n",
892 current, current->pid, current->comm);
895 void
896 prregs(struct pt_regs *fp)
898 int n;
899 unsigned base;
901 if (scanhex(&base))
902 fp = (struct pt_regs *) base;
903 for (n = 0; n < 32; ++n) {
904 printf("R%.2d = %.8x%s", n, fp->gpr[n],
905 (n & 3) == 3? "\n": " ");
906 if (n == 12 && !FULL_REGS(fp)) {
907 printf("\n");
908 break;
911 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
912 fp->nip, fp->msr, fp->link, fp->ccr);
913 printf("ctr = %.8x xer = %.8x trap = %4x\n",
914 fp->ctr, fp->xer, fp->trap);
917 void
918 cacheflush(void)
920 int cmd;
921 unsigned nflush;
923 cmd = inchar();
924 if (cmd != 'i')
925 termch = cmd;
926 scanhex(&adrs);
927 if (termch != '\n')
928 termch = 0;
929 nflush = 1;
930 scanhex(&nflush);
931 nflush = (nflush + 31) / 32;
932 if (cmd != 'i') {
933 for (; nflush > 0; --nflush, adrs += 0x20)
934 cflush((void *) adrs);
935 } else {
936 for (; nflush > 0; --nflush, adrs += 0x20)
937 cinval((void *) adrs);
941 unsigned int
942 read_spr(int n)
944 unsigned int instrs[2];
945 int (*code)(void);
947 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
948 instrs[1] = 0x4e800020;
949 store_inst(instrs);
950 store_inst(instrs+1);
951 code = (int (*)(void)) instrs;
952 return code();
955 void
956 write_spr(int n, unsigned int val)
958 unsigned int instrs[2];
959 int (*code)(unsigned int);
961 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
962 instrs[1] = 0x4e800020;
963 store_inst(instrs);
964 store_inst(instrs+1);
965 code = (int (*)(unsigned int)) instrs;
966 code(val);
969 static unsigned int regno;
970 extern char exc_prolog;
971 extern char dec_exc;
973 void
974 super_regs(void)
976 int i, cmd;
977 unsigned val;
979 cmd = skipbl();
980 if (cmd == '\n') {
981 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
982 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
983 get_sprg2(), get_sprg3());
984 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
985 #ifdef CONFIG_PPC_STD_MMU
986 printf("sr0-15 =");
987 for (i = 0; i < 16; ++i)
988 printf(" %x", get_sr(i));
989 printf("\n");
990 #endif
991 asm("mr %0,1" : "=r" (i) :);
992 printf("sp = %x ", i);
993 asm("mr %0,2" : "=r" (i) :);
994 printf("toc = %x\n", i);
995 return;
998 scanhex(&regno);
999 switch (cmd) {
1000 case 'w':
1001 val = read_spr(regno);
1002 scanhex(&val);
1003 write_spr(regno, val);
1004 /* fall through */
1005 case 'r':
1006 printf("spr %x = %x\n", regno, read_spr(regno));
1007 break;
1008 case 's':
1009 val = get_sr(regno);
1010 scanhex(&val);
1011 set_sr(regno, val);
1012 break;
1013 case 'm':
1014 val = get_msr();
1015 scanhex(&val);
1016 set_msr(val);
1017 break;
1019 scannl();
1022 #ifndef CONFIG_PPC_STD_MMU
1023 static void
1024 dump_hash_table(void)
1026 printf("This CPU doesn't have a hash table.\n");
1028 #else
1030 #ifndef CONFIG_PPC64BRIDGE
1031 static void
1032 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1034 extern void *Hash;
1035 extern unsigned long Hash_size;
1036 unsigned *htab = Hash;
1037 unsigned hsize = Hash_size;
1038 unsigned v, hmask, va, last_va = 0;
1039 int found, last_found, i;
1040 unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
1042 last_found = 0;
1043 hmask = hsize / 64 - 1;
1044 va = start;
1045 start = (start >> 12) & 0xffff;
1046 end = (end >> 12) & 0xffff;
1047 for (v = start; v < end; ++v) {
1048 found = 0;
1049 hg = htab + (((v ^ seg) & hmask) * 16);
1050 w1 = 0x80000000 | (seg << 7) | (v >> 10);
1051 for (i = 0; i < 8; ++i, hg += 2) {
1052 if (*hg == w1) {
1053 found = 1;
1054 break;
1057 if (!found) {
1058 w1 ^= 0x40;
1059 hg = htab + ((~(v ^ seg) & hmask) * 16);
1060 for (i = 0; i < 8; ++i, hg += 2) {
1061 if (*hg == w1) {
1062 found = 1;
1063 break;
1067 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1068 if (last_found) {
1069 if (last_va != last_va0)
1070 printf(" ... %x", last_va);
1071 printf("\n");
1073 if (found) {
1074 printf("%x to %x", va, hg[1]);
1075 last_va0 = va;
1077 last_found = found;
1079 if (found) {
1080 last_w2 = hg[1] & ~0x180;
1081 last_va = va;
1083 va += 4096;
1085 if (last_found)
1086 printf(" ... %x\n", last_va);
1089 #else /* CONFIG_PPC64BRIDGE */
1090 static void
1091 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1093 extern void *Hash;
1094 extern unsigned long Hash_size;
1095 unsigned *htab = Hash;
1096 unsigned hsize = Hash_size;
1097 unsigned v, hmask, va, last_va;
1098 int found, last_found, i;
1099 unsigned *hg, w1, last_w2, last_va0;
1101 last_found = 0;
1102 hmask = hsize / 128 - 1;
1103 va = start;
1104 start = (start >> 12) & 0xffff;
1105 end = (end >> 12) & 0xffff;
1106 for (v = start; v < end; ++v) {
1107 found = 0;
1108 hg = htab + (((v ^ seg) & hmask) * 32);
1109 w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
1110 for (i = 0; i < 8; ++i, hg += 4) {
1111 if (hg[1] == w1) {
1112 found = 1;
1113 break;
1116 if (!found) {
1117 w1 ^= 2;
1118 hg = htab + ((~(v ^ seg) & hmask) * 32);
1119 for (i = 0; i < 8; ++i, hg += 4) {
1120 if (hg[1] == w1) {
1121 found = 1;
1122 break;
1126 if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
1127 if (last_found) {
1128 if (last_va != last_va0)
1129 printf(" ... %x", last_va);
1130 printf("\n");
1132 if (found) {
1133 printf("%x to %x", va, hg[3]);
1134 last_va0 = va;
1136 last_found = found;
1138 if (found) {
1139 last_w2 = hg[3] & ~0x180;
1140 last_va = va;
1142 va += 4096;
1144 if (last_found)
1145 printf(" ... %x\n", last_va);
1147 #endif /* CONFIG_PPC64BRIDGE */
1149 static unsigned hash_ctx;
1150 static unsigned hash_start;
1151 static unsigned hash_end;
1153 static void
1154 dump_hash_table(void)
1156 int seg;
1157 unsigned seg_start, seg_end;
1159 hash_ctx = 0;
1160 hash_start = 0;
1161 hash_end = 0xfffff000;
1162 scanhex(&hash_ctx);
1163 scanhex(&hash_start);
1164 scanhex(&hash_end);
1165 printf("Mappings for context %x\n", hash_ctx);
1166 seg_start = hash_start;
1167 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1168 seg_end = (seg << 28) | 0x0ffff000;
1169 if (seg_end > hash_end)
1170 seg_end = hash_end;
1171 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1172 seg_start, seg_end);
1173 seg_start = seg_end + 0x1000;
1176 #endif /* CONFIG_PPC_STD_MMU */
1179 * Stuff for reading and writing memory safely
1183 mread(unsigned adrs, void *buf, int size)
1185 volatile int n;
1186 char *p, *q;
1188 n = 0;
1189 if( setjmp(bus_error_jmp) == 0 ){
1190 debugger_fault_handler = handle_fault;
1191 sync();
1192 p = (char *) adrs;
1193 q = (char *) buf;
1194 switch (size) {
1195 case 2: *(short *)q = *(short *)p; break;
1196 case 4: *(int *)q = *(int *)p; break;
1197 default:
1198 for( ; n < size; ++n ) {
1199 *q++ = *p++;
1200 sync();
1203 sync();
1204 /* wait a little while to see if we get a machine check */
1205 __delay(200);
1206 n = size;
1208 debugger_fault_handler = NULL;
1209 return n;
1213 mwrite(unsigned adrs, void *buf, int size)
1215 volatile int n;
1216 char *p, *q;
1218 n = 0;
1219 if( setjmp(bus_error_jmp) == 0 ){
1220 debugger_fault_handler = handle_fault;
1221 sync();
1222 p = (char *) adrs;
1223 q = (char *) buf;
1224 switch (size) {
1225 case 2: *(short *)p = *(short *)q; break;
1226 case 4: *(int *)p = *(int *)q; break;
1227 default:
1228 for( ; n < size; ++n ) {
1229 *p++ = *q++;
1230 sync();
1233 sync();
1234 n = size;
1235 } else {
1236 printf("*** Error writing address %x\n", adrs + n);
1238 debugger_fault_handler = NULL;
1239 return n;
1242 static int fault_type;
1243 static int fault_except;
1244 static char *fault_chars[] = { "--", "**", "##" };
1246 static void
1247 handle_fault(struct pt_regs *regs)
1249 fault_except = TRAP(regs);
1250 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1251 longjmp(bus_error_jmp, 1);
1254 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1256 void
1257 byterev(unsigned char *val, int size)
1259 int t;
1261 switch (size) {
1262 case 2:
1263 SWAP(val[0], val[1], t);
1264 break;
1265 case 4:
1266 SWAP(val[0], val[3], t);
1267 SWAP(val[1], val[2], t);
1268 break;
1272 static int brev;
1273 static int mnoread;
1275 void
1276 memex(void)
1278 int cmd, inc, i, nslash;
1279 unsigned n;
1280 unsigned char val[4];
1282 last_cmd = "m\n";
1283 scanhex(&adrs);
1284 while ((cmd = skipbl()) != '\n') {
1285 switch( cmd ){
1286 case 'b': size = 1; break;
1287 case 'w': size = 2; break;
1288 case 'l': size = 4; break;
1289 case 'r': brev = !brev; break;
1290 case 'n': mnoread = 1; break;
1291 case '.': mnoread = 0; break;
1294 if( size <= 0 )
1295 size = 1;
1296 else if( size > 4 )
1297 size = 4;
1298 for(;;){
1299 if (!mnoread)
1300 n = mread(adrs, val, size);
1301 printf("%.8x%c", adrs, brev? 'r': ' ');
1302 if (!mnoread) {
1303 if (brev)
1304 byterev(val, size);
1305 putchar(' ');
1306 for (i = 0; i < n; ++i)
1307 printf("%.2x", val[i]);
1308 for (; i < size; ++i)
1309 printf("%s", fault_chars[fault_type]);
1311 putchar(' ');
1312 inc = size;
1313 nslash = 0;
1314 for(;;){
1315 if( scanhex(&n) ){
1316 for (i = 0; i < size; ++i)
1317 val[i] = n >> (i * 8);
1318 if (!brev)
1319 byterev(val, size);
1320 mwrite(adrs, val, size);
1321 inc = size;
1323 cmd = skipbl();
1324 if (cmd == '\n')
1325 break;
1326 inc = 0;
1327 switch (cmd) {
1328 case '\'':
1329 for(;;){
1330 n = inchar();
1331 if( n == '\\' )
1332 n = bsesc();
1333 else if( n == '\'' )
1334 break;
1335 for (i = 0; i < size; ++i)
1336 val[i] = n >> (i * 8);
1337 if (!brev)
1338 byterev(val, size);
1339 mwrite(adrs, val, size);
1340 adrs += size;
1342 adrs -= size;
1343 inc = size;
1344 break;
1345 case ',':
1346 adrs += size;
1347 break;
1348 case '.':
1349 mnoread = 0;
1350 break;
1351 case ';':
1352 break;
1353 case 'x':
1354 case EOF:
1355 scannl();
1356 return;
1357 case 'b':
1358 case 'v':
1359 size = 1;
1360 break;
1361 case 'w':
1362 size = 2;
1363 break;
1364 case 'l':
1365 size = 4;
1366 break;
1367 case '^':
1368 adrs -= size;
1369 break;
1370 break;
1371 case '/':
1372 if (nslash > 0)
1373 adrs -= 1 << nslash;
1374 else
1375 nslash = 0;
1376 nslash += 4;
1377 adrs += 1 << nslash;
1378 break;
1379 case '\\':
1380 if (nslash < 0)
1381 adrs += 1 << -nslash;
1382 else
1383 nslash = 0;
1384 nslash -= 4;
1385 adrs -= 1 << -nslash;
1386 break;
1387 case 'm':
1388 scanhex(&adrs);
1389 break;
1390 case 'n':
1391 mnoread = 1;
1392 break;
1393 case 'r':
1394 brev = !brev;
1395 break;
1396 case '<':
1397 n = size;
1398 scanhex(&n);
1399 adrs -= n;
1400 break;
1401 case '>':
1402 n = size;
1403 scanhex(&n);
1404 adrs += n;
1405 break;
1408 adrs += inc;
1413 bsesc(void)
1415 int c;
1417 c = inchar();
1418 switch( c ){
1419 case 'n': c = '\n'; break;
1420 case 'r': c = '\r'; break;
1421 case 'b': c = '\b'; break;
1422 case 't': c = '\t'; break;
1424 return c;
1427 void
1428 dump(void)
1430 int c;
1432 c = inchar();
1433 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1434 termch = c;
1435 scanhex(&adrs);
1436 if( termch != '\n')
1437 termch = 0;
1438 if( c == 'i' ){
1439 scanhex(&nidump);
1440 if( nidump == 0 )
1441 nidump = 16;
1442 adrs += ppc_inst_dump(adrs, nidump);
1443 last_cmd = "di\n";
1444 } else {
1445 scanhex(&ndump);
1446 if( ndump == 0 )
1447 ndump = 64;
1448 prdump(adrs, ndump);
1449 adrs += ndump;
1450 last_cmd = "d\n";
1454 void
1455 prdump(unsigned adrs, int ndump)
1457 register int n, m, c, r, nr;
1458 unsigned char temp[16];
1460 for( n = ndump; n > 0; ){
1461 printf("%.8x", adrs);
1462 putchar(' ');
1463 r = n < 16? n: 16;
1464 nr = mread(adrs, temp, r);
1465 adrs += nr;
1466 for( m = 0; m < r; ++m ){
1467 putchar((m & 3) == 0 && m > 0? '.': ' ');
1468 if( m < nr )
1469 printf("%.2x", temp[m]);
1470 else
1471 printf("%s", fault_chars[fault_type]);
1473 for(; m < 16; ++m )
1474 printf(" ");
1475 printf(" |");
1476 for( m = 0; m < r; ++m ){
1477 if( m < nr ){
1478 c = temp[m];
1479 putchar(' ' <= c && c <= '~'? c: '.');
1480 } else
1481 putchar(' ');
1483 n -= r;
1484 for(; m < 16; ++m )
1485 putchar(' ');
1486 printf("|\n");
1487 if( nr < r )
1488 break;
1493 ppc_inst_dump(unsigned adr, int count)
1495 int nr, dotted;
1496 unsigned first_adr;
1497 unsigned long inst, last_inst = 0;
1498 unsigned char val[4];
1500 dotted = 0;
1501 for (first_adr = adr; count > 0; --count, adr += 4){
1502 nr = mread(adr, val, 4);
1503 if( nr == 0 ){
1504 const char *x = fault_chars[fault_type];
1505 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1506 break;
1508 inst = GETWORD(val);
1509 if (adr > first_adr && inst == last_inst) {
1510 if (!dotted) {
1511 printf(" ...\n");
1512 dotted = 1;
1514 continue;
1516 dotted = 0;
1517 last_inst = inst;
1518 printf("%.8x ", adr);
1519 printf("%.8x\t", inst);
1520 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1521 printf("\n");
1523 return adr - first_adr;
1526 void
1527 print_address(unsigned addr)
1529 printf("0x%x", addr);
1533 * Memory operations - move, set, print differences
1535 static unsigned mdest; /* destination address */
1536 static unsigned msrc; /* source address */
1537 static unsigned mval; /* byte value to set memory to */
1538 static unsigned mcount; /* # bytes to affect */
1539 static unsigned mdiffs; /* max # differences to print */
1541 void
1542 memops(int cmd)
1544 scanhex(&mdest);
1545 if( termch != '\n' )
1546 termch = 0;
1547 scanhex(cmd == 's'? &mval: &msrc);
1548 if( termch != '\n' )
1549 termch = 0;
1550 scanhex(&mcount);
1551 switch( cmd ){
1552 case 'm':
1553 memmove((void *)mdest, (void *)msrc, mcount);
1554 break;
1555 case 's':
1556 memset((void *)mdest, mval, mcount);
1557 break;
1558 case 'd':
1559 if( termch != '\n' )
1560 termch = 0;
1561 scanhex(&mdiffs);
1562 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1563 break;
1567 void
1568 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1570 unsigned n, prt;
1572 prt = 0;
1573 for( n = nb; n > 0; --n )
1574 if( *p1++ != *p2++ )
1575 if( ++prt <= maxpr )
1576 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1577 p1[-1], (unsigned)p2 - 1, p2[-1]);
1578 if( prt > maxpr )
1579 printf("Total of %d differences\n", prt);
1582 static unsigned mend;
1583 static unsigned mask;
1585 void
1586 memlocate(void)
1588 unsigned a, n;
1589 unsigned char val[4];
1591 last_cmd = "ml";
1592 scanhex(&mdest);
1593 if (termch != '\n') {
1594 termch = 0;
1595 scanhex(&mend);
1596 if (termch != '\n') {
1597 termch = 0;
1598 scanhex(&mval);
1599 mask = ~0;
1600 if (termch != '\n') termch = 0;
1601 scanhex(&mask);
1604 n = 0;
1605 for (a = mdest; a < mend; a += 4) {
1606 if (mread(a, val, 4) == 4
1607 && ((GETWORD(val) ^ mval) & mask) == 0) {
1608 printf("%.8x: %.8x\n", a, GETWORD(val));
1609 if (++n >= 10)
1610 break;
1615 static unsigned mskip = 0x1000;
1616 static unsigned mlim = 0xffffffff;
1618 void
1619 memzcan(void)
1621 unsigned char v;
1622 unsigned a;
1623 int ok, ook;
1625 scanhex(&mdest);
1626 if (termch != '\n') termch = 0;
1627 scanhex(&mskip);
1628 if (termch != '\n') termch = 0;
1629 scanhex(&mlim);
1630 ook = 0;
1631 for (a = mdest; a < mlim; a += mskip) {
1632 ok = mread(a, &v, 1);
1633 if (ok && !ook) {
1634 printf("%.8x .. ", a);
1635 fflush(stdout);
1636 } else if (!ok && ook)
1637 printf("%.8x\n", a - mskip);
1638 ook = ok;
1639 if (a + mskip < a)
1640 break;
1642 if (ook)
1643 printf("%.8x\n", a - mskip);
1646 void proccall(void)
1648 unsigned int args[8];
1649 unsigned int ret;
1650 int i;
1651 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1652 unsigned int, unsigned int, unsigned int,
1653 unsigned int, unsigned int, unsigned int);
1654 callfunc_t func;
1656 scanhex(&adrs);
1657 if (termch != '\n')
1658 termch = 0;
1659 for (i = 0; i < 8; ++i)
1660 args[i] = 0;
1661 for (i = 0; i < 8; ++i) {
1662 if (!scanhex(&args[i]) || termch == '\n')
1663 break;
1664 termch = 0;
1666 func = (callfunc_t) adrs;
1667 ret = 0;
1668 if (setjmp(bus_error_jmp) == 0) {
1669 debugger_fault_handler = handle_fault;
1670 sync();
1671 ret = func(args[0], args[1], args[2], args[3],
1672 args[4], args[5], args[6], args[7]);
1673 sync();
1674 printf("return value is %x\n", ret);
1675 } else {
1676 printf("*** %x exception occurred\n", fault_except);
1678 debugger_fault_handler = NULL;
1681 /* Input scanning routines */
1683 skipbl(void)
1685 int c;
1687 if( termch != 0 ){
1688 c = termch;
1689 termch = 0;
1690 } else
1691 c = inchar();
1692 while( c == ' ' || c == '\t' )
1693 c = inchar();
1694 return c;
1697 #define N_PTREGS 44
1698 static char *regnames[N_PTREGS] = {
1699 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1700 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1701 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1702 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1703 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1704 "trap", "dar", "dsisr", "res"
1708 scanhex(unsigned *vp)
1710 int c, d;
1711 unsigned v;
1713 c = skipbl();
1714 if (c == '%') {
1715 /* parse register name */
1716 char regname[8];
1717 int i;
1719 for (i = 0; i < sizeof(regname) - 1; ++i) {
1720 c = inchar();
1721 if (!isalnum(c)) {
1722 termch = c;
1723 break;
1725 regname[i] = c;
1727 regname[i] = 0;
1728 for (i = 0; i < N_PTREGS; ++i) {
1729 if (strcmp(regnames[i], regname) == 0) {
1730 unsigned *rp = (unsigned *)
1731 xmon_regs[smp_processor_id()];
1732 if (rp == NULL) {
1733 printf("regs not available\n");
1734 return 0;
1736 *vp = rp[i];
1737 return 1;
1740 printf("invalid register name '%%%s'\n", regname);
1741 return 0;
1742 } else if (c == '$') {
1743 static char symname[128];
1744 int i;
1745 for (i=0; i<63; i++) {
1746 c = inchar();
1747 if (isspace(c)) {
1748 termch = c;
1749 break;
1751 symname[i] = c;
1753 symname[i++] = 0;
1754 *vp = 0;
1755 if (setjmp(bus_error_jmp) == 0) {
1756 debugger_fault_handler = handle_fault;
1757 sync();
1758 *vp = kallsyms_lookup_name(symname);
1759 sync();
1761 debugger_fault_handler = NULL;
1762 if (!(*vp)) {
1763 printf("unknown symbol\n");
1764 return 0;
1766 return 1;
1769 d = hexdigit(c);
1770 if( d == EOF ){
1771 termch = c;
1772 return 0;
1774 v = 0;
1775 do {
1776 v = (v << 4) + d;
1777 c = inchar();
1778 d = hexdigit(c);
1779 } while( d != EOF );
1780 termch = c;
1781 *vp = v;
1782 return 1;
1785 void
1786 scannl(void)
1788 int c;
1790 c = termch;
1791 termch = 0;
1792 while( c != '\n' )
1793 c = inchar();
1796 int hexdigit(int c)
1798 if( '0' <= c && c <= '9' )
1799 return c - '0';
1800 if( 'A' <= c && c <= 'F' )
1801 return c - ('A' - 10);
1802 if( 'a' <= c && c <= 'f' )
1803 return c - ('a' - 10);
1804 return EOF;
1807 void
1808 getstring(char *s, int size)
1810 int c;
1812 c = skipbl();
1813 do {
1814 if( size > 1 ){
1815 *s++ = c;
1816 --size;
1818 c = inchar();
1819 } while( c != ' ' && c != '\t' && c != '\n' );
1820 termch = c;
1821 *s = 0;
1824 static char line[256];
1825 static char *lineptr;
1827 void
1828 flush_input(void)
1830 lineptr = NULL;
1834 inchar(void)
1836 if (lineptr == NULL || *lineptr == 0) {
1837 if (fgets(line, sizeof(line), stdin) == NULL) {
1838 lineptr = NULL;
1839 return EOF;
1841 lineptr = line;
1843 return *lineptr++;
1846 void
1847 take_input(char *str)
1849 lineptr = str;
1852 static void
1853 symbol_lookup(void)
1855 int type = inchar();
1856 unsigned addr;
1857 static char tmp[128];
1859 switch (type) {
1860 case 'a':
1861 if (scanhex(&addr))
1862 xmon_print_symbol(addr, ": ", "\n");
1863 termch = 0;
1864 break;
1865 case 's':
1866 getstring(tmp, 64);
1867 if (setjmp(bus_error_jmp) == 0) {
1868 debugger_fault_handler = handle_fault;
1869 sync();
1870 addr = kallsyms_lookup_name(tmp);
1871 if (addr)
1872 printf("%s: %lx\n", tmp, addr);
1873 else
1874 printf("Symbol '%s' not found.\n", tmp);
1875 sync();
1877 debugger_fault_handler = NULL;
1878 termch = 0;
1879 break;