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