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