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