1
2
3
4
5
6
7
8
9
10
11#include <linux/config.h>
12#include <linux/errno.h>
13#include <linux/sched.h>
14#include <linux/smp.h>
15#include <linux/mm.h>
16#include <linux/reboot.h>
17#include <linux/delay.h>
18#include <asm/ptrace.h>
19#include <asm/string.h>
20#include <asm/prom.h>
21#include <asm/machdep.h>
22#include <asm/processor.h>
23#include <asm/pgtable.h>
24#include <asm/mmu.h>
25#include <asm/mmu_context.h>
26#include <asm/naca.h>
27#include <asm/paca.h>
28#include <asm/ppcdebug.h>
29#include <asm/cputable.h>
30#include "nonstdio.h"
31#include "privinst.h"
32
33#define scanhex xmon_scanhex
34#define skipbl xmon_skipbl
35
36#ifdef CONFIG_SMP
37static volatile unsigned long cpus_in_xmon = 0;
38static volatile unsigned long got_xmon = 0;
39static volatile int take_xmon = -1;
40static volatile int leaving_xmon = 0;
41
42#endif
43
44static unsigned long adrs;
45static int size = 1;
46static unsigned long ndump = 64;
47static unsigned long nidump = 16;
48static unsigned long ncsum = 4096;
49static int termch;
50
51static u_int bus_error_jmp[100];
52#define setjmp xmon_setjmp
53#define longjmp xmon_longjmp
54
55
56#define MAXFRAMECOUNT 50
57
58
59struct bpt {
60 unsigned long address;
61 unsigned instr;
62 unsigned long count;
63 unsigned char enabled;
64 char funcname[64];
65};
66
67#define NBPTS 16
68static struct bpt bpts[NBPTS];
69static struct bpt dabr;
70static struct bpt iabr;
71static unsigned bpinstr = 0x7fe00008;
72
73
74extern void (*debugger_fault_handler)(struct pt_regs *);
75static int cmds(struct pt_regs *);
76static int mread(unsigned long, void *, int);
77static int mwrite(unsigned long, void *, int);
78static void handle_fault(struct pt_regs *);
79static void byterev(unsigned char *, int);
80static void memex(void);
81static int bsesc(void);
82static void dump(void);
83static void prdump(unsigned long, long);
84#ifdef __MWERKS__
85static void prndump(unsigned, int);
86static int nvreadb(unsigned);
87#endif
88static int ppc_inst_dump(unsigned long, long);
89void print_address(unsigned long);
90static int getsp(void);
91static void dump_hash_table(void);
92static void backtrace(struct pt_regs *);
93static void excprint(struct pt_regs *);
94static void prregs(struct pt_regs *);
95static void memops(int);
96static void memlocate(void);
97static void memzcan(void);
98static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
99int skipbl(void);
100int scanhex(unsigned long *valp);
101static void scannl(void);
102static int hexdigit(int);
103void getstring(char *, int);
104static void flush_input(void);
105static int inchar(void);
106static void take_input(char *);
107
108static unsigned long read_spr(int);
109static void write_spr(int, unsigned long);
110static void super_regs(void);
111static void print_sysmap(void);
112static void remove_bpts(void);
113static void insert_bpts(void);
114static struct bpt *at_breakpoint(unsigned long pc);
115static void bpt_cmds(void);
116static void cacheflush(void);
117#ifdef CONFIG_SMP
118static void cpu_cmd(void);
119#endif
120static void csum(void);
121static void bootcmds(void);
122static void mem_translate(void);
123static void mem_check(void);
124static void mem_find_real(void);
125static void mem_find_vsid(void);
126
127static void debug_trace(void);
128
129extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long);
130extern void printf(const char *fmt, ...);
131extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
132extern int xmon_putc(int c, void *f);
133extern int putchar(int ch);
134extern int xmon_read_poll(void);
135extern int setjmp(u_int *);
136extern void longjmp(u_int *, int);
137extern unsigned long _ASR;
138
139pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va);
140
141#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
142
143#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
144 || ('a' <= (c) && (c) <= 'f') \
145 || ('A' <= (c) && (c) <= 'F'))
146#define isalnum(c) (('0' <= (c) && (c) <= '9') \
147 || ('a' <= (c) && (c) <= 'z') \
148 || ('A' <= (c) && (c) <= 'Z'))
149#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
150
151static char *help_string = "\
152Commands:\n\
153 b show breakpoints\n\
154 bd set data breakpoint\n\
155 bi set instruction breakpoint\n\
156 bc clear breakpoint\n\
157 d dump bytes\n\
158 di dump instructions\n\
159 df dump float values\n\
160 dd dump double values\n\
161 e print exception information\n\
162 f flush cache\n\
163 h dump hash table\n\
164 m examine/change memory\n\
165 mm move a block of memory\n\
166 ms set a block of memory\n\
167 md compare two blocks of memory\n\
168 ml locate a block of memory\n\
169 mz zero a block of memory\n\
170 mx translation information for an effective address\n\
171 mi show information about memory allocation\n\
172 M print System.map\n\
173 p show the task list\n\
174 r print registers\n\
175 s single step\n\
176 S print special registers\n\
177 t print backtrace\n\
178 T Enable/Disable PPCDBG flags\n\
179 x exit monitor\n\
180";
181
182static int xmon_trace[NR_CPUS];
183#define SSTEP 1
184#define BRSTEP 2
185
186static struct pt_regs *xmon_regs[NR_CPUS];
187
188
189
190
191extern inline void sync(void)
192{
193 asm volatile("sync; isync");
194}
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222struct tbtable {
223 unsigned long flags;
224#define TBTAB_FLAGSGLOBALLINK (1L<<47)
225#define TBTAB_FLAGSISEPROL (1L<<46)
226#define TBTAB_FLAGSHASTBOFF (1L<<45)
227#define TBTAB_FLAGSINTPROC (1L<<44)
228#define TBTAB_FLAGSHASCTL (1L<<43)
229#define TBTAB_FLAGSTOCLESS (1L<<42)
230#define TBTAB_FLAGSFPPRESENT (1L<<41)
231#define TBTAB_FLAGSNAMEPRESENT (1L<<38)
232#define TBTAB_FLAGSUSESALLOCA (1L<<37)
233#define TBTAB_FLAGSSAVESCR (1L<<33)
234#define TBTAB_FLAGSSAVESLR (1L<<32)
235#define TBTAB_FLAGSSTORESBC (1L<<31)
236#define TBTAB_FLAGSFIXUP (1L<<30)
237#define TBTAB_FLAGSPARMSONSTK (1L<<0)
238 unsigned char fp_saved;
239 unsigned char gpr_saved;
240 unsigned char fixedparms;
241 unsigned char floatparms;
242 unsigned char parminfo[32];
243#define TBTAB_PARMFIXED 1
244#define TBTAB_PARMSFLOAT 2
245#define TBTAB_PARMDFLOAT 3
246 unsigned int tb_offset;
247 unsigned long funcstart;
248 char name[64];
249};
250static int find_tb_table(unsigned long codeaddr, struct tbtable *tab);
251
252void
253xmon(struct pt_regs *excp)
254{
255 struct pt_regs regs;
256 int cmd = 0;
257 unsigned long msr;
258
259 if (excp == NULL) {
260
261
262
263
264
265
266
267 asm volatile ("std 0,0(%0)\n\
268 std 1,8(%0)\n\
269 std 2,16(%0)\n\
270 std 3,24(%0)\n\
271 std 4,32(%0)\n\
272 std 5,40(%0)\n\
273 std 6,48(%0)\n\
274 std 7,56(%0)\n\
275 std 8,64(%0)\n\
276 std 9,72(%0)\n\
277 std 10,80(%0)\n\
278 std 11,88(%0)\n\
279 std 12,96(%0)\n\
280 std 13,104(%0)\n\
281 std 14,112(%0)\n\
282 std 15,120(%0)\n\
283 std 16,128(%0)\n\
284 std 17,136(%0)\n\
285 std 18,144(%0)\n\
286 std 19,152(%0)\n\
287 std 20,160(%0)\n\
288 std 21,168(%0)\n\
289 std 22,176(%0)\n\
290 std 23,184(%0)\n\
291 std 24,192(%0)\n\
292 std 25,200(%0)\n\
293 std 26,208(%0)\n\
294 std 27,216(%0)\n\
295 std 28,224(%0)\n\
296 std 29,232(%0)\n\
297 std 30,240(%0)\n\
298 std 31,248(%0)" : : "b" (®s));
299
300
301 regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
302 regs.msr = get_msr();
303 regs.ctr = get_ctr();
304 regs.xer = get_xer();
305 regs.ccr = get_cr();
306 regs.trap = 0;
307 excp = ®s;
308 }
309
310 msr = get_msr();
311 set_msrd(msr & ~MSR_EE);
312 xmon_regs[smp_processor_id()] = excp;
313 excprint(excp);
314#ifdef CONFIG_SMP
315
316
317 leaving_xmon = 0;
318 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) {
319
320 printf("We are already in xmon\n");
321 for (;;)
322 ;
323 }
324 while (test_and_set_bit(0, &got_xmon)) {
325 if (take_xmon == smp_processor_id()) {
326 take_xmon = -1;
327 break;
328 }
329 }
330
331
332
333#endif
334 remove_bpts();
335 cmd = cmds(excp);
336 if (cmd == 's') {
337 xmon_trace[smp_processor_id()] = SSTEP;
338 excp->msr |= MSR_SE;
339#ifdef CONFIG_SMP
340 take_xmon = smp_processor_id();
341#endif
342 } else if (at_breakpoint(excp->nip)) {
343 xmon_trace[smp_processor_id()] = BRSTEP;
344 excp->msr |= MSR_SE;
345 } else {
346 xmon_trace[smp_processor_id()] = 0;
347 insert_bpts();
348 }
349 xmon_regs[smp_processor_id()] = 0;
350#ifdef CONFIG_SMP
351 leaving_xmon = 1;
352 if (cmd != 's')
353 clear_bit(0, &got_xmon);
354 clear_bit(smp_processor_id(), &cpus_in_xmon);
355#endif
356 set_msrd(msr);
357}
358
359void
360xmon_irq(int irq, void *d, struct pt_regs *regs)
361{
362 unsigned long flags;
363 __save_flags(flags);
364 __cli();
365 printf("Keyboard interrupt\n");
366 xmon(regs);
367 __restore_flags(flags);
368}
369
370int
371xmon_bpt(struct pt_regs *regs)
372{
373 struct bpt *bp;
374
375 bp = at_breakpoint(regs->nip);
376 if (!bp)
377 return 0;
378 if (bp->count) {
379 --bp->count;
380 remove_bpts();
381 excprint(regs);
382 xmon_trace[smp_processor_id()] = BRSTEP;
383 regs->msr |= MSR_SE;
384 } else {
385 printf("Stopped at breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname);
386 xmon(regs);
387 }
388 return 1;
389}
390
391int
392xmon_sstep(struct pt_regs *regs)
393{
394 if (!xmon_trace[smp_processor_id()])
395 return 0;
396 if (xmon_trace[smp_processor_id()] == BRSTEP) {
397 xmon_trace[smp_processor_id()] = 0;
398 insert_bpts();
399 } else {
400 xmon(regs);
401 }
402 return 1;
403}
404
405int
406xmon_dabr_match(struct pt_regs *regs)
407{
408 if (dabr.enabled && dabr.count) {
409 --dabr.count;
410 remove_bpts();
411 excprint(regs);
412 xmon_trace[smp_processor_id()] = BRSTEP;
413 regs->msr |= MSR_SE;
414 } else {
415 dabr.instr = regs->nip;
416 xmon(regs);
417 }
418 return 1;
419}
420
421int
422xmon_iabr_match(struct pt_regs *regs)
423{
424 if (iabr.enabled && iabr.count) {
425 --iabr.count;
426 remove_bpts();
427 excprint(regs);
428 xmon_trace[smp_processor_id()] = BRSTEP;
429 regs->msr |= MSR_SE;
430 } else {
431 xmon(regs);
432 }
433 return 1;
434}
435
436static struct bpt *
437at_breakpoint(unsigned long pc)
438{
439 int i;
440 struct bpt *bp;
441
442 if (dabr.enabled && pc == dabr.instr)
443 return &dabr;
444 if (iabr.enabled && pc == iabr.address)
445 return &iabr;
446 bp = bpts;
447 for (i = 0; i < NBPTS; ++i, ++bp)
448 if (bp->enabled && pc == bp->address)
449 return bp;
450 return 0;
451}
452
453static void
454insert_bpts()
455{
456 int i;
457 struct bpt *bp;
458
459 if (!(systemcfg->platform & PLATFORM_PSERIES))
460 return;
461 bp = bpts;
462 for (i = 0; i < NBPTS; ++i, ++bp) {
463 if (!bp->enabled)
464 continue;
465 if (mread(bp->address, &bp->instr, 4) != 4
466 || mwrite(bp->address, &bpinstr, 4) != 4) {
467 printf("Couldn't insert breakpoint at %x, disabling\n",
468 bp->address);
469 bp->enabled = 0;
470 } else {
471 store_inst((void *)bp->address);
472 }
473 }
474
475 if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) {
476 if (dabr.enabled)
477 set_dabr(dabr.address);
478 if (iabr.enabled)
479 set_iabr(iabr.address);
480 }
481}
482
483static void
484remove_bpts()
485{
486 int i;
487 struct bpt *bp;
488 unsigned instr;
489
490 if (!(systemcfg->platform & PLATFORM_PSERIES))
491 return;
492 if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) {
493 if (dabr.enabled)
494 set_dabr(0);
495 if (iabr.enabled)
496 set_iabr(0);
497 }
498
499 bp = bpts;
500 for (i = 0; i < NBPTS; ++i, ++bp) {
501 if (!bp->enabled)
502 continue;
503 if (mread(bp->address, &instr, 4) == 4
504 && instr == bpinstr
505 && mwrite(bp->address, &bp->instr, 4) != 4)
506 printf("Couldn't remove breakpoint at %x\n",
507 bp->address);
508 else
509 store_inst((void *)bp->address);
510 }
511}
512
513static char *last_cmd;
514
515
516static int
517cmds(struct pt_regs *excp)
518{
519 int cmd = 0;
520
521 last_cmd = NULL;
522 for(;;) {
523#ifdef CONFIG_SMP
524
525
526 if (leaving_xmon)
527 return cmd;
528 printf("%d:", smp_processor_id());
529#endif
530 printf("mon> ");
531 fflush(stdout);
532 flush_input();
533 termch = 0;
534 cmd = skipbl();
535 if( cmd == '\n' ) {
536 if (last_cmd == NULL)
537 continue;
538 take_input(last_cmd);
539 last_cmd = NULL;
540 cmd = inchar();
541 }
542 switch (cmd) {
543 case 'm':
544 cmd = inchar();
545 switch (cmd) {
546 case 'm':
547 case 's':
548 case 'd':
549 memops(cmd);
550 break;
551 case 'l':
552 memlocate();
553 break;
554 case 'z':
555 memzcan();
556 break;
557 case 'x':
558 mem_translate();
559 break;
560 case 'c':
561 mem_check();
562 break;
563 case 'f':
564 mem_find_real();
565 break;
566 case 'e':
567 mem_find_vsid();
568 break;
569 case 'i':
570 show_mem();
571 break;
572 default:
573 termch = cmd;
574 memex();
575 }
576 break;
577 case 'd':
578 dump();
579 break;
580 case 'r':
581 if (excp != NULL)
582 prregs(excp);
583 break;
584 case 'e':
585 if (excp == NULL)
586 printf("No exception information\n");
587 else
588 excprint(excp);
589 break;
590 case 'M':
591 print_sysmap();
592 break;
593 case 'S':
594 super_regs();
595 break;
596 case 't':
597 backtrace(excp);
598 break;
599 case 'f':
600 cacheflush();
601 break;
602 case 'h':
603 dump_hash_table();
604 break;
605 case 's':
606 case 'x':
607 case EOF:
608 return cmd;
609 case '?':
610 printf(help_string);
611 break;
612 case 'p':
613 show_state();
614 break;
615 case 'b':
616 bpt_cmds();
617 break;
618 case 'C':
619 csum();
620 break;
621#ifdef CONFIG_SMP
622 case 'c':
623 cpu_cmd();
624 break;
625#endif
626 case 'z':
627 bootcmds();
628 case 'T':
629 debug_trace();
630 break;
631 default:
632 printf("Unrecognized command: ");
633 do {
634 if( ' ' < cmd && cmd <= '~' )
635 putchar(cmd);
636 else
637 printf("\\x%x", cmd);
638 cmd = inchar();
639 } while (cmd != '\n');
640 printf(" (type ? for help)\n");
641 break;
642 }
643 }
644}
645
646static void bootcmds(void)
647{
648 int cmd;
649
650 cmd = inchar();
651 if (cmd == 'r')
652 ppc_md.restart(NULL);
653 else if (cmd == 'h')
654 ppc_md.halt();
655 else if (cmd == 'p')
656 ppc_md.power_off();
657}
658
659#ifdef CONFIG_SMP
660static void cpu_cmd(void)
661{
662 unsigned long cpu;
663 int timeout;
664 int cmd;
665
666 cmd = inchar();
667 if (cmd == 'i') {
668 printf("stopping all cpus\n");
669
670 cpu = MSG_ALL_BUT_SELF;
671 smp_send_xmon_break(cpu);
672 return;
673 }
674 termch = cmd;
675 if (!scanhex(&cpu)) {
676
677 printf("cpus stopped:");
678 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
679 if (test_bit(cpu, &cpus_in_xmon)) {
680 printf(" %x", cpu);
681 if (cpu == smp_processor_id())
682 printf("*", cpu);
683 }
684 }
685 printf("\n");
686 return;
687 }
688
689 take_xmon = cpu;
690 timeout = 10000000;
691 while (take_xmon >= 0) {
692 if (--timeout == 0) {
693
694 take_xmon = -1;
695 printf("cpu %u didn't take control\n", cpu);
696 return;
697 }
698 }
699
700 while (test_and_set_bit(0, &got_xmon)) {
701 if (take_xmon == smp_processor_id()) {
702 take_xmon = -1;
703 break;
704 }
705 }
706}
707#endif
708
709static unsigned short fcstab[256] = {
710 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
711 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
712 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
713 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
714 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
715 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
716 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
717 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
718 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
719 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
720 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
721 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
722 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
723 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
724 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
725 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
726 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
727 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
728 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
729 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
730 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
731 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
732 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
733 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
734 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
735 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
736 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
737 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
738 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
739 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
740 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
741 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
742};
743
744#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
745
746static void
747csum(void)
748{
749 unsigned int i;
750 unsigned short fcs;
751 unsigned char v;
752
753 if (!scanhex(&adrs))
754 return;
755 if (!scanhex(&ncsum))
756 return;
757 fcs = 0xffff;
758 for (i = 0; i < ncsum; ++i) {
759 if (mread(adrs+i, &v, 1) == 0) {
760 printf("csum stopped at %x\n", adrs+i);
761 break;
762 }
763 fcs = FCS(fcs, v);
764 }
765 printf("%x\n", fcs);
766}
767
768static char *breakpoint_help_string =
769 "Breakpoint command usage:\n"
770 "b show breakpoints\n"
771 "b <addr> [cnt] set breakpoint at given instr addr\n"
772 "bc clear all breakpoints\n"
773 "bc <n/addr> clear breakpoint number n or at addr\n"
774 "bi <addr> [cnt] set hardware instr breakpoint (broken?)\n"
775 "bd <addr> [cnt] set hardware data breakpoint (broken?)\n"
776 "";
777
778static void
779bpt_cmds(void)
780{
781 int cmd;
782 unsigned long a;
783 int mode, i;
784 struct bpt *bp;
785 struct tbtable tab;
786
787 cmd = inchar();
788 switch (cmd) {
789 case 'd':
790 if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
791 printf("Not implemented on POWER4\n");
792 break;
793 }
794
795 mode = 7;
796 cmd = inchar();
797 if (cmd == 'r')
798 mode = 5;
799 else if (cmd == 'w')
800 mode = 6;
801 else
802 termch = cmd;
803 dabr.address = 0;
804 dabr.count = 0;
805 dabr.enabled = scanhex(&dabr.address);
806 scanhex(&dabr.count);
807 if (dabr.enabled)
808 dabr.address = (dabr.address & ~7) | mode;
809 break;
810 case 'i':
811 if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
812 printf("Not implemented on POWER4\n");
813 break;
814 }
815 iabr.address = 0;
816 iabr.count = 0;
817 iabr.enabled = scanhex(&iabr.address);
818 if (iabr.enabled)
819 iabr.address |= 3;
820 scanhex(&iabr.count);
821 break;
822 case 'c':
823 if (!scanhex(&a)) {
824
825 for (i = 0; i < NBPTS; ++i)
826 bpts[i].enabled = 0;
827 iabr.enabled = 0;
828 dabr.enabled = 0;
829 printf("All breakpoints cleared\n");
830 } else {
831 if (a <= NBPTS && a >= 1) {
832
833 --a;
834 bp = &bpts[a];
835 } else {
836
837 bp = at_breakpoint(a);
838 }
839 if (bp == 0) {
840 printf("No breakpoint at %x\n", a);
841 } else {
842 printf("Cleared breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname);
843 bp->enabled = 0;
844 }
845 }
846 break;
847 case '?':
848 printf(breakpoint_help_string);
849 break;
850 default:
851 termch = cmd;
852 cmd = skipbl();
853 if (cmd == '?') {
854 printf(breakpoint_help_string);
855 break;
856 }
857 termch = cmd;
858 if (!scanhex(&a)) {
859
860 int bpnum;
861
862 printf(" type address count\n");
863 if (dabr.enabled) {
864 printf(" data %.16lx %8x [", dabr.address & ~7,
865 dabr.count);
866 if (dabr.address & 1)
867 printf("r");
868 if (dabr.address & 2)
869 printf("w");
870 printf("]\n");
871 }
872 if (iabr.enabled)
873 printf(" inst %.16lx %8x\n", iabr.address & ~3,
874 iabr.count);
875 for (bp = bpts, bpnum = 1; bp < &bpts[NBPTS]; ++bp, ++bpnum)
876 if (bp->enabled)
877 printf("%2x trap %.16lx %8x %s\n", bpnum, bp->address, bp->count, bp->funcname);
878 break;
879 }
880 bp = at_breakpoint(a);
881 if (bp == 0) {
882 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
883 if (!bp->enabled)
884 break;
885 if (bp >= &bpts[NBPTS]) {
886 printf("Sorry, no free breakpoints. Please clear one first.\n");
887 break;
888 }
889 }
890 bp->enabled = 1;
891 bp->address = a;
892 bp->count = 0;
893 scanhex(&bp->count);
894
895 bp->funcname[0] = '\0';
896 if (find_tb_table(bp->address, &tab) && tab.name[0]) {
897
898 int delta = bp->address - tab.funcstart;
899 sprintf(bp->funcname, "%s+0x%x", tab.name, delta);
900 }
901 printf("Set breakpoint %2x trap %.16lx %8x %s\n", (bp-bpts)+1, bp->address, bp->count, bp->funcname);
902 break;
903 }
904}
905
906
907static
908const char *getvecname(unsigned long vec)
909{
910 char *ret;
911 switch (vec) {
912 case 0x100: ret = "(System Reset)"; break;
913 case 0x200: ret = "(Machine Check)"; break;
914 case 0x300: ret = "(Data Access)"; break;
915 case 0x380: ret = "(Data SLB Access)"; break;
916 case 0x400: ret = "(Instruction Access)"; break;
917 case 0x480: ret = "(Instruction SLB Access)"; break;
918 case 0x500: ret = "(Hardware Interrupt)"; break;
919 case 0x600: ret = "(Alignment)"; break;
920 case 0x700: ret = "(Program Check)"; break;
921 case 0x800: ret = "(FPU Unavailable)"; break;
922 case 0x900: ret = "(Decrementer)"; break;
923 case 0xc00: ret = "(System Call)"; break;
924 case 0xd00: ret = "(Single Step)"; break;
925 case 0xf00: ret = "(Performance Monitor)"; break;
926 default: ret = "";
927 }
928 return ret;
929}
930
931static void
932backtrace(struct pt_regs *excp)
933{
934 unsigned long sp;
935 unsigned long lr;
936 unsigned long stack[3];
937 struct pt_regs regs;
938 struct tbtable tab;
939 int framecount;
940 char *funcname;
941
942 extern void *ret_from_except, *ret_from_syscall_1;
943
944 if (excp != NULL) {
945 lr = excp->link;
946 sp = excp->gpr[1];
947 } else {
948
949
950 asm volatile ("mflr %0" : "=r" (lr) :);
951 sp = getsp();
952 }
953 scanhex(&sp);
954 scannl();
955 for (framecount = 0;
956 sp != 0 && framecount < MAXFRAMECOUNT;
957 sp = stack[0], framecount++) {
958 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
959 break;
960#if 0
961 if (lr != 0) {
962 stack[2] = lr;
963 lr = 0;
964 }
965#endif
966 printf("%.16lx %.16lx", sp, stack[2]);
967
968
969
970 if ((stack[2] == (unsigned long)ret_from_except &&
971 (funcname = "ret_from_except"))
972 || (stack[2] == (unsigned long)ret_from_syscall_1 &&
973 (funcname = "ret_from_syscall_1"))
974#if 0
975 || stack[2] == (unsigned) &ret_from_syscall_2
976 || stack[2] == (unsigned) &do_signal_ret
977#endif
978 ) {
979 printf(" %s\n", funcname);
980 if (mread(sp+112, ®s, sizeof(regs)) != sizeof(regs))
981 break;
982 printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112);
983 printf(" %.16lx", regs.nip);
984 if ((regs.nip & 0xffffffff00000000UL) &&
985 find_tb_table(regs.nip, &tab)) {
986 int delta = regs.nip-tab.funcstart;
987 if (delta < 0)
988 printf(" <unknown code>");
989 else
990 printf(" %s+0x%x", tab.name, delta);
991 }
992 printf("\n");
993 if (regs.gpr[1] < sp) {
994 printf("<Stack drops into 32-bit userspace %.16lx>\n", regs.gpr[1]);
995 break;
996 }
997
998 sp = regs.gpr[1];
999 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
1000 break;
1001 } else {
1002 if (stack[2] && find_tb_table(stack[2], &tab)) {
1003 int delta = stack[2]-tab.funcstart;
1004 if (delta < 0)
1005 printf(" <unknown code>");
1006 else
1007 printf(" %s+0x%x", tab.name, delta);
1008 }
1009 printf("\n");
1010 }
1011 if (stack[0] && stack[0] <= sp) {
1012 if ((stack[0] & 0xffffffff00000000UL) == 0)
1013 printf("<Stack drops into 32-bit userspace %.16lx>\n", stack[0]);
1014 else
1015 printf("<Corrupt stack. Next backchain is %.16lx>\n", stack[0]);
1016 break;
1017 }
1018 }
1019 if (framecount >= MAXFRAMECOUNT)
1020 printf("<Punt. Too many stack frames>\n");
1021}
1022
1023int
1024getsp()
1025{
1026 int x;
1027
1028 asm("mr %0,1" : "=r" (x) :);
1029 return x;
1030}
1031
1032spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED;
1033
1034void
1035excprint(struct pt_regs *fp)
1036{
1037 struct task_struct *c;
1038 struct tbtable tab;
1039 unsigned long flags;
1040
1041 spin_lock_irqsave(&exception_print_lock, flags);
1042
1043#ifdef CONFIG_SMP
1044 printf("cpu %d: ", smp_processor_id());
1045#endif
1046
1047 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(fp->trap), fp);
1048 printf(" pc: %lx", fp->nip);
1049 if (find_tb_table(fp->nip, &tab) && tab.name[0]) {
1050
1051 int delta = fp->nip - tab.funcstart;
1052 printf(" (%s+0x%x)", tab.name, delta);
1053 }
1054 printf("\n");
1055 printf(" lr: %lx", fp->link);
1056 if (find_tb_table(fp->link, &tab) && tab.name[0]) {
1057
1058 int delta = fp->link - tab.funcstart;
1059 printf(" (%s+0x%x)", tab.name, delta);
1060 }
1061 printf("\n");
1062 printf(" sp: %lx\n", fp->gpr[1]);
1063 printf(" msr: %lx\n", fp->msr);
1064
1065 if (fp->trap == 0x300 || fp->trap == 0x380 || fp->trap == 0x600) {
1066 printf(" dar: %lx\n", fp->dar);
1067 printf(" dsisr: %lx\n", fp->dsisr);
1068 }
1069
1070
1071 c = current;
1072 printf(" current = 0x%lx\n", c);
1073 printf(" paca = 0x%lx\n", get_paca());
1074 if (c) {
1075 printf(" current = %lx, pid = %ld, comm = %s\n",
1076 c, c->pid, c->comm);
1077 }
1078
1079 spin_unlock_irqrestore(&exception_print_lock, flags);
1080}
1081
1082void
1083prregs(struct pt_regs *fp)
1084{
1085 int n;
1086 unsigned long base;
1087
1088 if (scanhex((void *)&base))
1089 fp = (struct pt_regs *) base;
1090 for (n = 0; n < 16; ++n)
1091 printf("R%.2ld = %.16lx R%.2ld = %.16lx\n", n, fp->gpr[n],
1092 n+16, fp->gpr[n+16]);
1093 printf("pc = %.16lx msr = %.16lx\nlr = %.16lx cr = %.16lx\n",
1094 fp->nip, fp->msr, fp->link, fp->ccr);
1095 printf("ctr = %.16lx xer = %.16lx trap = %8lx\n",
1096 fp->ctr, fp->xer, fp->trap);
1097}
1098
1099void
1100cacheflush(void)
1101{
1102 int cmd;
1103 unsigned long nflush;
1104
1105 cmd = inchar();
1106 if (cmd != 'i')
1107 termch = cmd;
1108 scanhex((void *)&adrs);
1109 if (termch != '\n')
1110 termch = 0;
1111 nflush = 1;
1112 scanhex(&nflush);
1113 nflush = (nflush + 31) / 32;
1114 if (cmd != 'i') {
1115 for (; nflush > 0; --nflush, adrs += 0x20)
1116 cflush((void *) adrs);
1117 } else {
1118 for (; nflush > 0; --nflush, adrs += 0x20)
1119 cinval((void *) adrs);
1120 }
1121}
1122
1123unsigned long
1124read_spr(int n)
1125{
1126 unsigned int instrs[2];
1127 unsigned long (*code)(void);
1128 unsigned long opd[3];
1129
1130 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1131 instrs[1] = 0x4e800020;
1132 opd[0] = (unsigned long)instrs;
1133 opd[1] = 0;
1134 opd[2] = 0;
1135 store_inst(instrs);
1136 store_inst(instrs+1);
1137 code = (unsigned long (*)(void)) opd;
1138
1139 return code();
1140}
1141
1142void
1143write_spr(int n, unsigned long val)
1144{
1145 unsigned int instrs[2];
1146 unsigned long (*code)(unsigned long);
1147 unsigned long opd[3];
1148
1149 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1150 instrs[1] = 0x4e800020;
1151 opd[0] = (unsigned long)instrs;
1152 opd[1] = 0;
1153 opd[2] = 0;
1154 store_inst(instrs);
1155 store_inst(instrs+1);
1156 code = (unsigned long (*)(unsigned long)) opd;
1157
1158 code(val);
1159}
1160
1161static unsigned long regno;
1162extern char exc_prolog;
1163extern char dec_exc;
1164
1165void
1166print_sysmap(void)
1167{
1168 extern char *sysmap;
1169 if ( sysmap )
1170 printf("System.map: \n%s", sysmap);
1171}
1172
1173void
1174super_regs()
1175{
1176 int i, cmd;
1177 unsigned long val;
1178 struct paca_struct* ptrPaca = NULL;
1179 struct ItLpPaca* ptrLpPaca = NULL;
1180 struct ItLpRegSave* ptrLpRegSave = NULL;
1181
1182 cmd = skipbl();
1183 if (cmd == '\n') {
1184 unsigned long sp, toc;
1185 asm("mr %0,1" : "=r" (sp) :);
1186 asm("mr %0,2" : "=r" (toc) :);
1187
1188 printf("msr = %.16lx sprg0= %.16lx\n", get_msr(), get_sprg0());
1189 printf("pvr = %.16lx sprg1= %.16lx\n", get_pvr(), get_sprg1());
1190 printf("dec = %.16lx sprg2= %.16lx\n", get_dec(), get_sprg2());
1191 printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3());
1192 printf("toc = %.16lx dar = %.16lx\n", toc, get_dar());
1193 printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1());
1194 printf("asr = %.16lx\n", mfasr());
1195 for (i = 0; i < 8; ++i)
1196 printf("sr%.2ld = %.16lx sr%.2ld = %.16lx\n", i, get_sr(i), i+8, get_sr(i+8));
1197
1198
1199 printf("Paca: \n");
1200 ptrPaca = get_paca();
1201
1202 printf(" Local Processor Control Area (LpPaca): \n");
1203 ptrLpPaca = ptrPaca->xLpPacaPtr;
1204 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", ptrLpPaca->xSavedSrr0, ptrLpPaca->xSavedSrr1);
1205 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", ptrLpPaca->xSavedGpr3, ptrLpPaca->xSavedGpr4);
1206 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->xSavedGpr5);
1207
1208 printf(" Local Processor Register Save Area (LpRegSave): \n");
1209 ptrLpRegSave = ptrPaca->xLpRegSavePtr;
1210 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1211 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1212 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1213
1214 return;
1215 }
1216
1217 scanhex(®no);
1218 switch (cmd) {
1219 case 'w':
1220 val = read_spr(regno);
1221 scanhex(&val);
1222 write_spr(regno, val);
1223
1224 case 'r':
1225 printf("spr %lx = %lx\n", regno, read_spr(regno));
1226 break;
1227 case 's':
1228 val = get_sr(regno);
1229 scanhex(&val);
1230 set_sr(regno, val);
1231 break;
1232 case 'm':
1233 val = get_msr();
1234 scanhex(&val);
1235 set_msrd(val);
1236 break;
1237 }
1238 scannl();
1239}
1240
1241#ifndef CONFIG_PPC64BRIDGE
1242static void
1243dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1244{
1245 extern void *Hash;
1246 extern unsigned long Hash_size;
1247 unsigned *htab = Hash;
1248 unsigned hsize = Hash_size;
1249 unsigned v, hmask, va, last_va;
1250 int found, last_found, i;
1251 unsigned *hg, w1, last_w2, last_va0;
1252
1253 last_found = 0;
1254 hmask = hsize / 64 - 1;
1255 va = start;
1256 start = (start >> 12) & 0xffff;
1257 end = (end >> 12) & 0xffff;
1258 for (v = start; v < end; ++v) {
1259 found = 0;
1260 hg = htab + (((v ^ seg) & hmask) * 16);
1261 w1 = 0x80000000 | (seg << 7) | (v >> 10);
1262 for (i = 0; i < 8; ++i, hg += 2) {
1263 if (*hg == w1) {
1264 found = 1;
1265 break;
1266 }
1267 }
1268 if (!found) {
1269 w1 ^= 0x40;
1270 hg = htab + ((~(v ^ seg) & hmask) * 16);
1271 for (i = 0; i < 8; ++i, hg += 2) {
1272 if (*hg == w1) {
1273 found = 1;
1274 break;
1275 }
1276 }
1277 }
1278 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1279 if (last_found) {
1280 if (last_va != last_va0)
1281 printf(" ... %x", last_va);
1282 printf("\n");
1283 }
1284 if (found) {
1285 printf("%x to %x", va, hg[1]);
1286 last_va0 = va;
1287 }
1288 last_found = found;
1289 }
1290 if (found) {
1291 last_w2 = hg[1] & ~0x180;
1292 last_va = va;
1293 }
1294 va += 4096;
1295 }
1296 if (last_found)
1297 printf(" ... %x\n", last_va);
1298}
1299
1300#else
1301static void
1302dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1303{
1304 extern void *Hash;
1305 extern unsigned long Hash_size;
1306 unsigned *htab = Hash;
1307 unsigned hsize = Hash_size;
1308 unsigned v, hmask, va, last_va;
1309 int found, last_found, i;
1310 unsigned *hg, w1, last_w2, last_va0;
1311
1312 last_found = 0;
1313 hmask = hsize / 128 - 1;
1314 va = start;
1315 start = (start >> 12) & 0xffff;
1316 end = (end >> 12) & 0xffff;
1317 for (v = start; v < end; ++v) {
1318 found = 0;
1319 hg = htab + (((v ^ seg) & hmask) * 32);
1320 w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
1321 for (i = 0; i < 8; ++i, hg += 4) {
1322 if (hg[1] == w1) {
1323 found = 1;
1324 break;
1325 }
1326 }
1327 if (!found) {
1328 w1 ^= 2;
1329 hg = htab + ((~(v ^ seg) & hmask) * 32);
1330 for (i = 0; i < 8; ++i, hg += 4) {
1331 if (hg[1] == w1) {
1332 found = 1;
1333 break;
1334 }
1335 }
1336 }
1337 if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
1338 if (last_found) {
1339 if (last_va != last_va0)
1340 printf(" ... %x", last_va);
1341 printf("\n");
1342 }
1343 if (found) {
1344 printf("%x to %x", va, hg[3]);
1345 last_va0 = va;
1346 }
1347 last_found = found;
1348 }
1349 if (found) {
1350 last_w2 = hg[3] & ~0x180;
1351 last_va = va;
1352 }
1353 va += 4096;
1354 }
1355 if (last_found)
1356 printf(" ... %x\n", last_va);
1357}
1358#endif
1359
1360static unsigned long hash_ctx;
1361static unsigned long hash_start;
1362static unsigned long hash_end;
1363
1364static void
1365dump_hash_table()
1366{
1367 int seg;
1368 unsigned seg_start, seg_end;
1369
1370 hash_ctx = 0;
1371 hash_start = 0;
1372 hash_end = 0xfffff000;
1373 scanhex(&hash_ctx);
1374 scanhex(&hash_start);
1375 scanhex(&hash_end);
1376 printf("Mappings for context %x\n", hash_ctx);
1377 seg_start = hash_start;
1378 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1379 seg_end = (seg << 28) | 0x0ffff000;
1380 if (seg_end > hash_end)
1381 seg_end = hash_end;
1382 dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end);
1383 seg_start = seg_end + 0x1000;
1384 }
1385}
1386
1387int
1388mread(unsigned long adrs, void *buf, int size)
1389{
1390 volatile int n;
1391 char *p, *q;
1392
1393 n = 0;
1394 if( setjmp(bus_error_jmp) == 0 ){
1395 debugger_fault_handler = handle_fault;
1396 sync();
1397 p = (char *) adrs;
1398 q = (char *) buf;
1399 switch (size) {
1400 case 2: *(short *)q = *(short *)p; break;
1401 case 4: *(int *)q = *(int *)p; break;
1402 default:
1403 for( ; n < size; ++n ) {
1404 *q++ = *p++;
1405 sync();
1406 }
1407 }
1408 sync();
1409
1410 __delay(200);
1411 n = size;
1412 }
1413 debugger_fault_handler = 0;
1414 return n;
1415}
1416
1417int
1418mwrite(unsigned long adrs, void *buf, int size)
1419{
1420 volatile int n;
1421 char *p, *q;
1422
1423 n = 0;
1424 if( setjmp(bus_error_jmp) == 0 ){
1425 debugger_fault_handler = handle_fault;
1426 sync();
1427 p = (char *) adrs;
1428 q = (char *) buf;
1429 switch (size) {
1430 case 2: *(short *)p = *(short *)q; break;
1431 case 4: *(int *)p = *(int *)q; break;
1432 default:
1433 for( ; n < size; ++n ) {
1434 *p++ = *q++;
1435 sync();
1436 }
1437 }
1438 sync();
1439
1440 __delay(200);
1441 n = size;
1442 } else {
1443 printf("*** Error writing address %x\n", adrs + n);
1444 }
1445 debugger_fault_handler = 0;
1446 return n;
1447}
1448
1449static int fault_type;
1450static char *fault_chars[] = { "--", "**", "##" };
1451
1452static void
1453handle_fault(struct pt_regs *regs)
1454{
1455 switch (regs->trap) {
1456 case 0x200:
1457 fault_type = 0;
1458 break;
1459 case 0x300:
1460 case 0x380:
1461 fault_type = 1;
1462 break;
1463 default:
1464 fault_type = 2;
1465 }
1466
1467 longjmp(bus_error_jmp, 1);
1468}
1469
1470#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1471
1472void
1473byterev(unsigned char *val, int size)
1474{
1475 int t;
1476
1477 switch (size) {
1478 case 2:
1479 SWAP(val[0], val[1], t);
1480 break;
1481 case 4:
1482 SWAP(val[0], val[3], t);
1483 SWAP(val[1], val[2], t);
1484 break;
1485 case 8:
1486 SWAP(val[0], val[7], t);
1487 SWAP(val[1], val[6], t);
1488 SWAP(val[2], val[5], t);
1489 SWAP(val[3], val[4], t);
1490 break;
1491 }
1492}
1493
1494static int brev;
1495static int mnoread;
1496
1497static char *memex_help_string =
1498 "Memory examine command usage:\n"
1499 "m [addr] [flags] examine/change memory\n"
1500 " addr is optional. will start where left off.\n"
1501 " flags may include chars from this set:\n"
1502 " b modify by bytes (default)\n"
1503 " w modify by words (2 byte)\n"
1504 " l modify by longs (4 byte)\n"
1505 " d modify by doubleword (8 byte)\n"
1506 " r toggle reverse byte order mode\n"
1507 " n do not read memory (for i/o spaces)\n"
1508 " . ok to read (default)\n"
1509 "NOTE: flags are saved as defaults\n"
1510 "";
1511
1512static char *memex_subcmd_help_string =
1513 "Memory examine subcommands:\n"
1514 " hexval write this val to current location\n"
1515 " 'string' write chars from string to this location\n"
1516 " ' increment address\n"
1517 " ^ decrement address\n"
1518 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1519 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1520 " ` clear no-read flag\n"
1521 " ; stay at this addr\n"
1522 " v change to byte mode\n"
1523 " w change to word (2 byte) mode\n"
1524 " l change to long (4 byte) mode\n"
1525 " u change to doubleword (8 byte) mode\n"
1526 " m addr change current addr\n"
1527 " n toggle no-read flag\n"
1528 " r toggle byte reverse flag\n"
1529 " < count back up count bytes\n"
1530 " > count skip forward count bytes\n"
1531 " x exit this mode\n"
1532 "";
1533
1534void
1535memex()
1536{
1537 int cmd, inc, i, nslash;
1538 unsigned long n;
1539 unsigned char val[16];
1540
1541 scanhex((void *)&adrs);
1542 cmd = skipbl();
1543 if (cmd == '?') {
1544 printf(memex_help_string);
1545 return;
1546 } else {
1547 termch = cmd;
1548 }
1549 last_cmd = "m\n";
1550 while ((cmd = skipbl()) != '\n') {
1551 switch( cmd ){
1552 case 'b': size = 1; break;
1553 case 'w': size = 2; break;
1554 case 'l': size = 4; break;
1555 case 'd': size = 8; break;
1556 case 'r': brev = !brev; break;
1557 case 'n': mnoread = 1; break;
1558 case '.': mnoread = 0; break;
1559 }
1560 }
1561 if( size <= 0 )
1562 size = 1;
1563 else if( size > 8 )
1564 size = 8;
1565 for(;;){
1566 if (!mnoread)
1567 n = mread(adrs, val, size);
1568 printf("%.16x%c", adrs, brev? 'r': ' ');
1569 if (!mnoread) {
1570 if (brev)
1571 byterev(val, size);
1572 putchar(' ');
1573 for (i = 0; i < n; ++i)
1574 printf("%.2x", val[i]);
1575 for (; i < size; ++i)
1576 printf("%s", fault_chars[fault_type]);
1577 }
1578 putchar(' ');
1579 inc = size;
1580 nslash = 0;
1581 for(;;){
1582 if( scanhex(&n) ){
1583 for (i = 0; i < size; ++i)
1584 val[i] = n >> (i * 8);
1585 if (!brev)
1586 byterev(val, size);
1587 mwrite(adrs, val, size);
1588 inc = size;
1589 }
1590 cmd = skipbl();
1591 if (cmd == '\n')
1592 break;
1593 inc = 0;
1594 switch (cmd) {
1595 case '\'':
1596 for(;;){
1597 n = inchar();
1598 if( n == '\\' )
1599 n = bsesc();
1600 else if( n == '\'' )
1601 break;
1602 for (i = 0; i < size; ++i)
1603 val[i] = n >> (i * 8);
1604 if (!brev)
1605 byterev(val, size);
1606 mwrite(adrs, val, size);
1607 adrs += size;
1608 }
1609 adrs -= size;
1610 inc = size;
1611 break;
1612 case ',':
1613 adrs += size;
1614 break;
1615 case '.':
1616 mnoread = 0;
1617 break;
1618 case ';':
1619 break;
1620 case 'x':
1621 case EOF:
1622 scannl();
1623 return;
1624 case 'b':
1625 case 'v':
1626 size = 1;
1627 break;
1628 case 'w':
1629 size = 2;
1630 break;
1631 case 'l':
1632 size = 4;
1633 break;
1634 case 'u':
1635 size = 8;
1636 break;
1637 case '^':
1638 adrs -= size;
1639 break;
1640 break;
1641 case '/':
1642 if (nslash > 0)
1643 adrs -= 1 << nslash;
1644 else
1645 nslash = 0;
1646 nslash += 4;
1647 adrs += 1 << nslash;
1648 break;
1649 case '\\':
1650 if (nslash < 0)
1651 adrs += 1 << -nslash;
1652 else
1653 nslash = 0;
1654 nslash -= 4;
1655 adrs -= 1 << -nslash;
1656 break;
1657 case 'm':
1658 scanhex((void *)&adrs);
1659 break;
1660 case 'n':
1661 mnoread = 1;
1662 break;
1663 case 'r':
1664 brev = !brev;
1665 break;
1666 case '<':
1667 n = size;
1668 scanhex(&n);
1669 adrs -= n;
1670 break;
1671 case '>':
1672 n = size;
1673 scanhex(&n);
1674 adrs += n;
1675 break;
1676 case '?':
1677 printf(memex_subcmd_help_string);
1678 break;
1679 }
1680 }
1681 adrs += inc;
1682 }
1683}
1684
1685int
1686bsesc()
1687{
1688 int c;
1689
1690 c = inchar();
1691 switch( c ){
1692 case 'n': c = '\n'; break;
1693 case 'r': c = '\r'; break;
1694 case 'b': c = '\b'; break;
1695 case 't': c = '\t'; break;
1696 }
1697 return c;
1698}
1699
1700#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1701 || ('a' <= (c) && (c) <= 'f') \
1702 || ('A' <= (c) && (c) <= 'F'))
1703void
1704dump()
1705{
1706 int c;
1707
1708 c = inchar();
1709 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1710 termch = c;
1711 scanhex((void *)&adrs);
1712 if( termch != '\n')
1713 termch = 0;
1714 if( c == 'i' ){
1715 scanhex(&nidump);
1716 if( nidump == 0 )
1717 nidump = 16;
1718 adrs += ppc_inst_dump(adrs, nidump);
1719 last_cmd = "di\n";
1720 } else {
1721 scanhex(&ndump);
1722 if( ndump == 0 )
1723 ndump = 64;
1724 prdump(adrs, ndump);
1725 adrs += ndump;
1726 last_cmd = "d\n";
1727 }
1728}
1729
1730void
1731prdump(unsigned long adrs, long ndump)
1732{
1733 long n, m, c, r, nr;
1734 unsigned char temp[16];
1735
1736 for( n = ndump; n > 0; ){
1737 printf("%.16lx", adrs);
1738 putchar(' ');
1739 r = n < 16? n: 16;
1740 nr = mread(adrs, temp, r);
1741 adrs += nr;
1742 for( m = 0; m < r; ++m ){
1743 if ((m & 7) == 0 && m > 0)
1744 putchar(' ');
1745 if( m < nr )
1746 printf("%.2x", temp[m]);
1747 else
1748 printf("%s", fault_chars[fault_type]);
1749 }
1750 for(; m < 16; ++m )
1751 printf(" ");
1752 printf(" |");
1753 for( m = 0; m < r; ++m ){
1754 if( m < nr ){
1755 c = temp[m];
1756 putchar(' ' <= c && c <= '~'? c: '.');
1757 } else
1758 putchar(' ');
1759 }
1760 n -= r;
1761 for(; m < 16; ++m )
1762 putchar(' ');
1763 printf("|\n");
1764 if( nr < r )
1765 break;
1766 }
1767}
1768
1769int
1770ppc_inst_dump(unsigned long adr, long count)
1771{
1772 int nr, dotted;
1773 unsigned long first_adr;
1774 unsigned long inst, last_inst;
1775 unsigned char val[4];
1776
1777 dotted = 0;
1778 for (first_adr = adr; count > 0; --count, adr += 4){
1779 nr = mread(adr, val, 4);
1780 if( nr == 0 ){
1781 const char *x = fault_chars[fault_type];
1782 printf("%.16lx %s%s%s%s\n", adr, x, x, x, x);
1783 break;
1784 }
1785 inst = GETWORD(val);
1786 if (adr > first_adr && inst == last_inst) {
1787 if (!dotted) {
1788 printf(" ...\n");
1789 dotted = 1;
1790 }
1791 continue;
1792 }
1793 dotted = 0;
1794 last_inst = inst;
1795 printf("%.16lx ", adr);
1796 printf("%.8x\t", inst);
1797 print_insn_big_powerpc(stdout, inst, adr);
1798 printf("\n");
1799 }
1800 return adr - first_adr;
1801}
1802
1803void
1804print_address(unsigned long addr)
1805{
1806 printf("0x%lx", addr);
1807}
1808
1809
1810
1811
1812static unsigned long mdest;
1813static unsigned long msrc;
1814static unsigned long mval;
1815static unsigned long mcount;
1816static unsigned long mdiffs;
1817
1818void
1819memops(int cmd)
1820{
1821 scanhex((void *)&mdest);
1822 if( termch != '\n' )
1823 termch = 0;
1824 scanhex((void *)(cmd == 's'? &mval: &msrc));
1825 if( termch != '\n' )
1826 termch = 0;
1827 scanhex((void *)&mcount);
1828 switch( cmd ){
1829 case 'm':
1830 memmove((void *)mdest, (void *)msrc, mcount);
1831 break;
1832 case 's':
1833 memset((void *)mdest, mval, mcount);
1834 break;
1835 case 'd':
1836 if( termch != '\n' )
1837 termch = 0;
1838 scanhex((void *)&mdiffs);
1839 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1840 break;
1841 }
1842}
1843
1844void
1845memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1846{
1847 unsigned n, prt;
1848
1849 prt = 0;
1850 for( n = nb; n > 0; --n )
1851 if( *p1++ != *p2++ )
1852 if( ++prt <= maxpr )
1853 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
1854 p1[-1], p2 - 1, p2[-1]);
1855 if( prt > maxpr )
1856 printf("Total of %d differences\n", prt);
1857}
1858
1859static unsigned mend;
1860static unsigned mask;
1861
1862void
1863memlocate()
1864{
1865 unsigned a, n;
1866 unsigned char val[4];
1867
1868 last_cmd = "ml";
1869 scanhex((void *)&mdest);
1870 if (termch != '\n') {
1871 termch = 0;
1872 scanhex((void *)&mend);
1873 if (termch != '\n') {
1874 termch = 0;
1875 scanhex((void *)&mval);
1876 mask = ~0;
1877 if (termch != '\n') termch = 0;
1878 scanhex((void *)&mask);
1879 }
1880 }
1881 n = 0;
1882 for (a = mdest; a < mend; a += 4) {
1883 if (mread(a, val, 4) == 4
1884 && ((GETWORD(val) ^ mval) & mask) == 0) {
1885 printf("%.16x: %.16x\n", a, GETWORD(val));
1886 if (++n >= 10)
1887 break;
1888 }
1889 }
1890}
1891
1892static unsigned long mskip = 0x1000;
1893static unsigned long mlim = 0xffffffff;
1894
1895void
1896memzcan()
1897{
1898 unsigned char v;
1899 unsigned a;
1900 int ok, ook;
1901
1902 scanhex(&mdest);
1903 if (termch != '\n') termch = 0;
1904 scanhex(&mskip);
1905 if (termch != '\n') termch = 0;
1906 scanhex(&mlim);
1907 ook = 0;
1908 for (a = mdest; a < mlim; a += mskip) {
1909 ok = mread(a, &v, 1);
1910 if (ok && !ook) {
1911 printf("%.8x .. ", a);
1912 fflush(stdout);
1913 } else if (!ok && ook)
1914 printf("%.8x\n", a - mskip);
1915 ook = ok;
1916 if (a + mskip < a)
1917 break;
1918 }
1919 if (ook)
1920 printf("%.8x\n", a - mskip);
1921}
1922
1923
1924int
1925skipbl()
1926{
1927 int c;
1928
1929 if( termch != 0 ){
1930 c = termch;
1931 termch = 0;
1932 } else
1933 c = inchar();
1934 while( c == ' ' || c == '\t' )
1935 c = inchar();
1936 return c;
1937}
1938
1939#define N_PTREGS 44
1940static char *regnames[N_PTREGS] = {
1941 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1942 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1943 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1944 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1945 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1946 "trap", "dar", "dsisr", "res"
1947};
1948
1949int
1950scanhex(vp)
1951unsigned long *vp;
1952{
1953 int c, d;
1954 unsigned long v;
1955
1956 c = skipbl();
1957 if (c == '%') {
1958
1959 char regname[8];
1960 int i;
1961
1962 for (i = 0; i < sizeof(regname) - 1; ++i) {
1963 c = inchar();
1964 if (!isalnum(c)) {
1965 termch = c;
1966 break;
1967 }
1968 regname[i] = c;
1969 }
1970 regname[i] = 0;
1971 for (i = 0; i < N_PTREGS; ++i) {
1972 if (strcmp(regnames[i], regname) == 0) {
1973 unsigned long *rp = (unsigned long *)
1974 xmon_regs[smp_processor_id()];
1975 if (rp == NULL) {
1976 printf("regs not available\n");
1977 return 0;
1978 }
1979 *vp = rp[i];
1980 return 1;
1981 }
1982 }
1983 printf("invalid register name '%%%s'\n", regname);
1984 return 0;
1985 }
1986
1987 d = hexdigit(c);
1988 if( d == EOF ){
1989 termch = c;
1990 return 0;
1991 }
1992 v = 0;
1993 do {
1994 v = (v << 4) + d;
1995 c = inchar();
1996 d = hexdigit(c);
1997 } while( d != EOF );
1998 termch = c;
1999 *vp = v;
2000 return 1;
2001}
2002
2003void
2004scannl()
2005{
2006 int c;
2007
2008 c = termch;
2009 termch = 0;
2010 while( c != '\n' )
2011 c = inchar();
2012}
2013
2014int
2015hexdigit(int c)
2016{
2017 if( '0' <= c && c <= '9' )
2018 return c - '0';
2019 if( 'A' <= c && c <= 'F' )
2020 return c - ('A' - 10);
2021 if( 'a' <= c && c <= 'f' )
2022 return c - ('a' - 10);
2023 return EOF;
2024}
2025
2026void
2027getstring(char *s, int size)
2028{
2029 int c;
2030
2031 c = skipbl();
2032 do {
2033 if( size > 1 ){
2034 *s++ = c;
2035 --size;
2036 }
2037 c = inchar();
2038 } while( c != ' ' && c != '\t' && c != '\n' );
2039 termch = c;
2040 *s = 0;
2041}
2042
2043static char line[256];
2044static char *lineptr;
2045
2046void
2047flush_input()
2048{
2049 lineptr = NULL;
2050}
2051
2052int
2053inchar()
2054{
2055 if (lineptr == NULL || *lineptr == 0) {
2056 if (fgets(line, sizeof(line), stdin) == NULL) {
2057 lineptr = NULL;
2058 return EOF;
2059 }
2060 lineptr = line;
2061 }
2062 return *lineptr++;
2063}
2064
2065void
2066take_input(str)
2067char *str;
2068{
2069 lineptr = str;
2070}
2071
2072
2073
2074
2075
2076static int
2077find_tb_table(unsigned long codeaddr, struct tbtable *tab)
2078{
2079 unsigned long codeaddr_max;
2080 unsigned long tbtab_start;
2081 int nr;
2082 int instr;
2083 int num_parms;
2084
2085 if (tab == NULL)
2086 return 0;
2087 memset(tab, 0, sizeof(tab));
2088
2089
2090 for (codeaddr_max = codeaddr + 128*1024*4;
2091 codeaddr < codeaddr_max;
2092 codeaddr += 4) {
2093 nr = mread(codeaddr, &instr, 4);
2094 if (nr != 4)
2095 return 0;
2096 if (instr == 0) {
2097
2098 int version;
2099 unsigned long flags;
2100 tbtab_start = codeaddr;
2101 codeaddr += 4;
2102 nr = mread(codeaddr, &flags, 8);
2103 if (nr != 8)
2104 return 0;
2105 tab->flags = flags;
2106 version = (flags >> 56) & 0xff;
2107 if (version != 0)
2108 continue;
2109
2110
2111 tab->fp_saved = (flags >> 24) & 0x3f;
2112 tab->gpr_saved = (flags >> 16) & 0x3f;
2113 tab->fixedparms = (flags >> 8) & 0xff;
2114 tab->floatparms = (flags >> 1) & 0x7f;
2115 codeaddr += 8;
2116 num_parms = tab->fixedparms + tab->floatparms;
2117 if (num_parms) {
2118 unsigned int parminfo;
2119 int parm;
2120 if (num_parms > 32)
2121 return 1;
2122 nr = mread(codeaddr, &parminfo, 4);
2123 if (nr != 4)
2124 return 1;
2125
2126
2127
2128
2129 for (parm = 0; parm < num_parms; parm++) {
2130 if (parminfo & 0x80000000) {
2131 parminfo <<= 1;
2132 if (parminfo & 0x80000000)
2133 tab->parminfo[parm] = TBTAB_PARMDFLOAT;
2134 else
2135 tab->parminfo[parm] = TBTAB_PARMSFLOAT;
2136 } else {
2137 tab->parminfo[parm] = TBTAB_PARMFIXED;
2138 }
2139 parminfo <<= 1;
2140 }
2141 codeaddr += 4;
2142 }
2143 if (flags & TBTAB_FLAGSHASTBOFF) {
2144 nr = mread(codeaddr, &tab->tb_offset, 4);
2145 if (nr != 4)
2146 return 1;
2147 if (tab->tb_offset > 0) {
2148 tab->funcstart = tbtab_start - tab->tb_offset;
2149 }
2150 codeaddr += 4;
2151 }
2152
2153 if (flags & TBTAB_FLAGSHASCTL) {
2154
2155 return 1;
2156 }
2157 if (flags & TBTAB_FLAGSNAMEPRESENT) {
2158 short namlen;
2159 nr = mread(codeaddr, &namlen, 2);
2160 if (nr != 2)
2161 return 1;
2162 if (namlen >= sizeof(tab->name))
2163 namlen = sizeof(tab->name)-1;
2164 codeaddr += 2;
2165 nr = mread(codeaddr, tab->name, namlen);
2166 tab->name[namlen] = '\0';
2167 codeaddr += namlen;
2168 }
2169 return 1;
2170 }
2171 }
2172 return 0;
2173}
2174
2175void
2176mem_translate()
2177{
2178 int c;
2179 unsigned long ea, va, vsid, vpn, page, hpteg_slot_primary, hpteg_slot_secondary, primary_hash, i, *steg, esid, stabl;
2180 HPTE * hpte;
2181 struct mm_struct * mm;
2182 pte_t *ptep = NULL;
2183 void * pgdir;
2184
2185 c = inchar();
2186 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2187 termch = c;
2188 scanhex((void *)&ea);
2189
2190 if ((ea >= KRANGE_START) && (ea <= (KRANGE_START + (1UL<<60)))) {
2191 ptep = 0;
2192 vsid = get_kernel_vsid(ea);
2193 va = ( vsid << 28 ) | ( ea & 0x0fffffff );
2194 } else {
2195
2196 if ( ( ea >= VMALLOC_START ) && ( ea <= VMALLOC_END ) ) {
2197 mm = &init_mm;
2198 vsid = get_kernel_vsid( ea );
2199 }
2200
2201 else if ( ( ea >= IMALLOC_START ) && ( ea <= IMALLOC_END ) ) {
2202 mm = &ioremap_mm;
2203 vsid = get_kernel_vsid( ea );
2204 }
2205
2206 else if ( ( ea >= USER_START ) && ( ea <= USER_END ) ) {
2207 mm = current->mm;
2208 vsid = get_vsid(mm->context, ea );
2209 }
2210 pgdir = mm->pgd;
2211 va = ( vsid << 28 ) | ( ea & 0x0fffffff );
2212 ptep = find_linux_pte( pgdir, ea );
2213 }
2214
2215 vpn = ((vsid << 28) | (((ea) & 0xFFFF000))) >> 12;
2216 page = vpn & 0xffff;
2217 esid = (ea >> 28) & 0xFFFFFFFFF;
2218
2219
2220 primary_hash = ( vsid & 0x7fffffffff ) ^ page;
2221 hpteg_slot_primary = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
2222 hpteg_slot_secondary = ( ~primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
2223
2224 printf("ea : %.16lx\n", ea);
2225 printf("esid : %.16lx\n", esid);
2226 printf("vsid : %.16lx\n", vsid);
2227
2228 printf("\nSoftware Page Table\n-------------------\n");
2229 printf("ptep : %.16lx\n", ((unsigned long *)ptep));
2230 if(ptep) {
2231 printf("*ptep : %.16lx\n", *((unsigned long *)ptep));
2232 }
2233
2234 hpte = htab_data.htab + hpteg_slot_primary;
2235 printf("\nHardware Page Table\n-------------------\n");
2236 printf("htab base : %.16lx\n", htab_data.htab);
2237 printf("slot primary : %.16lx\n", hpteg_slot_primary);
2238 printf("slot secondary : %.16lx\n", hpteg_slot_secondary);
2239 printf("\nPrimary Group\n");
2240 for (i=0; i<8; ++i) {
2241 if ( hpte->dw0.dw0.v != 0 ) {
2242 printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1);
2243 printf(" vsid: %.13lx api: %.2lx hash: %.1lx\n",
2244 (hpte->dw0.dw0.avpn)>>5,
2245 (hpte->dw0.dw0.avpn) & 0x1f,
2246 (hpte->dw0.dw0.h));
2247 printf(" rpn: %.13lx \n", (hpte->dw1.dw1.rpn));
2248 printf(" pp: %.1lx \n",
2249 ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp));
2250 printf(" wimgn: %.2lx reference: %.1lx change: %.1lx\n",
2251 ((hpte->dw1.dw1.w)<<4)|
2252 ((hpte->dw1.dw1.i)<<3)|
2253 ((hpte->dw1.dw1.m)<<2)|
2254 ((hpte->dw1.dw1.g)<<1)|
2255 ((hpte->dw1.dw1.n)<<0),
2256 hpte->dw1.dw1.r, hpte->dw1.dw1.c);
2257 }
2258 hpte++;
2259 }
2260
2261 printf("\nSecondary Group\n");
2262
2263 hpte = htab_data.htab + hpteg_slot_secondary;
2264 for (i=0; i<8; ++i) {
2265 if(hpte->dw0.dw0.v) {
2266 printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1);
2267 printf(" vsid: %.13lx api: %.2lx hash: %.1lx\n",
2268 (hpte->dw0.dw0.avpn)>>5,
2269 (hpte->dw0.dw0.avpn) & 0x1f,
2270 (hpte->dw0.dw0.h));
2271 printf(" rpn: %.13lx \n", (hpte->dw1.dw1.rpn));
2272 printf(" pp: %.1lx \n",
2273 ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp));
2274 printf(" wimgn: %.2lx reference: %.1lx change: %.1lx\n",
2275 ((hpte->dw1.dw1.w)<<4)|
2276 ((hpte->dw1.dw1.i)<<3)|
2277 ((hpte->dw1.dw1.m)<<2)|
2278 ((hpte->dw1.dw1.g)<<1)|
2279 ((hpte->dw1.dw1.n)<<0),
2280 hpte->dw1.dw1.r, hpte->dw1.dw1.c);
2281 }
2282 hpte++;
2283 }
2284
2285 printf("\nHardware Segment Table\n-----------------------\n");
2286 stabl = (unsigned long)(KERNELBASE+(_ASR&0xFFFFFFFFFFFFFFFE));
2287 steg = (unsigned long *)((stabl) | ((esid & 0x1f) << 7));
2288
2289 printf("stab base : %.16lx\n", stabl);
2290 printf("slot : %.16lx\n", steg);
2291
2292 for (i=0; i<8; ++i) {
2293 printf("%d: (ste) %.16lx %.16lx\n", i,
2294 *((unsigned long *)(steg+i*2)),*((unsigned long *)(steg+i*2+1)) );
2295 }
2296}
2297
2298void mem_check()
2299{
2300 unsigned long htab_size_bytes;
2301 unsigned long htab_end;
2302 unsigned long last_rpn;
2303 HPTE *hpte1, *hpte2;
2304
2305 htab_size_bytes = htab_data.htab_num_ptegs * 128;
2306 htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
2307
2308 last_rpn = 0xfffff;
2309
2310 printf("\nHardware Page Table Check\n-------------------\n");
2311 printf("htab base : %.16lx\n", htab_data.htab);
2312 printf("htab size : %.16lx\n", htab_size_bytes);
2313
2314#if 1
2315 for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
2316 if ( hpte1->dw0.dw0.v != 0 ) {
2317 if ( hpte1->dw1.dw1.rpn <= last_rpn ) {
2318 for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) {
2319 if ( hpte2->dw0.dw0.v != 0 ) {
2320 if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) {
2321 printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
2322 printf(" hpte1: %16.16lx *hpte1: %16.16lx %16.16lx\n",
2323 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2324 printf(" hpte2: %16.16lx *hpte2: %16.16lx %16.16lx\n",
2325 hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1);
2326 }
2327 }
2328 }
2329 } else {
2330 printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
2331 printf(" hpte: %16.16lx *hpte: %16.16lx %16.16lx\n",
2332 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2333 }
2334 }
2335 }
2336#endif
2337 printf("\nDone -------------------\n");
2338}
2339
2340void mem_find_real()
2341{
2342 unsigned long htab_size_bytes;
2343 unsigned long htab_end;
2344 unsigned long last_rpn;
2345 HPTE *hpte1;
2346 unsigned long pa, rpn;
2347 int c;
2348
2349 c = inchar();
2350 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2351 termch = c;
2352 scanhex((void *)&pa);
2353 rpn = pa >> 12;
2354
2355 htab_size_bytes = htab_data.htab_num_ptegs * 128;
2356 htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
2357
2358 last_rpn = 0xfffff;
2359
2360 printf("\nMem Find RPN\n-------------------\n");
2361 printf("htab base : %.16lx\n", htab_data.htab);
2362 printf("htab size : %.16lx\n", htab_size_bytes);
2363
2364 for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
2365 if ( hpte1->dw0.dw0.v != 0 ) {
2366 if ( hpte1->dw1.dw1.rpn == rpn ) {
2367 printf(" Found rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
2368 printf(" hpte: %16.16lx *hpte1: %16.16lx %16.16lx\n",
2369 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2370 }
2371 }
2372 }
2373 printf("\nDone -------------------\n");
2374}
2375
2376void mem_find_vsid()
2377{
2378 unsigned long htab_size_bytes;
2379 unsigned long htab_end;
2380 HPTE *hpte1;
2381 unsigned long vsid;
2382 int c;
2383
2384 c = inchar();
2385 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2386 termch = c;
2387 scanhex((void *)&vsid);
2388
2389 htab_size_bytes = htab_data.htab_num_ptegs * 128;
2390 htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
2391
2392 printf("\nMem Find VSID\n-------------------\n");
2393 printf("htab base : %.16lx\n", htab_data.htab);
2394 printf("htab size : %.16lx\n", htab_size_bytes);
2395
2396 for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
2397 if ( hpte1->dw0.dw0.v != 0 ) {
2398 if ( ((hpte1->dw0.dw0.avpn)>>5) == vsid ) {
2399 printf(" Found vsid: %.16lx \n", ((hpte1->dw0.dw0.avpn) >> 5));
2400 printf(" hpte: %16.16lx *hpte1: %16.16lx %16.16lx\n",
2401 hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2402 }
2403 }
2404 }
2405 printf("\nDone -------------------\n");
2406}
2407
2408static void debug_trace(void) {
2409 unsigned long val, cmd, on;
2410
2411 cmd = skipbl();
2412 if (cmd == '\n') {
2413
2414 unsigned long i;
2415 printf("naca->debug_switch = 0x%lx\n", naca->debug_switch);
2416 for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) {
2417 on = PPCDBG_BITVAL(i) & naca->debug_switch;
2418 printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : "");
2419 if (((i+1) % 3) == 0)
2420 printf("\n");
2421 }
2422 printf("\n");
2423 return;
2424 }
2425 while (cmd != '\n') {
2426 on = 1;
2427 while (cmd == '+' || cmd == '-') {
2428 on = (cmd == '+');
2429 cmd = inchar();
2430 if (cmd == ' ' || cmd == '\n') {
2431 naca->debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE;
2432 printf("Setting all values to %s...\n", on ? "on" : "off");
2433 if (cmd == '\n') return;
2434 else cmd = skipbl();
2435 }
2436 else
2437 termch = cmd;
2438 }
2439 termch = cmd;
2440 scanhex((void *)&val);
2441 if (val >= 64) {
2442 printf("Value %x out of range:\n", val);
2443 return;
2444 }
2445 if (on) {
2446 naca->debug_switch |= PPCDBG_BITVAL(val);
2447 printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2448 } else {
2449 naca->debug_switch &= ~PPCDBG_BITVAL(val);
2450 printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2451 }
2452 cmd = skipbl();
2453 }
2454}
2455