Merge git://git.infradead.org/mtd-2.6
[deliverable/linux.git] / arch / powerpc / xmon / xmon.c
1 /*
2 * Routines providing a simple monitor for use on the PowerMac.
3 *
4 * Copyright (C) 1996-2005 Paul Mackerras.
5 * Copyright (C) 2001 PPC64 Team, IBM Corp
6 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/smp.h>
16 #include <linux/mm.h>
17 #include <linux/reboot.h>
18 #include <linux/delay.h>
19 #include <linux/kallsyms.h>
20 #include <linux/cpumask.h>
21 #include <linux/module.h>
22 #include <linux/sysrq.h>
23 #include <linux/interrupt.h>
24 #include <linux/irq.h>
25 #include <linux/bug.h>
26
27 #include <asm/ptrace.h>
28 #include <asm/string.h>
29 #include <asm/prom.h>
30 #include <asm/machdep.h>
31 #include <asm/xmon.h>
32 #include <asm/processor.h>
33 #include <asm/pgtable.h>
34 #include <asm/mmu.h>
35 #include <asm/mmu_context.h>
36 #include <asm/cputable.h>
37 #include <asm/rtas.h>
38 #include <asm/sstep.h>
39 #include <asm/irq_regs.h>
40 #include <asm/spu.h>
41 #include <asm/spu_priv1.h>
42 #include <asm/firmware.h>
43 #include <asm/setjmp.h>
44
45 #ifdef CONFIG_PPC64
46 #include <asm/hvcall.h>
47 #include <asm/paca.h>
48 #endif
49
50 #include "nonstdio.h"
51 #include "dis-asm.h"
52
53 #define scanhex xmon_scanhex
54 #define skipbl xmon_skipbl
55
56 #ifdef CONFIG_SMP
57 static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
58 static unsigned long xmon_taken = 1;
59 static int xmon_owner;
60 static int xmon_gate;
61 #endif /* CONFIG_SMP */
62
63 static unsigned long in_xmon = 0;
64
65 static unsigned long adrs;
66 static int size = 1;
67 #define MAX_DUMP (128 * 1024)
68 static unsigned long ndump = 64;
69 static unsigned long nidump = 16;
70 static unsigned long ncsum = 4096;
71 static int termch;
72 static char tmpstr[128];
73
74 static long bus_error_jmp[JMP_BUF_LEN];
75 static int catch_memory_errors;
76 static long *xmon_fault_jmp[NR_CPUS];
77
78 /* Breakpoint stuff */
79 struct bpt {
80 unsigned long address;
81 unsigned int instr[2];
82 atomic_t ref_count;
83 int enabled;
84 unsigned long pad;
85 };
86
87 /* Bits in bpt.enabled */
88 #define BP_IABR_TE 1 /* IABR translation enabled */
89 #define BP_IABR 2
90 #define BP_TRAP 8
91 #define BP_DABR 0x10
92
93 #define NBPTS 256
94 static struct bpt bpts[NBPTS];
95 static struct bpt dabr;
96 static struct bpt *iabr;
97 static unsigned bpinstr = 0x7fe00008; /* trap */
98
99 #define BP_NUM(bp) ((bp) - bpts + 1)
100
101 /* Prototypes */
102 static int cmds(struct pt_regs *);
103 static int mread(unsigned long, void *, int);
104 static int mwrite(unsigned long, void *, int);
105 static int handle_fault(struct pt_regs *);
106 static void byterev(unsigned char *, int);
107 static void memex(void);
108 static int bsesc(void);
109 static void dump(void);
110 static void prdump(unsigned long, long);
111 static int ppc_inst_dump(unsigned long, long, int);
112 static void backtrace(struct pt_regs *);
113 static void excprint(struct pt_regs *);
114 static void prregs(struct pt_regs *);
115 static void memops(int);
116 static void memlocate(void);
117 static void memzcan(void);
118 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
119 int skipbl(void);
120 int scanhex(unsigned long *valp);
121 static void scannl(void);
122 static int hexdigit(int);
123 void getstring(char *, int);
124 static void flush_input(void);
125 static int inchar(void);
126 static void take_input(char *);
127 static unsigned long read_spr(int);
128 static void write_spr(int, unsigned long);
129 static void super_regs(void);
130 static void remove_bpts(void);
131 static void insert_bpts(void);
132 static void remove_cpu_bpts(void);
133 static void insert_cpu_bpts(void);
134 static struct bpt *at_breakpoint(unsigned long pc);
135 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
136 static int do_step(struct pt_regs *);
137 static void bpt_cmds(void);
138 static void cacheflush(void);
139 static int cpu_cmd(void);
140 static void csum(void);
141 static void bootcmds(void);
142 static void proccall(void);
143 void dump_segments(void);
144 static void symbol_lookup(void);
145 static void xmon_show_stack(unsigned long sp, unsigned long lr,
146 unsigned long pc);
147 static void xmon_print_symbol(unsigned long address, const char *mid,
148 const char *after);
149 static const char *getvecname(unsigned long vec);
150
151 static int do_spu_cmd(void);
152
153 #ifdef CONFIG_44x
154 static void dump_tlb_44x(void);
155 #endif
156
157 static int xmon_no_auto_backtrace;
158
159 extern void xmon_enter(void);
160 extern void xmon_leave(void);
161
162 extern void xmon_save_regs(struct pt_regs *);
163
164 #ifdef CONFIG_PPC64
165 #define REG "%.16lx"
166 #define REGS_PER_LINE 4
167 #define LAST_VOLATILE 13
168 #else
169 #define REG "%.8lx"
170 #define REGS_PER_LINE 8
171 #define LAST_VOLATILE 12
172 #endif
173
174 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
175
176 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
177 || ('a' <= (c) && (c) <= 'f') \
178 || ('A' <= (c) && (c) <= 'F'))
179 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
180 || ('a' <= (c) && (c) <= 'z') \
181 || ('A' <= (c) && (c) <= 'Z'))
182 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
183
184 static char *help_string = "\
185 Commands:\n\
186 b show breakpoints\n\
187 bd set data breakpoint\n\
188 bi set instruction breakpoint\n\
189 bc clear breakpoint\n"
190 #ifdef CONFIG_SMP
191 "\
192 c print cpus stopped in xmon\n\
193 c# try to switch to cpu number h (in hex)\n"
194 #endif
195 "\
196 C checksum\n\
197 d dump bytes\n\
198 di dump instructions\n\
199 df dump float values\n\
200 dd dump double values\n\
201 dr dump stream of raw bytes\n\
202 e print exception information\n\
203 f flush cache\n\
204 la lookup symbol+offset of specified address\n\
205 ls lookup address of specified symbol\n\
206 m examine/change memory\n\
207 mm move a block of memory\n\
208 ms set a block of memory\n\
209 md compare two blocks of memory\n\
210 ml locate a block of memory\n\
211 mz zero a block of memory\n\
212 mi show information about memory allocation\n\
213 p call a procedure\n\
214 r print registers\n\
215 s single step\n"
216 #ifdef CONFIG_SPU_BASE
217 " ss stop execution on all spus\n\
218 sr restore execution on stopped spus\n\
219 sf # dump spu fields for spu # (in hex)\n\
220 sd # dump spu local store for spu # (in hex)\n\
221 sdi # disassemble spu local store for spu # (in hex)\n"
222 #endif
223 " S print special registers\n\
224 t print backtrace\n\
225 x exit monitor and recover\n\
226 X exit monitor and dont recover\n"
227 #ifdef CONFIG_PPC64
228 " u dump segment table or SLB\n"
229 #endif
230 #ifdef CONFIG_PPC_STD_MMU_32
231 " u dump segment registers\n"
232 #endif
233 #ifdef CONFIG_44x
234 " u dump TLB\n"
235 #endif
236 " ? help\n"
237 " zr reboot\n\
238 zh halt\n"
239 ;
240
241 static struct pt_regs *xmon_regs;
242
243 static inline void sync(void)
244 {
245 asm volatile("sync; isync");
246 }
247
248 static inline void store_inst(void *p)
249 {
250 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
251 }
252
253 static inline void cflush(void *p)
254 {
255 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
256 }
257
258 static inline void cinval(void *p)
259 {
260 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
261 }
262
263 /*
264 * Disable surveillance (the service processor watchdog function)
265 * while we are in xmon.
266 * XXX we should re-enable it when we leave. :)
267 */
268 #define SURVEILLANCE_TOKEN 9000
269
270 static inline void disable_surveillance(void)
271 {
272 #ifdef CONFIG_PPC_PSERIES
273 /* Since this can't be a module, args should end up below 4GB. */
274 static struct rtas_args args;
275
276 /*
277 * At this point we have got all the cpus we can into
278 * xmon, so there is hopefully no other cpu calling RTAS
279 * at the moment, even though we don't take rtas.lock.
280 * If we did try to take rtas.lock there would be a
281 * real possibility of deadlock.
282 */
283 args.token = rtas_token("set-indicator");
284 if (args.token == RTAS_UNKNOWN_SERVICE)
285 return;
286 args.nargs = 3;
287 args.nret = 1;
288 args.rets = &args.args[3];
289 args.args[0] = SURVEILLANCE_TOKEN;
290 args.args[1] = 0;
291 args.args[2] = 0;
292 enter_rtas(__pa(&args));
293 #endif /* CONFIG_PPC_PSERIES */
294 }
295
296 #ifdef CONFIG_SMP
297 static int xmon_speaker;
298
299 static void get_output_lock(void)
300 {
301 int me = smp_processor_id() + 0x100;
302 int last_speaker = 0, prev;
303 long timeout;
304
305 if (xmon_speaker == me)
306 return;
307 for (;;) {
308 if (xmon_speaker == 0) {
309 last_speaker = cmpxchg(&xmon_speaker, 0, me);
310 if (last_speaker == 0)
311 return;
312 }
313 timeout = 10000000;
314 while (xmon_speaker == last_speaker) {
315 if (--timeout > 0)
316 continue;
317 /* hostile takeover */
318 prev = cmpxchg(&xmon_speaker, last_speaker, me);
319 if (prev == last_speaker)
320 return;
321 break;
322 }
323 }
324 }
325
326 static void release_output_lock(void)
327 {
328 xmon_speaker = 0;
329 }
330
331 int cpus_are_in_xmon(void)
332 {
333 return !cpus_empty(cpus_in_xmon);
334 }
335 #endif
336
337 static int xmon_core(struct pt_regs *regs, int fromipi)
338 {
339 int cmd = 0;
340 struct bpt *bp;
341 long recurse_jmp[JMP_BUF_LEN];
342 unsigned long offset;
343 unsigned long flags;
344 #ifdef CONFIG_SMP
345 int cpu;
346 int secondary;
347 unsigned long timeout;
348 #endif
349
350 local_irq_save(flags);
351
352 bp = in_breakpoint_table(regs->nip, &offset);
353 if (bp != NULL) {
354 regs->nip = bp->address + offset;
355 atomic_dec(&bp->ref_count);
356 }
357
358 remove_cpu_bpts();
359
360 #ifdef CONFIG_SMP
361 cpu = smp_processor_id();
362 if (cpu_isset(cpu, cpus_in_xmon)) {
363 get_output_lock();
364 excprint(regs);
365 printf("cpu 0x%x: Exception %lx %s in xmon, "
366 "returning to main loop\n",
367 cpu, regs->trap, getvecname(TRAP(regs)));
368 release_output_lock();
369 longjmp(xmon_fault_jmp[cpu], 1);
370 }
371
372 if (setjmp(recurse_jmp) != 0) {
373 if (!in_xmon || !xmon_gate) {
374 get_output_lock();
375 printf("xmon: WARNING: bad recursive fault "
376 "on cpu 0x%x\n", cpu);
377 release_output_lock();
378 goto waiting;
379 }
380 secondary = !(xmon_taken && cpu == xmon_owner);
381 goto cmdloop;
382 }
383
384 xmon_fault_jmp[cpu] = recurse_jmp;
385 cpu_set(cpu, cpus_in_xmon);
386
387 bp = NULL;
388 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
389 bp = at_breakpoint(regs->nip);
390 if (bp || (regs->msr & MSR_RI) == 0)
391 fromipi = 0;
392
393 if (!fromipi) {
394 get_output_lock();
395 excprint(regs);
396 if (bp) {
397 printf("cpu 0x%x stopped at breakpoint 0x%x (",
398 cpu, BP_NUM(bp));
399 xmon_print_symbol(regs->nip, " ", ")\n");
400 }
401 if ((regs->msr & MSR_RI) == 0)
402 printf("WARNING: exception is not recoverable, "
403 "can't continue\n");
404 release_output_lock();
405 }
406
407 waiting:
408 secondary = 1;
409 while (secondary && !xmon_gate) {
410 if (in_xmon == 0) {
411 if (fromipi)
412 goto leave;
413 secondary = test_and_set_bit(0, &in_xmon);
414 }
415 barrier();
416 }
417
418 if (!secondary && !xmon_gate) {
419 /* we are the first cpu to come in */
420 /* interrupt other cpu(s) */
421 int ncpus = num_online_cpus();
422
423 xmon_owner = cpu;
424 mb();
425 if (ncpus > 1) {
426 smp_send_debugger_break(MSG_ALL_BUT_SELF);
427 /* wait for other cpus to come in */
428 for (timeout = 100000000; timeout != 0; --timeout) {
429 if (cpus_weight(cpus_in_xmon) >= ncpus)
430 break;
431 barrier();
432 }
433 }
434 remove_bpts();
435 disable_surveillance();
436 /* for breakpoint or single step, print the current instr. */
437 if (bp || TRAP(regs) == 0xd00)
438 ppc_inst_dump(regs->nip, 1, 0);
439 printf("enter ? for help\n");
440 mb();
441 xmon_gate = 1;
442 barrier();
443 }
444
445 cmdloop:
446 while (in_xmon) {
447 if (secondary) {
448 if (cpu == xmon_owner) {
449 if (!test_and_set_bit(0, &xmon_taken)) {
450 secondary = 0;
451 continue;
452 }
453 /* missed it */
454 while (cpu == xmon_owner)
455 barrier();
456 }
457 barrier();
458 } else {
459 cmd = cmds(regs);
460 if (cmd != 0) {
461 /* exiting xmon */
462 insert_bpts();
463 xmon_gate = 0;
464 wmb();
465 in_xmon = 0;
466 break;
467 }
468 /* have switched to some other cpu */
469 secondary = 1;
470 }
471 }
472 leave:
473 cpu_clear(cpu, cpus_in_xmon);
474 xmon_fault_jmp[cpu] = NULL;
475 #else
476 /* UP is simple... */
477 if (in_xmon) {
478 printf("Exception %lx %s in xmon, returning to main loop\n",
479 regs->trap, getvecname(TRAP(regs)));
480 longjmp(xmon_fault_jmp[0], 1);
481 }
482 if (setjmp(recurse_jmp) == 0) {
483 xmon_fault_jmp[0] = recurse_jmp;
484 in_xmon = 1;
485
486 excprint(regs);
487 bp = at_breakpoint(regs->nip);
488 if (bp) {
489 printf("Stopped at breakpoint %x (", BP_NUM(bp));
490 xmon_print_symbol(regs->nip, " ", ")\n");
491 }
492 if ((regs->msr & MSR_RI) == 0)
493 printf("WARNING: exception is not recoverable, "
494 "can't continue\n");
495 remove_bpts();
496 disable_surveillance();
497 /* for breakpoint or single step, print the current instr. */
498 if (bp || TRAP(regs) == 0xd00)
499 ppc_inst_dump(regs->nip, 1, 0);
500 printf("enter ? for help\n");
501 }
502
503 cmd = cmds(regs);
504
505 insert_bpts();
506 in_xmon = 0;
507 #endif
508
509 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
510 bp = at_breakpoint(regs->nip);
511 if (bp != NULL) {
512 int stepped = emulate_step(regs, bp->instr[0]);
513 if (stepped == 0) {
514 regs->nip = (unsigned long) &bp->instr[0];
515 atomic_inc(&bp->ref_count);
516 } else if (stepped < 0) {
517 printf("Couldn't single-step %s instruction\n",
518 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
519 }
520 }
521 }
522
523 insert_cpu_bpts();
524
525 local_irq_restore(flags);
526
527 return cmd != 'X' && cmd != EOF;
528 }
529
530 int xmon(struct pt_regs *excp)
531 {
532 struct pt_regs regs;
533
534 if (excp == NULL) {
535 xmon_save_regs(&regs);
536 excp = &regs;
537 }
538
539 return xmon_core(excp, 0);
540 }
541 EXPORT_SYMBOL(xmon);
542
543 irqreturn_t xmon_irq(int irq, void *d)
544 {
545 unsigned long flags;
546 local_irq_save(flags);
547 printf("Keyboard interrupt\n");
548 xmon(get_irq_regs());
549 local_irq_restore(flags);
550 return IRQ_HANDLED;
551 }
552
553 static int xmon_bpt(struct pt_regs *regs)
554 {
555 struct bpt *bp;
556 unsigned long offset;
557
558 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
559 return 0;
560
561 /* Are we at the trap at bp->instr[1] for some bp? */
562 bp = in_breakpoint_table(regs->nip, &offset);
563 if (bp != NULL && offset == 4) {
564 regs->nip = bp->address + 4;
565 atomic_dec(&bp->ref_count);
566 return 1;
567 }
568
569 /* Are we at a breakpoint? */
570 bp = at_breakpoint(regs->nip);
571 if (!bp)
572 return 0;
573
574 xmon_core(regs, 0);
575
576 return 1;
577 }
578
579 static int xmon_sstep(struct pt_regs *regs)
580 {
581 if (user_mode(regs))
582 return 0;
583 xmon_core(regs, 0);
584 return 1;
585 }
586
587 static int xmon_dabr_match(struct pt_regs *regs)
588 {
589 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
590 return 0;
591 if (dabr.enabled == 0)
592 return 0;
593 xmon_core(regs, 0);
594 return 1;
595 }
596
597 static int xmon_iabr_match(struct pt_regs *regs)
598 {
599 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
600 return 0;
601 if (iabr == NULL)
602 return 0;
603 xmon_core(regs, 0);
604 return 1;
605 }
606
607 static int xmon_ipi(struct pt_regs *regs)
608 {
609 #ifdef CONFIG_SMP
610 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
611 xmon_core(regs, 1);
612 #endif
613 return 0;
614 }
615
616 static int xmon_fault_handler(struct pt_regs *regs)
617 {
618 struct bpt *bp;
619 unsigned long offset;
620
621 if (in_xmon && catch_memory_errors)
622 handle_fault(regs); /* doesn't return */
623
624 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
625 bp = in_breakpoint_table(regs->nip, &offset);
626 if (bp != NULL) {
627 regs->nip = bp->address + offset;
628 atomic_dec(&bp->ref_count);
629 }
630 }
631
632 return 0;
633 }
634
635 static struct bpt *at_breakpoint(unsigned long pc)
636 {
637 int i;
638 struct bpt *bp;
639
640 bp = bpts;
641 for (i = 0; i < NBPTS; ++i, ++bp)
642 if (bp->enabled && pc == bp->address)
643 return bp;
644 return NULL;
645 }
646
647 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
648 {
649 unsigned long off;
650
651 off = nip - (unsigned long) bpts;
652 if (off >= sizeof(bpts))
653 return NULL;
654 off %= sizeof(struct bpt);
655 if (off != offsetof(struct bpt, instr[0])
656 && off != offsetof(struct bpt, instr[1]))
657 return NULL;
658 *offp = off - offsetof(struct bpt, instr[0]);
659 return (struct bpt *) (nip - off);
660 }
661
662 static struct bpt *new_breakpoint(unsigned long a)
663 {
664 struct bpt *bp;
665
666 a &= ~3UL;
667 bp = at_breakpoint(a);
668 if (bp)
669 return bp;
670
671 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
672 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
673 bp->address = a;
674 bp->instr[1] = bpinstr;
675 store_inst(&bp->instr[1]);
676 return bp;
677 }
678 }
679
680 printf("Sorry, no free breakpoints. Please clear one first.\n");
681 return NULL;
682 }
683
684 static void insert_bpts(void)
685 {
686 int i;
687 struct bpt *bp;
688
689 bp = bpts;
690 for (i = 0; i < NBPTS; ++i, ++bp) {
691 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
692 continue;
693 if (mread(bp->address, &bp->instr[0], 4) != 4) {
694 printf("Couldn't read instruction at %lx, "
695 "disabling breakpoint there\n", bp->address);
696 bp->enabled = 0;
697 continue;
698 }
699 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
700 printf("Breakpoint at %lx is on an mtmsrd or rfid "
701 "instruction, disabling it\n", bp->address);
702 bp->enabled = 0;
703 continue;
704 }
705 store_inst(&bp->instr[0]);
706 if (bp->enabled & BP_IABR)
707 continue;
708 if (mwrite(bp->address, &bpinstr, 4) != 4) {
709 printf("Couldn't write instruction at %lx, "
710 "disabling breakpoint there\n", bp->address);
711 bp->enabled &= ~BP_TRAP;
712 continue;
713 }
714 store_inst((void *)bp->address);
715 }
716 }
717
718 static void insert_cpu_bpts(void)
719 {
720 if (dabr.enabled)
721 set_dabr(dabr.address | (dabr.enabled & 7));
722 if (iabr && cpu_has_feature(CPU_FTR_IABR))
723 mtspr(SPRN_IABR, iabr->address
724 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
725 }
726
727 static void remove_bpts(void)
728 {
729 int i;
730 struct bpt *bp;
731 unsigned instr;
732
733 bp = bpts;
734 for (i = 0; i < NBPTS; ++i, ++bp) {
735 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
736 continue;
737 if (mread(bp->address, &instr, 4) == 4
738 && instr == bpinstr
739 && mwrite(bp->address, &bp->instr, 4) != 4)
740 printf("Couldn't remove breakpoint at %lx\n",
741 bp->address);
742 else
743 store_inst((void *)bp->address);
744 }
745 }
746
747 static void remove_cpu_bpts(void)
748 {
749 set_dabr(0);
750 if (cpu_has_feature(CPU_FTR_IABR))
751 mtspr(SPRN_IABR, 0);
752 }
753
754 /* Command interpreting routine */
755 static char *last_cmd;
756
757 static int
758 cmds(struct pt_regs *excp)
759 {
760 int cmd = 0;
761
762 last_cmd = NULL;
763 xmon_regs = excp;
764
765 if (!xmon_no_auto_backtrace) {
766 xmon_no_auto_backtrace = 1;
767 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
768 }
769
770 for(;;) {
771 #ifdef CONFIG_SMP
772 printf("%x:", smp_processor_id());
773 #endif /* CONFIG_SMP */
774 printf("mon> ");
775 flush_input();
776 termch = 0;
777 cmd = skipbl();
778 if( cmd == '\n' ) {
779 if (last_cmd == NULL)
780 continue;
781 take_input(last_cmd);
782 last_cmd = NULL;
783 cmd = inchar();
784 }
785 switch (cmd) {
786 case 'm':
787 cmd = inchar();
788 switch (cmd) {
789 case 'm':
790 case 's':
791 case 'd':
792 memops(cmd);
793 break;
794 case 'l':
795 memlocate();
796 break;
797 case 'z':
798 memzcan();
799 break;
800 case 'i':
801 show_mem();
802 break;
803 default:
804 termch = cmd;
805 memex();
806 }
807 break;
808 case 'd':
809 dump();
810 break;
811 case 'l':
812 symbol_lookup();
813 break;
814 case 'r':
815 prregs(excp); /* print regs */
816 break;
817 case 'e':
818 excprint(excp);
819 break;
820 case 'S':
821 super_regs();
822 break;
823 case 't':
824 backtrace(excp);
825 break;
826 case 'f':
827 cacheflush();
828 break;
829 case 's':
830 if (do_spu_cmd() == 0)
831 break;
832 if (do_step(excp))
833 return cmd;
834 break;
835 case 'x':
836 case 'X':
837 return cmd;
838 case EOF:
839 printf(" <no input ...>\n");
840 mdelay(2000);
841 return cmd;
842 case '?':
843 xmon_puts(help_string);
844 break;
845 case 'b':
846 bpt_cmds();
847 break;
848 case 'C':
849 csum();
850 break;
851 case 'c':
852 if (cpu_cmd())
853 return 0;
854 break;
855 case 'z':
856 bootcmds();
857 break;
858 case 'p':
859 proccall();
860 break;
861 #ifdef CONFIG_PPC_STD_MMU
862 case 'u':
863 dump_segments();
864 break;
865 #endif
866 #ifdef CONFIG_4xx
867 case 'u':
868 dump_tlb_44x();
869 break;
870 #endif
871 default:
872 printf("Unrecognized command: ");
873 do {
874 if (' ' < cmd && cmd <= '~')
875 putchar(cmd);
876 else
877 printf("\\x%x", cmd);
878 cmd = inchar();
879 } while (cmd != '\n');
880 printf(" (type ? for help)\n");
881 break;
882 }
883 }
884 }
885
886 /*
887 * Step a single instruction.
888 * Some instructions we emulate, others we execute with MSR_SE set.
889 */
890 static int do_step(struct pt_regs *regs)
891 {
892 unsigned int instr;
893 int stepped;
894
895 /* check we are in 64-bit kernel mode, translation enabled */
896 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
897 if (mread(regs->nip, &instr, 4) == 4) {
898 stepped = emulate_step(regs, instr);
899 if (stepped < 0) {
900 printf("Couldn't single-step %s instruction\n",
901 (IS_RFID(instr)? "rfid": "mtmsrd"));
902 return 0;
903 }
904 if (stepped > 0) {
905 regs->trap = 0xd00 | (regs->trap & 1);
906 printf("stepped to ");
907 xmon_print_symbol(regs->nip, " ", "\n");
908 ppc_inst_dump(regs->nip, 1, 0);
909 return 0;
910 }
911 }
912 }
913 regs->msr |= MSR_SE;
914 return 1;
915 }
916
917 static void bootcmds(void)
918 {
919 int cmd;
920
921 cmd = inchar();
922 if (cmd == 'r')
923 ppc_md.restart(NULL);
924 else if (cmd == 'h')
925 ppc_md.halt();
926 else if (cmd == 'p')
927 ppc_md.power_off();
928 }
929
930 static int cpu_cmd(void)
931 {
932 #ifdef CONFIG_SMP
933 unsigned long cpu;
934 int timeout;
935 int count;
936
937 if (!scanhex(&cpu)) {
938 /* print cpus waiting or in xmon */
939 printf("cpus stopped:");
940 count = 0;
941 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
942 if (cpu_isset(cpu, cpus_in_xmon)) {
943 if (count == 0)
944 printf(" %x", cpu);
945 ++count;
946 } else {
947 if (count > 1)
948 printf("-%x", cpu - 1);
949 count = 0;
950 }
951 }
952 if (count > 1)
953 printf("-%x", NR_CPUS - 1);
954 printf("\n");
955 return 0;
956 }
957 /* try to switch to cpu specified */
958 if (!cpu_isset(cpu, cpus_in_xmon)) {
959 printf("cpu 0x%x isn't in xmon\n", cpu);
960 return 0;
961 }
962 xmon_taken = 0;
963 mb();
964 xmon_owner = cpu;
965 timeout = 10000000;
966 while (!xmon_taken) {
967 if (--timeout == 0) {
968 if (test_and_set_bit(0, &xmon_taken))
969 break;
970 /* take control back */
971 mb();
972 xmon_owner = smp_processor_id();
973 printf("cpu %u didn't take control\n", cpu);
974 return 0;
975 }
976 barrier();
977 }
978 return 1;
979 #else
980 return 0;
981 #endif /* CONFIG_SMP */
982 }
983
984 static unsigned short fcstab[256] = {
985 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
986 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
987 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
988 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
989 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
990 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
991 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
992 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
993 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
994 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
995 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
996 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
997 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
998 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
999 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1000 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1001 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1002 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1003 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1004 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1005 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1006 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1007 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1008 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1009 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1010 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1011 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1012 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1013 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1014 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1015 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1016 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1017 };
1018
1019 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1020
1021 static void
1022 csum(void)
1023 {
1024 unsigned int i;
1025 unsigned short fcs;
1026 unsigned char v;
1027
1028 if (!scanhex(&adrs))
1029 return;
1030 if (!scanhex(&ncsum))
1031 return;
1032 fcs = 0xffff;
1033 for (i = 0; i < ncsum; ++i) {
1034 if (mread(adrs+i, &v, 1) == 0) {
1035 printf("csum stopped at %x\n", adrs+i);
1036 break;
1037 }
1038 fcs = FCS(fcs, v);
1039 }
1040 printf("%x\n", fcs);
1041 }
1042
1043 /*
1044 * Check if this is a suitable place to put a breakpoint.
1045 */
1046 static long check_bp_loc(unsigned long addr)
1047 {
1048 unsigned int instr;
1049
1050 addr &= ~3;
1051 if (!is_kernel_addr(addr)) {
1052 printf("Breakpoints may only be placed at kernel addresses\n");
1053 return 0;
1054 }
1055 if (!mread(addr, &instr, sizeof(instr))) {
1056 printf("Can't read instruction at address %lx\n", addr);
1057 return 0;
1058 }
1059 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1060 printf("Breakpoints may not be placed on mtmsrd or rfid "
1061 "instructions\n");
1062 return 0;
1063 }
1064 return 1;
1065 }
1066
1067 static char *breakpoint_help_string =
1068 "Breakpoint command usage:\n"
1069 "b show breakpoints\n"
1070 "b <addr> [cnt] set breakpoint at given instr addr\n"
1071 "bc clear all breakpoints\n"
1072 "bc <n/addr> clear breakpoint number n or at addr\n"
1073 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1074 "bd <addr> [cnt] set hardware data breakpoint\n"
1075 "";
1076
1077 static void
1078 bpt_cmds(void)
1079 {
1080 int cmd;
1081 unsigned long a;
1082 int mode, i;
1083 struct bpt *bp;
1084 const char badaddr[] = "Only kernel addresses are permitted "
1085 "for breakpoints\n";
1086
1087 cmd = inchar();
1088 switch (cmd) {
1089 #ifndef CONFIG_8xx
1090 case 'd': /* bd - hardware data breakpoint */
1091 mode = 7;
1092 cmd = inchar();
1093 if (cmd == 'r')
1094 mode = 5;
1095 else if (cmd == 'w')
1096 mode = 6;
1097 else
1098 termch = cmd;
1099 dabr.address = 0;
1100 dabr.enabled = 0;
1101 if (scanhex(&dabr.address)) {
1102 if (!is_kernel_addr(dabr.address)) {
1103 printf(badaddr);
1104 break;
1105 }
1106 dabr.address &= ~7;
1107 dabr.enabled = mode | BP_DABR;
1108 }
1109 break;
1110
1111 case 'i': /* bi - hardware instr breakpoint */
1112 if (!cpu_has_feature(CPU_FTR_IABR)) {
1113 printf("Hardware instruction breakpoint "
1114 "not supported on this cpu\n");
1115 break;
1116 }
1117 if (iabr) {
1118 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1119 iabr = NULL;
1120 }
1121 if (!scanhex(&a))
1122 break;
1123 if (!check_bp_loc(a))
1124 break;
1125 bp = new_breakpoint(a);
1126 if (bp != NULL) {
1127 bp->enabled |= BP_IABR | BP_IABR_TE;
1128 iabr = bp;
1129 }
1130 break;
1131 #endif
1132
1133 case 'c':
1134 if (!scanhex(&a)) {
1135 /* clear all breakpoints */
1136 for (i = 0; i < NBPTS; ++i)
1137 bpts[i].enabled = 0;
1138 iabr = NULL;
1139 dabr.enabled = 0;
1140 printf("All breakpoints cleared\n");
1141 break;
1142 }
1143
1144 if (a <= NBPTS && a >= 1) {
1145 /* assume a breakpoint number */
1146 bp = &bpts[a-1]; /* bp nums are 1 based */
1147 } else {
1148 /* assume a breakpoint address */
1149 bp = at_breakpoint(a);
1150 if (bp == NULL) {
1151 printf("No breakpoint at %x\n", a);
1152 break;
1153 }
1154 }
1155
1156 printf("Cleared breakpoint %x (", BP_NUM(bp));
1157 xmon_print_symbol(bp->address, " ", ")\n");
1158 bp->enabled = 0;
1159 break;
1160
1161 default:
1162 termch = cmd;
1163 cmd = skipbl();
1164 if (cmd == '?') {
1165 printf(breakpoint_help_string);
1166 break;
1167 }
1168 termch = cmd;
1169 if (!scanhex(&a)) {
1170 /* print all breakpoints */
1171 printf(" type address\n");
1172 if (dabr.enabled) {
1173 printf(" data "REG" [", dabr.address);
1174 if (dabr.enabled & 1)
1175 printf("r");
1176 if (dabr.enabled & 2)
1177 printf("w");
1178 printf("]\n");
1179 }
1180 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1181 if (!bp->enabled)
1182 continue;
1183 printf("%2x %s ", BP_NUM(bp),
1184 (bp->enabled & BP_IABR)? "inst": "trap");
1185 xmon_print_symbol(bp->address, " ", "\n");
1186 }
1187 break;
1188 }
1189
1190 if (!check_bp_loc(a))
1191 break;
1192 bp = new_breakpoint(a);
1193 if (bp != NULL)
1194 bp->enabled |= BP_TRAP;
1195 break;
1196 }
1197 }
1198
1199 /* Very cheap human name for vector lookup. */
1200 static
1201 const char *getvecname(unsigned long vec)
1202 {
1203 char *ret;
1204
1205 switch (vec) {
1206 case 0x100: ret = "(System Reset)"; break;
1207 case 0x200: ret = "(Machine Check)"; break;
1208 case 0x300: ret = "(Data Access)"; break;
1209 case 0x380: ret = "(Data SLB Access)"; break;
1210 case 0x400: ret = "(Instruction Access)"; break;
1211 case 0x480: ret = "(Instruction SLB Access)"; break;
1212 case 0x500: ret = "(Hardware Interrupt)"; break;
1213 case 0x600: ret = "(Alignment)"; break;
1214 case 0x700: ret = "(Program Check)"; break;
1215 case 0x800: ret = "(FPU Unavailable)"; break;
1216 case 0x900: ret = "(Decrementer)"; break;
1217 case 0xc00: ret = "(System Call)"; break;
1218 case 0xd00: ret = "(Single Step)"; break;
1219 case 0xf00: ret = "(Performance Monitor)"; break;
1220 case 0xf20: ret = "(Altivec Unavailable)"; break;
1221 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1222 default: ret = "";
1223 }
1224 return ret;
1225 }
1226
1227 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1228 unsigned long *endp)
1229 {
1230 unsigned long size, offset;
1231 const char *name;
1232
1233 *startp = *endp = 0;
1234 if (pc == 0)
1235 return;
1236 if (setjmp(bus_error_jmp) == 0) {
1237 catch_memory_errors = 1;
1238 sync();
1239 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1240 if (name != NULL) {
1241 *startp = pc - offset;
1242 *endp = pc - offset + size;
1243 }
1244 sync();
1245 }
1246 catch_memory_errors = 0;
1247 }
1248
1249 static int xmon_depth_to_print = 64;
1250
1251 #define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1252 #define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1253
1254 #ifdef __powerpc64__
1255 #define REGS_OFFSET 0x70
1256 #else
1257 #define REGS_OFFSET 16
1258 #endif
1259
1260 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1261 unsigned long pc)
1262 {
1263 unsigned long ip;
1264 unsigned long newsp;
1265 unsigned long marker;
1266 int count = 0;
1267 struct pt_regs regs;
1268
1269 do {
1270 if (sp < PAGE_OFFSET) {
1271 if (sp != 0)
1272 printf("SP (%lx) is in userspace\n", sp);
1273 break;
1274 }
1275
1276 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1277 || !mread(sp, &newsp, sizeof(unsigned long))) {
1278 printf("Couldn't read stack frame at %lx\n", sp);
1279 break;
1280 }
1281
1282 /*
1283 * For the first stack frame, try to work out if
1284 * LR and/or the saved LR value in the bottommost
1285 * stack frame are valid.
1286 */
1287 if ((pc | lr) != 0) {
1288 unsigned long fnstart, fnend;
1289 unsigned long nextip;
1290 int printip = 1;
1291
1292 get_function_bounds(pc, &fnstart, &fnend);
1293 nextip = 0;
1294 if (newsp > sp)
1295 mread(newsp + LRSAVE_OFFSET, &nextip,
1296 sizeof(unsigned long));
1297 if (lr == ip) {
1298 if (lr < PAGE_OFFSET
1299 || (fnstart <= lr && lr < fnend))
1300 printip = 0;
1301 } else if (lr == nextip) {
1302 printip = 0;
1303 } else if (lr >= PAGE_OFFSET
1304 && !(fnstart <= lr && lr < fnend)) {
1305 printf("[link register ] ");
1306 xmon_print_symbol(lr, " ", "\n");
1307 }
1308 if (printip) {
1309 printf("["REG"] ", sp);
1310 xmon_print_symbol(ip, " ", " (unreliable)\n");
1311 }
1312 pc = lr = 0;
1313
1314 } else {
1315 printf("["REG"] ", sp);
1316 xmon_print_symbol(ip, " ", "\n");
1317 }
1318
1319 /* Look for "regshere" marker to see if this is
1320 an exception frame. */
1321 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1322 && marker == STACK_FRAME_REGS_MARKER) {
1323 if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
1324 != sizeof(regs)) {
1325 printf("Couldn't read registers at %lx\n",
1326 sp + REGS_OFFSET);
1327 break;
1328 }
1329 printf("--- Exception: %lx %s at ", regs.trap,
1330 getvecname(TRAP(&regs)));
1331 pc = regs.nip;
1332 lr = regs.link;
1333 xmon_print_symbol(pc, " ", "\n");
1334 }
1335
1336 if (newsp == 0)
1337 break;
1338
1339 sp = newsp;
1340 } while (count++ < xmon_depth_to_print);
1341 }
1342
1343 static void backtrace(struct pt_regs *excp)
1344 {
1345 unsigned long sp;
1346
1347 if (scanhex(&sp))
1348 xmon_show_stack(sp, 0, 0);
1349 else
1350 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1351 scannl();
1352 }
1353
1354 static void print_bug_trap(struct pt_regs *regs)
1355 {
1356 #ifdef CONFIG_BUG
1357 const struct bug_entry *bug;
1358 unsigned long addr;
1359
1360 if (regs->msr & MSR_PR)
1361 return; /* not in kernel */
1362 addr = regs->nip; /* address of trap instruction */
1363 if (addr < PAGE_OFFSET)
1364 return;
1365 bug = find_bug(regs->nip);
1366 if (bug == NULL)
1367 return;
1368 if (is_warning_bug(bug))
1369 return;
1370
1371 #ifdef CONFIG_DEBUG_BUGVERBOSE
1372 printf("kernel BUG at %s:%u!\n",
1373 bug->file, bug->line);
1374 #else
1375 printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
1376 #endif
1377 #endif /* CONFIG_BUG */
1378 }
1379
1380 static void excprint(struct pt_regs *fp)
1381 {
1382 unsigned long trap;
1383
1384 #ifdef CONFIG_SMP
1385 printf("cpu 0x%x: ", smp_processor_id());
1386 #endif /* CONFIG_SMP */
1387
1388 trap = TRAP(fp);
1389 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1390 printf(" pc: ");
1391 xmon_print_symbol(fp->nip, ": ", "\n");
1392
1393 printf(" lr: ", fp->link);
1394 xmon_print_symbol(fp->link, ": ", "\n");
1395
1396 printf(" sp: %lx\n", fp->gpr[1]);
1397 printf(" msr: %lx\n", fp->msr);
1398
1399 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1400 printf(" dar: %lx\n", fp->dar);
1401 if (trap != 0x380)
1402 printf(" dsisr: %lx\n", fp->dsisr);
1403 }
1404
1405 printf(" current = 0x%lx\n", current);
1406 #ifdef CONFIG_PPC64
1407 printf(" paca = 0x%lx\n", get_paca());
1408 #endif
1409 if (current) {
1410 printf(" pid = %ld, comm = %s\n",
1411 current->pid, current->comm);
1412 }
1413
1414 if (trap == 0x700)
1415 print_bug_trap(fp);
1416 }
1417
1418 static void prregs(struct pt_regs *fp)
1419 {
1420 int n, trap;
1421 unsigned long base;
1422 struct pt_regs regs;
1423
1424 if (scanhex(&base)) {
1425 if (setjmp(bus_error_jmp) == 0) {
1426 catch_memory_errors = 1;
1427 sync();
1428 regs = *(struct pt_regs *)base;
1429 sync();
1430 __delay(200);
1431 } else {
1432 catch_memory_errors = 0;
1433 printf("*** Error reading registers from "REG"\n",
1434 base);
1435 return;
1436 }
1437 catch_memory_errors = 0;
1438 fp = &regs;
1439 }
1440
1441 #ifdef CONFIG_PPC64
1442 if (FULL_REGS(fp)) {
1443 for (n = 0; n < 16; ++n)
1444 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1445 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1446 } else {
1447 for (n = 0; n < 7; ++n)
1448 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1449 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1450 }
1451 #else
1452 for (n = 0; n < 32; ++n) {
1453 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1454 (n & 3) == 3? "\n": " ");
1455 if (n == 12 && !FULL_REGS(fp)) {
1456 printf("\n");
1457 break;
1458 }
1459 }
1460 #endif
1461 printf("pc = ");
1462 xmon_print_symbol(fp->nip, " ", "\n");
1463 printf("lr = ");
1464 xmon_print_symbol(fp->link, " ", "\n");
1465 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1466 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1467 fp->ctr, fp->xer, fp->trap);
1468 trap = TRAP(fp);
1469 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1470 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1471 }
1472
1473 static void cacheflush(void)
1474 {
1475 int cmd;
1476 unsigned long nflush;
1477
1478 cmd = inchar();
1479 if (cmd != 'i')
1480 termch = cmd;
1481 scanhex((void *)&adrs);
1482 if (termch != '\n')
1483 termch = 0;
1484 nflush = 1;
1485 scanhex(&nflush);
1486 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1487 if (setjmp(bus_error_jmp) == 0) {
1488 catch_memory_errors = 1;
1489 sync();
1490
1491 if (cmd != 'i') {
1492 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1493 cflush((void *) adrs);
1494 } else {
1495 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1496 cinval((void *) adrs);
1497 }
1498 sync();
1499 /* wait a little while to see if we get a machine check */
1500 __delay(200);
1501 }
1502 catch_memory_errors = 0;
1503 }
1504
1505 static unsigned long
1506 read_spr(int n)
1507 {
1508 unsigned int instrs[2];
1509 unsigned long (*code)(void);
1510 unsigned long ret = -1UL;
1511 #ifdef CONFIG_PPC64
1512 unsigned long opd[3];
1513
1514 opd[0] = (unsigned long)instrs;
1515 opd[1] = 0;
1516 opd[2] = 0;
1517 code = (unsigned long (*)(void)) opd;
1518 #else
1519 code = (unsigned long (*)(void)) instrs;
1520 #endif
1521
1522 /* mfspr r3,n; blr */
1523 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1524 instrs[1] = 0x4e800020;
1525 store_inst(instrs);
1526 store_inst(instrs+1);
1527
1528 if (setjmp(bus_error_jmp) == 0) {
1529 catch_memory_errors = 1;
1530 sync();
1531
1532 ret = code();
1533
1534 sync();
1535 /* wait a little while to see if we get a machine check */
1536 __delay(200);
1537 n = size;
1538 }
1539
1540 return ret;
1541 }
1542
1543 static void
1544 write_spr(int n, unsigned long val)
1545 {
1546 unsigned int instrs[2];
1547 unsigned long (*code)(unsigned long);
1548 #ifdef CONFIG_PPC64
1549 unsigned long opd[3];
1550
1551 opd[0] = (unsigned long)instrs;
1552 opd[1] = 0;
1553 opd[2] = 0;
1554 code = (unsigned long (*)(unsigned long)) opd;
1555 #else
1556 code = (unsigned long (*)(unsigned long)) instrs;
1557 #endif
1558
1559 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1560 instrs[1] = 0x4e800020;
1561 store_inst(instrs);
1562 store_inst(instrs+1);
1563
1564 if (setjmp(bus_error_jmp) == 0) {
1565 catch_memory_errors = 1;
1566 sync();
1567
1568 code(val);
1569
1570 sync();
1571 /* wait a little while to see if we get a machine check */
1572 __delay(200);
1573 n = size;
1574 }
1575 }
1576
1577 static unsigned long regno;
1578 extern char exc_prolog;
1579 extern char dec_exc;
1580
1581 static void super_regs(void)
1582 {
1583 int cmd;
1584 unsigned long val;
1585
1586 cmd = skipbl();
1587 if (cmd == '\n') {
1588 unsigned long sp, toc;
1589 asm("mr %0,1" : "=r" (sp) :);
1590 asm("mr %0,2" : "=r" (toc) :);
1591
1592 printf("msr = "REG" sprg0= "REG"\n",
1593 mfmsr(), mfspr(SPRN_SPRG0));
1594 printf("pvr = "REG" sprg1= "REG"\n",
1595 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1596 printf("dec = "REG" sprg2= "REG"\n",
1597 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1598 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1599 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1600 #ifdef CONFIG_PPC_ISERIES
1601 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
1602 struct paca_struct *ptrPaca;
1603 struct lppaca *ptrLpPaca;
1604
1605 /* Dump out relevant Paca data areas. */
1606 printf("Paca: \n");
1607 ptrPaca = get_paca();
1608
1609 printf(" Local Processor Control Area (LpPaca): \n");
1610 ptrLpPaca = ptrPaca->lppaca_ptr;
1611 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1612 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1613 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1614 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1615 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1616 }
1617 #endif
1618
1619 return;
1620 }
1621
1622 scanhex(&regno);
1623 switch (cmd) {
1624 case 'w':
1625 val = read_spr(regno);
1626 scanhex(&val);
1627 write_spr(regno, val);
1628 /* fall through */
1629 case 'r':
1630 printf("spr %lx = %lx\n", regno, read_spr(regno));
1631 break;
1632 }
1633 scannl();
1634 }
1635
1636 /*
1637 * Stuff for reading and writing memory safely
1638 */
1639 static int
1640 mread(unsigned long adrs, void *buf, int size)
1641 {
1642 volatile int n;
1643 char *p, *q;
1644
1645 n = 0;
1646 if (setjmp(bus_error_jmp) == 0) {
1647 catch_memory_errors = 1;
1648 sync();
1649 p = (char *)adrs;
1650 q = (char *)buf;
1651 switch (size) {
1652 case 2:
1653 *(u16 *)q = *(u16 *)p;
1654 break;
1655 case 4:
1656 *(u32 *)q = *(u32 *)p;
1657 break;
1658 case 8:
1659 *(u64 *)q = *(u64 *)p;
1660 break;
1661 default:
1662 for( ; n < size; ++n) {
1663 *q++ = *p++;
1664 sync();
1665 }
1666 }
1667 sync();
1668 /* wait a little while to see if we get a machine check */
1669 __delay(200);
1670 n = size;
1671 }
1672 catch_memory_errors = 0;
1673 return n;
1674 }
1675
1676 static int
1677 mwrite(unsigned long adrs, void *buf, int size)
1678 {
1679 volatile int n;
1680 char *p, *q;
1681
1682 n = 0;
1683 if (setjmp(bus_error_jmp) == 0) {
1684 catch_memory_errors = 1;
1685 sync();
1686 p = (char *) adrs;
1687 q = (char *) buf;
1688 switch (size) {
1689 case 2:
1690 *(u16 *)p = *(u16 *)q;
1691 break;
1692 case 4:
1693 *(u32 *)p = *(u32 *)q;
1694 break;
1695 case 8:
1696 *(u64 *)p = *(u64 *)q;
1697 break;
1698 default:
1699 for ( ; n < size; ++n) {
1700 *p++ = *q++;
1701 sync();
1702 }
1703 }
1704 sync();
1705 /* wait a little while to see if we get a machine check */
1706 __delay(200);
1707 n = size;
1708 } else {
1709 printf("*** Error writing address %x\n", adrs + n);
1710 }
1711 catch_memory_errors = 0;
1712 return n;
1713 }
1714
1715 static int fault_type;
1716 static int fault_except;
1717 static char *fault_chars[] = { "--", "**", "##" };
1718
1719 static int handle_fault(struct pt_regs *regs)
1720 {
1721 fault_except = TRAP(regs);
1722 switch (TRAP(regs)) {
1723 case 0x200:
1724 fault_type = 0;
1725 break;
1726 case 0x300:
1727 case 0x380:
1728 fault_type = 1;
1729 break;
1730 default:
1731 fault_type = 2;
1732 }
1733
1734 longjmp(bus_error_jmp, 1);
1735
1736 return 0;
1737 }
1738
1739 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1740
1741 static void
1742 byterev(unsigned char *val, int size)
1743 {
1744 int t;
1745
1746 switch (size) {
1747 case 2:
1748 SWAP(val[0], val[1], t);
1749 break;
1750 case 4:
1751 SWAP(val[0], val[3], t);
1752 SWAP(val[1], val[2], t);
1753 break;
1754 case 8: /* is there really any use for this? */
1755 SWAP(val[0], val[7], t);
1756 SWAP(val[1], val[6], t);
1757 SWAP(val[2], val[5], t);
1758 SWAP(val[3], val[4], t);
1759 break;
1760 }
1761 }
1762
1763 static int brev;
1764 static int mnoread;
1765
1766 static char *memex_help_string =
1767 "Memory examine command usage:\n"
1768 "m [addr] [flags] examine/change memory\n"
1769 " addr is optional. will start where left off.\n"
1770 " flags may include chars from this set:\n"
1771 " b modify by bytes (default)\n"
1772 " w modify by words (2 byte)\n"
1773 " l modify by longs (4 byte)\n"
1774 " d modify by doubleword (8 byte)\n"
1775 " r toggle reverse byte order mode\n"
1776 " n do not read memory (for i/o spaces)\n"
1777 " . ok to read (default)\n"
1778 "NOTE: flags are saved as defaults\n"
1779 "";
1780
1781 static char *memex_subcmd_help_string =
1782 "Memory examine subcommands:\n"
1783 " hexval write this val to current location\n"
1784 " 'string' write chars from string to this location\n"
1785 " ' increment address\n"
1786 " ^ decrement address\n"
1787 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1788 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1789 " ` clear no-read flag\n"
1790 " ; stay at this addr\n"
1791 " v change to byte mode\n"
1792 " w change to word (2 byte) mode\n"
1793 " l change to long (4 byte) mode\n"
1794 " u change to doubleword (8 byte) mode\n"
1795 " m addr change current addr\n"
1796 " n toggle no-read flag\n"
1797 " r toggle byte reverse flag\n"
1798 " < count back up count bytes\n"
1799 " > count skip forward count bytes\n"
1800 " x exit this mode\n"
1801 "";
1802
1803 static void
1804 memex(void)
1805 {
1806 int cmd, inc, i, nslash;
1807 unsigned long n;
1808 unsigned char val[16];
1809
1810 scanhex((void *)&adrs);
1811 cmd = skipbl();
1812 if (cmd == '?') {
1813 printf(memex_help_string);
1814 return;
1815 } else {
1816 termch = cmd;
1817 }
1818 last_cmd = "m\n";
1819 while ((cmd = skipbl()) != '\n') {
1820 switch( cmd ){
1821 case 'b': size = 1; break;
1822 case 'w': size = 2; break;
1823 case 'l': size = 4; break;
1824 case 'd': size = 8; break;
1825 case 'r': brev = !brev; break;
1826 case 'n': mnoread = 1; break;
1827 case '.': mnoread = 0; break;
1828 }
1829 }
1830 if( size <= 0 )
1831 size = 1;
1832 else if( size > 8 )
1833 size = 8;
1834 for(;;){
1835 if (!mnoread)
1836 n = mread(adrs, val, size);
1837 printf(REG"%c", adrs, brev? 'r': ' ');
1838 if (!mnoread) {
1839 if (brev)
1840 byterev(val, size);
1841 putchar(' ');
1842 for (i = 0; i < n; ++i)
1843 printf("%.2x", val[i]);
1844 for (; i < size; ++i)
1845 printf("%s", fault_chars[fault_type]);
1846 }
1847 putchar(' ');
1848 inc = size;
1849 nslash = 0;
1850 for(;;){
1851 if( scanhex(&n) ){
1852 for (i = 0; i < size; ++i)
1853 val[i] = n >> (i * 8);
1854 if (!brev)
1855 byterev(val, size);
1856 mwrite(adrs, val, size);
1857 inc = size;
1858 }
1859 cmd = skipbl();
1860 if (cmd == '\n')
1861 break;
1862 inc = 0;
1863 switch (cmd) {
1864 case '\'':
1865 for(;;){
1866 n = inchar();
1867 if( n == '\\' )
1868 n = bsesc();
1869 else if( n == '\'' )
1870 break;
1871 for (i = 0; i < size; ++i)
1872 val[i] = n >> (i * 8);
1873 if (!brev)
1874 byterev(val, size);
1875 mwrite(adrs, val, size);
1876 adrs += size;
1877 }
1878 adrs -= size;
1879 inc = size;
1880 break;
1881 case ',':
1882 adrs += size;
1883 break;
1884 case '.':
1885 mnoread = 0;
1886 break;
1887 case ';':
1888 break;
1889 case 'x':
1890 case EOF:
1891 scannl();
1892 return;
1893 case 'b':
1894 case 'v':
1895 size = 1;
1896 break;
1897 case 'w':
1898 size = 2;
1899 break;
1900 case 'l':
1901 size = 4;
1902 break;
1903 case 'u':
1904 size = 8;
1905 break;
1906 case '^':
1907 adrs -= size;
1908 break;
1909 break;
1910 case '/':
1911 if (nslash > 0)
1912 adrs -= 1 << nslash;
1913 else
1914 nslash = 0;
1915 nslash += 4;
1916 adrs += 1 << nslash;
1917 break;
1918 case '\\':
1919 if (nslash < 0)
1920 adrs += 1 << -nslash;
1921 else
1922 nslash = 0;
1923 nslash -= 4;
1924 adrs -= 1 << -nslash;
1925 break;
1926 case 'm':
1927 scanhex((void *)&adrs);
1928 break;
1929 case 'n':
1930 mnoread = 1;
1931 break;
1932 case 'r':
1933 brev = !brev;
1934 break;
1935 case '<':
1936 n = size;
1937 scanhex(&n);
1938 adrs -= n;
1939 break;
1940 case '>':
1941 n = size;
1942 scanhex(&n);
1943 adrs += n;
1944 break;
1945 case '?':
1946 printf(memex_subcmd_help_string);
1947 break;
1948 }
1949 }
1950 adrs += inc;
1951 }
1952 }
1953
1954 static int
1955 bsesc(void)
1956 {
1957 int c;
1958
1959 c = inchar();
1960 switch( c ){
1961 case 'n': c = '\n'; break;
1962 case 'r': c = '\r'; break;
1963 case 'b': c = '\b'; break;
1964 case 't': c = '\t'; break;
1965 }
1966 return c;
1967 }
1968
1969 static void xmon_rawdump (unsigned long adrs, long ndump)
1970 {
1971 long n, m, r, nr;
1972 unsigned char temp[16];
1973
1974 for (n = ndump; n > 0;) {
1975 r = n < 16? n: 16;
1976 nr = mread(adrs, temp, r);
1977 adrs += nr;
1978 for (m = 0; m < r; ++m) {
1979 if (m < nr)
1980 printf("%.2x", temp[m]);
1981 else
1982 printf("%s", fault_chars[fault_type]);
1983 }
1984 n -= r;
1985 if (nr < r)
1986 break;
1987 }
1988 printf("\n");
1989 }
1990
1991 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1992 || ('a' <= (c) && (c) <= 'f') \
1993 || ('A' <= (c) && (c) <= 'F'))
1994 static void
1995 dump(void)
1996 {
1997 int c;
1998
1999 c = inchar();
2000 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2001 termch = c;
2002 scanhex((void *)&adrs);
2003 if (termch != '\n')
2004 termch = 0;
2005 if (c == 'i') {
2006 scanhex(&nidump);
2007 if (nidump == 0)
2008 nidump = 16;
2009 else if (nidump > MAX_DUMP)
2010 nidump = MAX_DUMP;
2011 adrs += ppc_inst_dump(adrs, nidump, 1);
2012 last_cmd = "di\n";
2013 } else if (c == 'r') {
2014 scanhex(&ndump);
2015 if (ndump == 0)
2016 ndump = 64;
2017 xmon_rawdump(adrs, ndump);
2018 adrs += ndump;
2019 last_cmd = "dr\n";
2020 } else {
2021 scanhex(&ndump);
2022 if (ndump == 0)
2023 ndump = 64;
2024 else if (ndump > MAX_DUMP)
2025 ndump = MAX_DUMP;
2026 prdump(adrs, ndump);
2027 adrs += ndump;
2028 last_cmd = "d\n";
2029 }
2030 }
2031
2032 static void
2033 prdump(unsigned long adrs, long ndump)
2034 {
2035 long n, m, c, r, nr;
2036 unsigned char temp[16];
2037
2038 for (n = ndump; n > 0;) {
2039 printf(REG, adrs);
2040 putchar(' ');
2041 r = n < 16? n: 16;
2042 nr = mread(adrs, temp, r);
2043 adrs += nr;
2044 for (m = 0; m < r; ++m) {
2045 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2046 putchar(' ');
2047 if (m < nr)
2048 printf("%.2x", temp[m]);
2049 else
2050 printf("%s", fault_chars[fault_type]);
2051 }
2052 for (; m < 16; ++m) {
2053 if ((m & (sizeof(long) - 1)) == 0)
2054 putchar(' ');
2055 printf(" ");
2056 }
2057 printf(" |");
2058 for (m = 0; m < r; ++m) {
2059 if (m < nr) {
2060 c = temp[m];
2061 putchar(' ' <= c && c <= '~'? c: '.');
2062 } else
2063 putchar(' ');
2064 }
2065 n -= r;
2066 for (; m < 16; ++m)
2067 putchar(' ');
2068 printf("|\n");
2069 if (nr < r)
2070 break;
2071 }
2072 }
2073
2074 typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2075
2076 static int
2077 generic_inst_dump(unsigned long adr, long count, int praddr,
2078 instruction_dump_func dump_func)
2079 {
2080 int nr, dotted;
2081 unsigned long first_adr;
2082 unsigned long inst, last_inst = 0;
2083 unsigned char val[4];
2084
2085 dotted = 0;
2086 for (first_adr = adr; count > 0; --count, adr += 4) {
2087 nr = mread(adr, val, 4);
2088 if (nr == 0) {
2089 if (praddr) {
2090 const char *x = fault_chars[fault_type];
2091 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2092 }
2093 break;
2094 }
2095 inst = GETWORD(val);
2096 if (adr > first_adr && inst == last_inst) {
2097 if (!dotted) {
2098 printf(" ...\n");
2099 dotted = 1;
2100 }
2101 continue;
2102 }
2103 dotted = 0;
2104 last_inst = inst;
2105 if (praddr)
2106 printf(REG" %.8x", adr, inst);
2107 printf("\t");
2108 dump_func(inst, adr);
2109 printf("\n");
2110 }
2111 return adr - first_adr;
2112 }
2113
2114 static int
2115 ppc_inst_dump(unsigned long adr, long count, int praddr)
2116 {
2117 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2118 }
2119
2120 void
2121 print_address(unsigned long addr)
2122 {
2123 xmon_print_symbol(addr, "\t# ", "");
2124 }
2125
2126
2127 /*
2128 * Memory operations - move, set, print differences
2129 */
2130 static unsigned long mdest; /* destination address */
2131 static unsigned long msrc; /* source address */
2132 static unsigned long mval; /* byte value to set memory to */
2133 static unsigned long mcount; /* # bytes to affect */
2134 static unsigned long mdiffs; /* max # differences to print */
2135
2136 static void
2137 memops(int cmd)
2138 {
2139 scanhex((void *)&mdest);
2140 if( termch != '\n' )
2141 termch = 0;
2142 scanhex((void *)(cmd == 's'? &mval: &msrc));
2143 if( termch != '\n' )
2144 termch = 0;
2145 scanhex((void *)&mcount);
2146 switch( cmd ){
2147 case 'm':
2148 memmove((void *)mdest, (void *)msrc, mcount);
2149 break;
2150 case 's':
2151 memset((void *)mdest, mval, mcount);
2152 break;
2153 case 'd':
2154 if( termch != '\n' )
2155 termch = 0;
2156 scanhex((void *)&mdiffs);
2157 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2158 break;
2159 }
2160 }
2161
2162 static void
2163 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2164 {
2165 unsigned n, prt;
2166
2167 prt = 0;
2168 for( n = nb; n > 0; --n )
2169 if( *p1++ != *p2++ )
2170 if( ++prt <= maxpr )
2171 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2172 p1[-1], p2 - 1, p2[-1]);
2173 if( prt > maxpr )
2174 printf("Total of %d differences\n", prt);
2175 }
2176
2177 static unsigned mend;
2178 static unsigned mask;
2179
2180 static void
2181 memlocate(void)
2182 {
2183 unsigned a, n;
2184 unsigned char val[4];
2185
2186 last_cmd = "ml";
2187 scanhex((void *)&mdest);
2188 if (termch != '\n') {
2189 termch = 0;
2190 scanhex((void *)&mend);
2191 if (termch != '\n') {
2192 termch = 0;
2193 scanhex((void *)&mval);
2194 mask = ~0;
2195 if (termch != '\n') termch = 0;
2196 scanhex((void *)&mask);
2197 }
2198 }
2199 n = 0;
2200 for (a = mdest; a < mend; a += 4) {
2201 if (mread(a, val, 4) == 4
2202 && ((GETWORD(val) ^ mval) & mask) == 0) {
2203 printf("%.16x: %.16x\n", a, GETWORD(val));
2204 if (++n >= 10)
2205 break;
2206 }
2207 }
2208 }
2209
2210 static unsigned long mskip = 0x1000;
2211 static unsigned long mlim = 0xffffffff;
2212
2213 static void
2214 memzcan(void)
2215 {
2216 unsigned char v;
2217 unsigned a;
2218 int ok, ook;
2219
2220 scanhex(&mdest);
2221 if (termch != '\n') termch = 0;
2222 scanhex(&mskip);
2223 if (termch != '\n') termch = 0;
2224 scanhex(&mlim);
2225 ook = 0;
2226 for (a = mdest; a < mlim; a += mskip) {
2227 ok = mread(a, &v, 1);
2228 if (ok && !ook) {
2229 printf("%.8x .. ", a);
2230 } else if (!ok && ook)
2231 printf("%.8x\n", a - mskip);
2232 ook = ok;
2233 if (a + mskip < a)
2234 break;
2235 }
2236 if (ook)
2237 printf("%.8x\n", a - mskip);
2238 }
2239
2240 static void proccall(void)
2241 {
2242 unsigned long args[8];
2243 unsigned long ret;
2244 int i;
2245 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2246 unsigned long, unsigned long, unsigned long,
2247 unsigned long, unsigned long, unsigned long);
2248 callfunc_t func;
2249
2250 if (!scanhex(&adrs))
2251 return;
2252 if (termch != '\n')
2253 termch = 0;
2254 for (i = 0; i < 8; ++i)
2255 args[i] = 0;
2256 for (i = 0; i < 8; ++i) {
2257 if (!scanhex(&args[i]) || termch == '\n')
2258 break;
2259 termch = 0;
2260 }
2261 func = (callfunc_t) adrs;
2262 ret = 0;
2263 if (setjmp(bus_error_jmp) == 0) {
2264 catch_memory_errors = 1;
2265 sync();
2266 ret = func(args[0], args[1], args[2], args[3],
2267 args[4], args[5], args[6], args[7]);
2268 sync();
2269 printf("return value is %x\n", ret);
2270 } else {
2271 printf("*** %x exception occurred\n", fault_except);
2272 }
2273 catch_memory_errors = 0;
2274 }
2275
2276 /* Input scanning routines */
2277 int
2278 skipbl(void)
2279 {
2280 int c;
2281
2282 if( termch != 0 ){
2283 c = termch;
2284 termch = 0;
2285 } else
2286 c = inchar();
2287 while( c == ' ' || c == '\t' )
2288 c = inchar();
2289 return c;
2290 }
2291
2292 #define N_PTREGS 44
2293 static char *regnames[N_PTREGS] = {
2294 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2295 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2296 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2297 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2298 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2299 #ifdef CONFIG_PPC64
2300 "softe",
2301 #else
2302 "mq",
2303 #endif
2304 "trap", "dar", "dsisr", "res"
2305 };
2306
2307 int
2308 scanhex(unsigned long *vp)
2309 {
2310 int c, d;
2311 unsigned long v;
2312
2313 c = skipbl();
2314 if (c == '%') {
2315 /* parse register name */
2316 char regname[8];
2317 int i;
2318
2319 for (i = 0; i < sizeof(regname) - 1; ++i) {
2320 c = inchar();
2321 if (!isalnum(c)) {
2322 termch = c;
2323 break;
2324 }
2325 regname[i] = c;
2326 }
2327 regname[i] = 0;
2328 for (i = 0; i < N_PTREGS; ++i) {
2329 if (strcmp(regnames[i], regname) == 0) {
2330 if (xmon_regs == NULL) {
2331 printf("regs not available\n");
2332 return 0;
2333 }
2334 *vp = ((unsigned long *)xmon_regs)[i];
2335 return 1;
2336 }
2337 }
2338 printf("invalid register name '%%%s'\n", regname);
2339 return 0;
2340 }
2341
2342 /* skip leading "0x" if any */
2343
2344 if (c == '0') {
2345 c = inchar();
2346 if (c == 'x') {
2347 c = inchar();
2348 } else {
2349 d = hexdigit(c);
2350 if (d == EOF) {
2351 termch = c;
2352 *vp = 0;
2353 return 1;
2354 }
2355 }
2356 } else if (c == '$') {
2357 int i;
2358 for (i=0; i<63; i++) {
2359 c = inchar();
2360 if (isspace(c)) {
2361 termch = c;
2362 break;
2363 }
2364 tmpstr[i] = c;
2365 }
2366 tmpstr[i++] = 0;
2367 *vp = 0;
2368 if (setjmp(bus_error_jmp) == 0) {
2369 catch_memory_errors = 1;
2370 sync();
2371 *vp = kallsyms_lookup_name(tmpstr);
2372 sync();
2373 }
2374 catch_memory_errors = 0;
2375 if (!(*vp)) {
2376 printf("unknown symbol '%s'\n", tmpstr);
2377 return 0;
2378 }
2379 return 1;
2380 }
2381
2382 d = hexdigit(c);
2383 if (d == EOF) {
2384 termch = c;
2385 return 0;
2386 }
2387 v = 0;
2388 do {
2389 v = (v << 4) + d;
2390 c = inchar();
2391 d = hexdigit(c);
2392 } while (d != EOF);
2393 termch = c;
2394 *vp = v;
2395 return 1;
2396 }
2397
2398 static void
2399 scannl(void)
2400 {
2401 int c;
2402
2403 c = termch;
2404 termch = 0;
2405 while( c != '\n' )
2406 c = inchar();
2407 }
2408
2409 static int hexdigit(int c)
2410 {
2411 if( '0' <= c && c <= '9' )
2412 return c - '0';
2413 if( 'A' <= c && c <= 'F' )
2414 return c - ('A' - 10);
2415 if( 'a' <= c && c <= 'f' )
2416 return c - ('a' - 10);
2417 return EOF;
2418 }
2419
2420 void
2421 getstring(char *s, int size)
2422 {
2423 int c;
2424
2425 c = skipbl();
2426 do {
2427 if( size > 1 ){
2428 *s++ = c;
2429 --size;
2430 }
2431 c = inchar();
2432 } while( c != ' ' && c != '\t' && c != '\n' );
2433 termch = c;
2434 *s = 0;
2435 }
2436
2437 static char line[256];
2438 static char *lineptr;
2439
2440 static void
2441 flush_input(void)
2442 {
2443 lineptr = NULL;
2444 }
2445
2446 static int
2447 inchar(void)
2448 {
2449 if (lineptr == NULL || *lineptr == 0) {
2450 if (xmon_gets(line, sizeof(line)) == NULL) {
2451 lineptr = NULL;
2452 return EOF;
2453 }
2454 lineptr = line;
2455 }
2456 return *lineptr++;
2457 }
2458
2459 static void
2460 take_input(char *str)
2461 {
2462 lineptr = str;
2463 }
2464
2465
2466 static void
2467 symbol_lookup(void)
2468 {
2469 int type = inchar();
2470 unsigned long addr;
2471 static char tmp[64];
2472
2473 switch (type) {
2474 case 'a':
2475 if (scanhex(&addr))
2476 xmon_print_symbol(addr, ": ", "\n");
2477 termch = 0;
2478 break;
2479 case 's':
2480 getstring(tmp, 64);
2481 if (setjmp(bus_error_jmp) == 0) {
2482 catch_memory_errors = 1;
2483 sync();
2484 addr = kallsyms_lookup_name(tmp);
2485 if (addr)
2486 printf("%s: %lx\n", tmp, addr);
2487 else
2488 printf("Symbol '%s' not found.\n", tmp);
2489 sync();
2490 }
2491 catch_memory_errors = 0;
2492 termch = 0;
2493 break;
2494 }
2495 }
2496
2497
2498 /* Print an address in numeric and symbolic form (if possible) */
2499 static void xmon_print_symbol(unsigned long address, const char *mid,
2500 const char *after)
2501 {
2502 char *modname;
2503 const char *name = NULL;
2504 unsigned long offset, size;
2505
2506 printf(REG, address);
2507 if (setjmp(bus_error_jmp) == 0) {
2508 catch_memory_errors = 1;
2509 sync();
2510 name = kallsyms_lookup(address, &size, &offset, &modname,
2511 tmpstr);
2512 sync();
2513 /* wait a little while to see if we get a machine check */
2514 __delay(200);
2515 }
2516
2517 catch_memory_errors = 0;
2518
2519 if (name) {
2520 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2521 if (modname)
2522 printf(" [%s]", modname);
2523 }
2524 printf("%s", after);
2525 }
2526
2527 #ifdef CONFIG_PPC64
2528 static void dump_slb(void)
2529 {
2530 int i;
2531 unsigned long esid,vsid,valid;
2532 unsigned long llp;
2533
2534 printf("SLB contents of cpu %x\n", smp_processor_id());
2535
2536 for (i = 0; i < mmu_slb_size; i++) {
2537 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
2538 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
2539 valid = (esid & SLB_ESID_V);
2540 if (valid | esid | vsid) {
2541 printf("%02d %016lx %016lx", i, esid, vsid);
2542 if (valid) {
2543 llp = vsid & SLB_VSID_LLP;
2544 if (vsid & SLB_VSID_B_1T) {
2545 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
2546 GET_ESID_1T(esid),
2547 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2548 llp);
2549 } else {
2550 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
2551 GET_ESID(esid),
2552 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2553 llp);
2554 }
2555 } else
2556 printf("\n");
2557 }
2558 }
2559 }
2560
2561 static void dump_stab(void)
2562 {
2563 int i;
2564 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2565
2566 printf("Segment table contents of cpu %x\n", smp_processor_id());
2567
2568 for (i = 0; i < PAGE_SIZE/16; i++) {
2569 unsigned long a, b;
2570
2571 a = *tmp++;
2572 b = *tmp++;
2573
2574 if (a || b) {
2575 printf("%03d %016lx ", i, a);
2576 printf("%016lx\n", b);
2577 }
2578 }
2579 }
2580
2581 void dump_segments(void)
2582 {
2583 if (cpu_has_feature(CPU_FTR_SLB))
2584 dump_slb();
2585 else
2586 dump_stab();
2587 }
2588 #endif
2589
2590 #ifdef CONFIG_PPC_STD_MMU_32
2591 void dump_segments(void)
2592 {
2593 int i;
2594
2595 printf("sr0-15 =");
2596 for (i = 0; i < 16; ++i)
2597 printf(" %x", mfsrin(i));
2598 printf("\n");
2599 }
2600 #endif
2601
2602 #ifdef CONFIG_44x
2603 static void dump_tlb_44x(void)
2604 {
2605 int i;
2606
2607 for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2608 unsigned long w0,w1,w2;
2609 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
2610 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
2611 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
2612 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2613 if (w0 & PPC44x_TLB_VALID) {
2614 printf("V %08x -> %01x%08x %c%c%c%c%c",
2615 w0 & PPC44x_TLB_EPN_MASK,
2616 w1 & PPC44x_TLB_ERPN_MASK,
2617 w1 & PPC44x_TLB_RPN_MASK,
2618 (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2619 (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2620 (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2621 (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2622 (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2623 }
2624 printf("\n");
2625 }
2626 }
2627 #endif /* CONFIG_44x */
2628
2629 static void xmon_init(int enable)
2630 {
2631 #ifdef CONFIG_PPC_ISERIES
2632 if (firmware_has_feature(FW_FEATURE_ISERIES))
2633 return;
2634 #endif
2635 if (enable) {
2636 __debugger = xmon;
2637 __debugger_ipi = xmon_ipi;
2638 __debugger_bpt = xmon_bpt;
2639 __debugger_sstep = xmon_sstep;
2640 __debugger_iabr_match = xmon_iabr_match;
2641 __debugger_dabr_match = xmon_dabr_match;
2642 __debugger_fault_handler = xmon_fault_handler;
2643 } else {
2644 __debugger = NULL;
2645 __debugger_ipi = NULL;
2646 __debugger_bpt = NULL;
2647 __debugger_sstep = NULL;
2648 __debugger_iabr_match = NULL;
2649 __debugger_dabr_match = NULL;
2650 __debugger_fault_handler = NULL;
2651 }
2652 xmon_map_scc();
2653 }
2654
2655 #ifdef CONFIG_MAGIC_SYSRQ
2656 static void sysrq_handle_xmon(int key, struct tty_struct *tty)
2657 {
2658 /* ensure xmon is enabled */
2659 xmon_init(1);
2660 debugger(get_irq_regs());
2661 }
2662
2663 static struct sysrq_key_op sysrq_xmon_op =
2664 {
2665 .handler = sysrq_handle_xmon,
2666 .help_msg = "Xmon",
2667 .action_msg = "Entering xmon",
2668 };
2669
2670 static int __init setup_xmon_sysrq(void)
2671 {
2672 #ifdef CONFIG_PPC_ISERIES
2673 if (firmware_has_feature(FW_FEATURE_ISERIES))
2674 return 0;
2675 #endif
2676 register_sysrq_key('x', &sysrq_xmon_op);
2677 return 0;
2678 }
2679 __initcall(setup_xmon_sysrq);
2680 #endif /* CONFIG_MAGIC_SYSRQ */
2681
2682 static int __initdata xmon_early, xmon_off;
2683
2684 static int __init early_parse_xmon(char *p)
2685 {
2686 if (!p || strncmp(p, "early", 5) == 0) {
2687 /* just "xmon" is equivalent to "xmon=early" */
2688 xmon_init(1);
2689 xmon_early = 1;
2690 } else if (strncmp(p, "on", 2) == 0)
2691 xmon_init(1);
2692 else if (strncmp(p, "off", 3) == 0)
2693 xmon_off = 1;
2694 else if (strncmp(p, "nobt", 4) == 0)
2695 xmon_no_auto_backtrace = 1;
2696 else
2697 return 1;
2698
2699 return 0;
2700 }
2701 early_param("xmon", early_parse_xmon);
2702
2703 void __init xmon_setup(void)
2704 {
2705 #ifdef CONFIG_XMON_DEFAULT
2706 if (!xmon_off)
2707 xmon_init(1);
2708 #endif
2709 if (xmon_early)
2710 debugger(NULL);
2711 }
2712
2713 #ifdef CONFIG_SPU_BASE
2714
2715 struct spu_info {
2716 struct spu *spu;
2717 u64 saved_mfc_sr1_RW;
2718 u32 saved_spu_runcntl_RW;
2719 unsigned long dump_addr;
2720 u8 stopped_ok;
2721 };
2722
2723 #define XMON_NUM_SPUS 16 /* Enough for current hardware */
2724
2725 static struct spu_info spu_info[XMON_NUM_SPUS];
2726
2727 void xmon_register_spus(struct list_head *list)
2728 {
2729 struct spu *spu;
2730
2731 list_for_each_entry(spu, list, full_list) {
2732 if (spu->number >= XMON_NUM_SPUS) {
2733 WARN_ON(1);
2734 continue;
2735 }
2736
2737 spu_info[spu->number].spu = spu;
2738 spu_info[spu->number].stopped_ok = 0;
2739 spu_info[spu->number].dump_addr = (unsigned long)
2740 spu_info[spu->number].spu->local_store;
2741 }
2742 }
2743
2744 static void stop_spus(void)
2745 {
2746 struct spu *spu;
2747 int i;
2748 u64 tmp;
2749
2750 for (i = 0; i < XMON_NUM_SPUS; i++) {
2751 if (!spu_info[i].spu)
2752 continue;
2753
2754 if (setjmp(bus_error_jmp) == 0) {
2755 catch_memory_errors = 1;
2756 sync();
2757
2758 spu = spu_info[i].spu;
2759
2760 spu_info[i].saved_spu_runcntl_RW =
2761 in_be32(&spu->problem->spu_runcntl_RW);
2762
2763 tmp = spu_mfc_sr1_get(spu);
2764 spu_info[i].saved_mfc_sr1_RW = tmp;
2765
2766 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2767 spu_mfc_sr1_set(spu, tmp);
2768
2769 sync();
2770 __delay(200);
2771
2772 spu_info[i].stopped_ok = 1;
2773
2774 printf("Stopped spu %.2d (was %s)\n", i,
2775 spu_info[i].saved_spu_runcntl_RW ?
2776 "running" : "stopped");
2777 } else {
2778 catch_memory_errors = 0;
2779 printf("*** Error stopping spu %.2d\n", i);
2780 }
2781 catch_memory_errors = 0;
2782 }
2783 }
2784
2785 static void restart_spus(void)
2786 {
2787 struct spu *spu;
2788 int i;
2789
2790 for (i = 0; i < XMON_NUM_SPUS; i++) {
2791 if (!spu_info[i].spu)
2792 continue;
2793
2794 if (!spu_info[i].stopped_ok) {
2795 printf("*** Error, spu %d was not successfully stopped"
2796 ", not restarting\n", i);
2797 continue;
2798 }
2799
2800 if (setjmp(bus_error_jmp) == 0) {
2801 catch_memory_errors = 1;
2802 sync();
2803
2804 spu = spu_info[i].spu;
2805 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
2806 out_be32(&spu->problem->spu_runcntl_RW,
2807 spu_info[i].saved_spu_runcntl_RW);
2808
2809 sync();
2810 __delay(200);
2811
2812 printf("Restarted spu %.2d\n", i);
2813 } else {
2814 catch_memory_errors = 0;
2815 printf("*** Error restarting spu %.2d\n", i);
2816 }
2817 catch_memory_errors = 0;
2818 }
2819 }
2820
2821 #define DUMP_WIDTH 23
2822 #define DUMP_VALUE(format, field, value) \
2823 do { \
2824 if (setjmp(bus_error_jmp) == 0) { \
2825 catch_memory_errors = 1; \
2826 sync(); \
2827 printf(" %-*s = "format"\n", DUMP_WIDTH, \
2828 #field, value); \
2829 sync(); \
2830 __delay(200); \
2831 } else { \
2832 catch_memory_errors = 0; \
2833 printf(" %-*s = *** Error reading field.\n", \
2834 DUMP_WIDTH, #field); \
2835 } \
2836 catch_memory_errors = 0; \
2837 } while (0)
2838
2839 #define DUMP_FIELD(obj, format, field) \
2840 DUMP_VALUE(format, field, obj->field)
2841
2842 static void dump_spu_fields(struct spu *spu)
2843 {
2844 printf("Dumping spu fields at address %p:\n", spu);
2845
2846 DUMP_FIELD(spu, "0x%x", number);
2847 DUMP_FIELD(spu, "%s", name);
2848 DUMP_FIELD(spu, "0x%lx", local_store_phys);
2849 DUMP_FIELD(spu, "0x%p", local_store);
2850 DUMP_FIELD(spu, "0x%lx", ls_size);
2851 DUMP_FIELD(spu, "0x%x", node);
2852 DUMP_FIELD(spu, "0x%lx", flags);
2853 DUMP_FIELD(spu, "%d", class_0_pending);
2854 DUMP_FIELD(spu, "0x%lx", class_0_dar);
2855 DUMP_FIELD(spu, "0x%lx", class_1_dar);
2856 DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
2857 DUMP_FIELD(spu, "0x%lx", irqs[0]);
2858 DUMP_FIELD(spu, "0x%lx", irqs[1]);
2859 DUMP_FIELD(spu, "0x%lx", irqs[2]);
2860 DUMP_FIELD(spu, "0x%x", slb_replace);
2861 DUMP_FIELD(spu, "%d", pid);
2862 DUMP_FIELD(spu, "0x%p", mm);
2863 DUMP_FIELD(spu, "0x%p", ctx);
2864 DUMP_FIELD(spu, "0x%p", rq);
2865 DUMP_FIELD(spu, "0x%p", timestamp);
2866 DUMP_FIELD(spu, "0x%lx", problem_phys);
2867 DUMP_FIELD(spu, "0x%p", problem);
2868 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
2869 in_be32(&spu->problem->spu_runcntl_RW));
2870 DUMP_VALUE("0x%x", problem->spu_status_R,
2871 in_be32(&spu->problem->spu_status_R));
2872 DUMP_VALUE("0x%x", problem->spu_npc_RW,
2873 in_be32(&spu->problem->spu_npc_RW));
2874 DUMP_FIELD(spu, "0x%p", priv2);
2875 DUMP_FIELD(spu, "0x%p", pdata);
2876 }
2877
2878 int
2879 spu_inst_dump(unsigned long adr, long count, int praddr)
2880 {
2881 return generic_inst_dump(adr, count, praddr, print_insn_spu);
2882 }
2883
2884 static void dump_spu_ls(unsigned long num, int subcmd)
2885 {
2886 unsigned long offset, addr, ls_addr;
2887
2888 if (setjmp(bus_error_jmp) == 0) {
2889 catch_memory_errors = 1;
2890 sync();
2891 ls_addr = (unsigned long)spu_info[num].spu->local_store;
2892 sync();
2893 __delay(200);
2894 } else {
2895 catch_memory_errors = 0;
2896 printf("*** Error: accessing spu info for spu %d\n", num);
2897 return;
2898 }
2899 catch_memory_errors = 0;
2900
2901 if (scanhex(&offset))
2902 addr = ls_addr + offset;
2903 else
2904 addr = spu_info[num].dump_addr;
2905
2906 if (addr >= ls_addr + LS_SIZE) {
2907 printf("*** Error: address outside of local store\n");
2908 return;
2909 }
2910
2911 switch (subcmd) {
2912 case 'i':
2913 addr += spu_inst_dump(addr, 16, 1);
2914 last_cmd = "sdi\n";
2915 break;
2916 default:
2917 prdump(addr, 64);
2918 addr += 64;
2919 last_cmd = "sd\n";
2920 break;
2921 }
2922
2923 spu_info[num].dump_addr = addr;
2924 }
2925
2926 static int do_spu_cmd(void)
2927 {
2928 static unsigned long num = 0;
2929 int cmd, subcmd = 0;
2930
2931 cmd = inchar();
2932 switch (cmd) {
2933 case 's':
2934 stop_spus();
2935 break;
2936 case 'r':
2937 restart_spus();
2938 break;
2939 case 'd':
2940 subcmd = inchar();
2941 if (isxdigit(subcmd) || subcmd == '\n')
2942 termch = subcmd;
2943 case 'f':
2944 scanhex(&num);
2945 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
2946 printf("*** Error: invalid spu number\n");
2947 return 0;
2948 }
2949
2950 switch (cmd) {
2951 case 'f':
2952 dump_spu_fields(spu_info[num].spu);
2953 break;
2954 default:
2955 dump_spu_ls(num, subcmd);
2956 break;
2957 }
2958
2959 break;
2960 default:
2961 return -1;
2962 }
2963
2964 return 0;
2965 }
2966 #else /* ! CONFIG_SPU_BASE */
2967 static int do_spu_cmd(void)
2968 {
2969 return -1;
2970 }
2971 #endif
This page took 0.089734 seconds and 6 git commands to generate.