Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / ppc64 / xmon / xmon.c
blob3c0ccb2623aeba4e89e9b43c439bf0c4ceafe1cd
1 /*
2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996 Paul Mackerras.
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.
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>
21 #include <asm/ptrace.h>
22 #include <asm/string.h>
23 #include <asm/prom.h>
24 #include <asm/machdep.h>
25 #include <asm/processor.h>
26 #include <asm/pgtable.h>
27 #include <asm/mmu.h>
28 #include <asm/mmu_context.h>
29 #include <asm/paca.h>
30 #include <asm/ppcdebug.h>
31 #include <asm/cputable.h>
32 #include <asm/rtas.h>
33 #include <asm/sstep.h>
34 #include <asm/bug.h>
35 #include <asm/hvcall.h>
37 #include "nonstdio.h"
38 #include "privinst.h"
40 #define scanhex xmon_scanhex
41 #define skipbl xmon_skipbl
43 #ifdef CONFIG_SMP
44 cpumask_t cpus_in_xmon = CPU_MASK_NONE;
45 static unsigned long xmon_taken = 1;
46 static int xmon_owner;
47 static int xmon_gate;
48 #endif /* CONFIG_SMP */
50 static unsigned long in_xmon = 0;
52 static unsigned long adrs;
53 static int size = 1;
54 #define MAX_DUMP (128 * 1024)
55 static unsigned long ndump = 64;
56 static unsigned long nidump = 16;
57 static unsigned long ncsum = 4096;
58 static int termch;
59 static char tmpstr[128];
61 #define JMP_BUF_LEN (184/sizeof(long))
62 static long bus_error_jmp[JMP_BUF_LEN];
63 static int catch_memory_errors;
64 static long *xmon_fault_jmp[NR_CPUS];
65 #define setjmp xmon_setjmp
66 #define longjmp xmon_longjmp
68 /* Breakpoint stuff */
69 struct bpt {
70 unsigned long address;
71 unsigned int instr[2];
72 atomic_t ref_count;
73 int enabled;
74 unsigned long pad;
77 /* Bits in bpt.enabled */
78 #define BP_IABR_TE 1 /* IABR translation enabled */
79 #define BP_IABR 2
80 #define BP_TRAP 8
81 #define BP_DABR 0x10
83 #define NBPTS 256
84 static struct bpt bpts[NBPTS];
85 static struct bpt dabr;
86 static struct bpt *iabr;
87 static unsigned bpinstr = 0x7fe00008; /* trap */
89 #define BP_NUM(bp) ((bp) - bpts + 1)
91 /* Prototypes */
92 static int cmds(struct pt_regs *);
93 static int mread(unsigned long, void *, int);
94 static int mwrite(unsigned long, void *, int);
95 static int handle_fault(struct pt_regs *);
96 static void byterev(unsigned char *, int);
97 static void memex(void);
98 static int bsesc(void);
99 static void dump(void);
100 static void prdump(unsigned long, long);
101 static int ppc_inst_dump(unsigned long, long, int);
102 void print_address(unsigned long);
103 static void backtrace(struct pt_regs *);
104 static void excprint(struct pt_regs *);
105 static void prregs(struct pt_regs *);
106 static void memops(int);
107 static void memlocate(void);
108 static void memzcan(void);
109 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
110 int skipbl(void);
111 int scanhex(unsigned long *valp);
112 static void scannl(void);
113 static int hexdigit(int);
114 void getstring(char *, int);
115 static void flush_input(void);
116 static int inchar(void);
117 static void take_input(char *);
118 static unsigned long read_spr(int);
119 static void write_spr(int, unsigned long);
120 static void super_regs(void);
121 static void remove_bpts(void);
122 static void insert_bpts(void);
123 static void remove_cpu_bpts(void);
124 static void insert_cpu_bpts(void);
125 static struct bpt *at_breakpoint(unsigned long pc);
126 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
127 static int do_step(struct pt_regs *);
128 static void bpt_cmds(void);
129 static void cacheflush(void);
130 static int cpu_cmd(void);
131 static void csum(void);
132 static void bootcmds(void);
133 void dump_segments(void);
134 static void symbol_lookup(void);
135 static void xmon_print_symbol(unsigned long address, const char *mid,
136 const char *after);
137 static const char *getvecname(unsigned long vec);
139 static void debug_trace(void);
141 extern int print_insn_powerpc(unsigned long, unsigned long, int);
142 extern void printf(const char *fmt, ...);
143 extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
144 extern int xmon_putc(int c, void *f);
145 extern int putchar(int ch);
146 extern int xmon_read_poll(void);
147 extern int setjmp(long *);
148 extern void longjmp(long *, int);
149 extern unsigned long _ASR;
151 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
153 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
154 || ('a' <= (c) && (c) <= 'f') \
155 || ('A' <= (c) && (c) <= 'F'))
156 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
157 || ('a' <= (c) && (c) <= 'z') \
158 || ('A' <= (c) && (c) <= 'Z'))
159 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
161 static char *help_string = "\
162 Commands:\n\
163 b show breakpoints\n\
164 bd set data breakpoint\n\
165 bi set instruction breakpoint\n\
166 bc clear breakpoint\n"
167 #ifdef CONFIG_SMP
169 c print cpus stopped in xmon\n\
170 c# try to switch to cpu number h (in hex)\n"
171 #endif
173 C checksum\n\
174 d dump bytes\n\
175 di dump instructions\n\
176 df dump float values\n\
177 dd dump double values\n\
178 e print exception information\n\
179 f flush cache\n\
180 la lookup symbol+offset of specified address\n\
181 ls lookup address of specified symbol\n\
182 m examine/change memory\n\
183 mm move a block of memory\n\
184 ms set a block of memory\n\
185 md compare two blocks of memory\n\
186 ml locate a block of memory\n\
187 mz zero a block of memory\n\
188 mi show information about memory allocation\n\
189 p show the task list\n\
190 r print registers\n\
191 s single step\n\
192 S print special registers\n\
193 t print backtrace\n\
194 T Enable/Disable PPCDBG flags\n\
195 x exit monitor and recover\n\
196 X exit monitor and dont recover\n\
197 u dump segment table or SLB\n\
198 ? help\n"
200 zr reboot\n\
201 zh halt\n"
204 static struct pt_regs *xmon_regs;
206 extern inline void sync(void)
208 asm volatile("sync; isync");
211 /* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs).
212 A PPC stack frame looks like this:
214 High Address
215 Back Chain
216 FP reg save area
217 GP reg save area
218 Local var space
219 Parameter save area (SP+48)
220 TOC save area (SP+40)
221 link editor doubleword (SP+32)
222 compiler doubleword (SP+24)
223 LR save (SP+16)
224 CR save (SP+8)
225 Back Chain (SP+0)
227 Note that the LR (ret addr) may not be saved in the current frame if
228 no functions have been called from the current function.
232 * Disable surveillance (the service processor watchdog function)
233 * while we are in xmon.
234 * XXX we should re-enable it when we leave. :)
236 #define SURVEILLANCE_TOKEN 9000
238 static inline void disable_surveillance(void)
240 #ifdef CONFIG_PPC_PSERIES
241 /* Since this can't be a module, args should end up below 4GB. */
242 static struct rtas_args args;
245 * At this point we have got all the cpus we can into
246 * xmon, so there is hopefully no other cpu calling RTAS
247 * at the moment, even though we don't take rtas.lock.
248 * If we did try to take rtas.lock there would be a
249 * real possibility of deadlock.
251 args.token = rtas_token("set-indicator");
252 if (args.token == RTAS_UNKNOWN_SERVICE)
253 return;
254 args.nargs = 3;
255 args.nret = 1;
256 args.rets = &args.args[3];
257 args.args[0] = SURVEILLANCE_TOKEN;
258 args.args[1] = 0;
259 args.args[2] = 0;
260 enter_rtas(__pa(&args));
261 #endif /* CONFIG_PPC_PSERIES */
264 #ifdef CONFIG_SMP
265 static int xmon_speaker;
267 static void get_output_lock(void)
269 int me = smp_processor_id() + 0x100;
270 int last_speaker = 0, prev;
271 long timeout;
273 if (xmon_speaker == me)
274 return;
275 for (;;) {
276 if (xmon_speaker == 0) {
277 last_speaker = cmpxchg(&xmon_speaker, 0, me);
278 if (last_speaker == 0)
279 return;
281 timeout = 10000000;
282 while (xmon_speaker == last_speaker) {
283 if (--timeout > 0)
284 continue;
285 /* hostile takeover */
286 prev = cmpxchg(&xmon_speaker, last_speaker, me);
287 if (prev == last_speaker)
288 return;
289 break;
294 static void release_output_lock(void)
296 xmon_speaker = 0;
298 #endif
300 int xmon_core(struct pt_regs *regs, int fromipi)
302 int cmd = 0;
303 unsigned long msr;
304 struct bpt *bp;
305 long recurse_jmp[JMP_BUF_LEN];
306 unsigned long offset;
307 #ifdef CONFIG_SMP
308 int cpu;
309 int secondary;
310 unsigned long timeout;
311 #endif
313 msr = get_msr();
314 set_msrd(msr & ~MSR_EE); /* disable interrupts */
316 bp = in_breakpoint_table(regs->nip, &offset);
317 if (bp != NULL) {
318 regs->nip = bp->address + offset;
319 atomic_dec(&bp->ref_count);
322 remove_cpu_bpts();
324 #ifdef CONFIG_SMP
325 cpu = smp_processor_id();
326 if (cpu_isset(cpu, cpus_in_xmon)) {
327 get_output_lock();
328 excprint(regs);
329 printf("cpu 0x%x: Exception %lx %s in xmon, "
330 "returning to main loop\n",
331 cpu, regs->trap, getvecname(TRAP(regs)));
332 longjmp(xmon_fault_jmp[cpu], 1);
335 if (setjmp(recurse_jmp) != 0) {
336 if (!in_xmon || !xmon_gate) {
337 printf("xmon: WARNING: bad recursive fault "
338 "on cpu 0x%x\n", cpu);
339 goto waiting;
341 secondary = !(xmon_taken && cpu == xmon_owner);
342 goto cmdloop;
345 xmon_fault_jmp[cpu] = recurse_jmp;
346 cpu_set(cpu, cpus_in_xmon);
348 bp = NULL;
349 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
350 bp = at_breakpoint(regs->nip);
351 if (bp || (regs->msr & MSR_RI) == 0)
352 fromipi = 0;
354 if (!fromipi) {
355 get_output_lock();
356 excprint(regs);
357 if (bp) {
358 printf("cpu 0x%x stopped at breakpoint 0x%x (",
359 cpu, BP_NUM(bp));
360 xmon_print_symbol(regs->nip, " ", ")\n");
362 if ((regs->msr & MSR_RI) == 0)
363 printf("WARNING: exception is not recoverable, "
364 "can't continue\n");
365 release_output_lock();
368 waiting:
369 secondary = 1;
370 while (secondary && !xmon_gate) {
371 if (in_xmon == 0) {
372 if (fromipi)
373 goto leave;
374 secondary = test_and_set_bit(0, &in_xmon);
376 barrier();
379 if (!secondary && !xmon_gate) {
380 /* we are the first cpu to come in */
381 /* interrupt other cpu(s) */
382 int ncpus = num_online_cpus();
384 xmon_owner = cpu;
385 mb();
386 if (ncpus > 1) {
387 smp_send_debugger_break(MSG_ALL_BUT_SELF);
388 /* wait for other cpus to come in */
389 for (timeout = 100000000; timeout != 0; --timeout) {
390 if (cpus_weight(cpus_in_xmon) >= ncpus)
391 break;
392 barrier();
395 remove_bpts();
396 disable_surveillance();
397 /* for breakpoint or single step, print the current instr. */
398 if (bp || TRAP(regs) == 0xd00)
399 ppc_inst_dump(regs->nip, 1, 0);
400 printf("enter ? for help\n");
401 mb();
402 xmon_gate = 1;
403 barrier();
406 cmdloop:
407 while (in_xmon) {
408 if (secondary) {
409 if (cpu == xmon_owner) {
410 if (!test_and_set_bit(0, &xmon_taken)) {
411 secondary = 0;
412 continue;
414 /* missed it */
415 while (cpu == xmon_owner)
416 barrier();
418 barrier();
419 } else {
420 cmd = cmds(regs);
421 if (cmd != 0) {
422 /* exiting xmon */
423 insert_bpts();
424 xmon_gate = 0;
425 wmb();
426 in_xmon = 0;
427 break;
429 /* have switched to some other cpu */
430 secondary = 1;
433 leave:
434 cpu_clear(cpu, cpus_in_xmon);
435 xmon_fault_jmp[cpu] = NULL;
437 #else
438 /* UP is simple... */
439 if (in_xmon) {
440 printf("Exception %lx %s in xmon, returning to main loop\n",
441 regs->trap, getvecname(TRAP(regs)));
442 longjmp(xmon_fault_jmp[0], 1);
444 if (setjmp(recurse_jmp) == 0) {
445 xmon_fault_jmp[0] = recurse_jmp;
446 in_xmon = 1;
448 excprint(regs);
449 bp = at_breakpoint(regs->nip);
450 if (bp) {
451 printf("Stopped at breakpoint %x (", BP_NUM(bp));
452 xmon_print_symbol(regs->nip, " ", ")\n");
454 if ((regs->msr & MSR_RI) == 0)
455 printf("WARNING: exception is not recoverable, "
456 "can't continue\n");
457 remove_bpts();
458 disable_surveillance();
459 /* for breakpoint or single step, print the current instr. */
460 if (bp || TRAP(regs) == 0xd00)
461 ppc_inst_dump(regs->nip, 1, 0);
462 printf("enter ? for help\n");
465 cmd = cmds(regs);
467 insert_bpts();
468 in_xmon = 0;
469 #endif
471 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
472 bp = at_breakpoint(regs->nip);
473 if (bp != NULL) {
474 int stepped = emulate_step(regs, bp->instr[0]);
475 if (stepped == 0) {
476 regs->nip = (unsigned long) &bp->instr[0];
477 atomic_inc(&bp->ref_count);
478 } else if (stepped < 0) {
479 printf("Couldn't single-step %s instruction\n",
480 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
485 insert_cpu_bpts();
487 set_msrd(msr); /* restore interrupt enable */
489 return cmd != 'X';
492 int xmon(struct pt_regs *excp)
494 struct pt_regs regs;
496 if (excp == NULL) {
497 /* Ok, grab regs as they are now.
498 This won't do a particularily good job because the
499 prologue has already been executed.
500 ToDo: We could reach back into the callers save
501 area to do a better job of representing the
502 caller's state.
504 asm volatile ("std 0,0(%0)\n\
505 std 1,8(%0)\n\
506 std 2,16(%0)\n\
507 std 3,24(%0)\n\
508 std 4,32(%0)\n\
509 std 5,40(%0)\n\
510 std 6,48(%0)\n\
511 std 7,56(%0)\n\
512 std 8,64(%0)\n\
513 std 9,72(%0)\n\
514 std 10,80(%0)\n\
515 std 11,88(%0)\n\
516 std 12,96(%0)\n\
517 std 13,104(%0)\n\
518 std 14,112(%0)\n\
519 std 15,120(%0)\n\
520 std 16,128(%0)\n\
521 std 17,136(%0)\n\
522 std 18,144(%0)\n\
523 std 19,152(%0)\n\
524 std 20,160(%0)\n\
525 std 21,168(%0)\n\
526 std 22,176(%0)\n\
527 std 23,184(%0)\n\
528 std 24,192(%0)\n\
529 std 25,200(%0)\n\
530 std 26,208(%0)\n\
531 std 27,216(%0)\n\
532 std 28,224(%0)\n\
533 std 29,232(%0)\n\
534 std 30,240(%0)\n\
535 std 31,248(%0)" : : "b" (&regs));
537 regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
538 regs.msr = get_msr();
539 regs.ctr = get_ctr();
540 regs.xer = get_xer();
541 regs.ccr = get_cr();
542 regs.trap = 0;
543 excp = &regs;
545 return xmon_core(excp, 0);
548 int xmon_bpt(struct pt_regs *regs)
550 struct bpt *bp;
551 unsigned long offset;
553 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
554 return 0;
556 /* Are we at the trap at bp->instr[1] for some bp? */
557 bp = in_breakpoint_table(regs->nip, &offset);
558 if (bp != NULL && offset == 4) {
559 regs->nip = bp->address + 4;
560 atomic_dec(&bp->ref_count);
561 return 1;
564 /* Are we at a breakpoint? */
565 bp = at_breakpoint(regs->nip);
566 if (!bp)
567 return 0;
569 xmon_core(regs, 0);
571 return 1;
574 int xmon_sstep(struct pt_regs *regs)
576 if (user_mode(regs))
577 return 0;
578 xmon_core(regs, 0);
579 return 1;
582 int xmon_dabr_match(struct pt_regs *regs)
584 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
585 return 0;
586 xmon_core(regs, 0);
587 return 1;
590 int xmon_iabr_match(struct pt_regs *regs)
592 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
593 return 0;
594 if (iabr == 0)
595 return 0;
596 xmon_core(regs, 0);
597 return 1;
600 int xmon_ipi(struct pt_regs *regs)
602 #ifdef CONFIG_SMP
603 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
604 xmon_core(regs, 1);
605 #endif
606 return 0;
609 int xmon_fault_handler(struct pt_regs *regs)
611 struct bpt *bp;
612 unsigned long offset;
614 if (in_xmon && catch_memory_errors)
615 handle_fault(regs); /* doesn't return */
617 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
618 bp = in_breakpoint_table(regs->nip, &offset);
619 if (bp != NULL) {
620 regs->nip = bp->address + offset;
621 atomic_dec(&bp->ref_count);
625 return 0;
628 /* On systems with a hypervisor, we can't set the DABR
629 (data address breakpoint register) directly. */
630 static void set_controlled_dabr(unsigned long val)
632 #ifdef CONFIG_PPC_PSERIES
633 if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
634 int rc = plpar_hcall_norets(H_SET_DABR, val);
635 if (rc != H_Success)
636 xmon_printf("Warning: setting DABR failed (%d)\n", rc);
637 } else
638 #endif
639 set_dabr(val);
642 static struct bpt *at_breakpoint(unsigned long pc)
644 int i;
645 struct bpt *bp;
647 bp = bpts;
648 for (i = 0; i < NBPTS; ++i, ++bp)
649 if (bp->enabled && pc == bp->address)
650 return bp;
651 return NULL;
654 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
656 unsigned long off;
658 off = nip - (unsigned long) bpts;
659 if (off >= sizeof(bpts))
660 return NULL;
661 off %= sizeof(struct bpt);
662 if (off != offsetof(struct bpt, instr[0])
663 && off != offsetof(struct bpt, instr[1]))
664 return NULL;
665 *offp = off - offsetof(struct bpt, instr[0]);
666 return (struct bpt *) (nip - off);
669 static struct bpt *new_breakpoint(unsigned long a)
671 struct bpt *bp;
673 a &= ~3UL;
674 bp = at_breakpoint(a);
675 if (bp)
676 return bp;
678 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
679 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
680 bp->address = a;
681 bp->instr[1] = bpinstr;
682 store_inst(&bp->instr[1]);
683 return bp;
687 printf("Sorry, no free breakpoints. Please clear one first.\n");
688 return NULL;
691 static void insert_bpts(void)
693 int i;
694 struct bpt *bp;
696 bp = bpts;
697 for (i = 0; i < NBPTS; ++i, ++bp) {
698 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
699 continue;
700 if (mread(bp->address, &bp->instr[0], 4) != 4) {
701 printf("Couldn't read instruction at %lx, "
702 "disabling breakpoint there\n", bp->address);
703 bp->enabled = 0;
704 continue;
706 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
707 printf("Breakpoint at %lx is on an mtmsrd or rfid "
708 "instruction, disabling it\n", bp->address);
709 bp->enabled = 0;
710 continue;
712 store_inst(&bp->instr[0]);
713 if (bp->enabled & BP_IABR)
714 continue;
715 if (mwrite(bp->address, &bpinstr, 4) != 4) {
716 printf("Couldn't write instruction at %lx, "
717 "disabling breakpoint there\n", bp->address);
718 bp->enabled &= ~BP_TRAP;
719 continue;
721 store_inst((void *)bp->address);
725 static void insert_cpu_bpts(void)
727 if (dabr.enabled)
728 set_controlled_dabr(dabr.address | (dabr.enabled & 7));
729 if (iabr && cpu_has_feature(CPU_FTR_IABR))
730 set_iabr(iabr->address
731 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
734 static void remove_bpts(void)
736 int i;
737 struct bpt *bp;
738 unsigned instr;
740 bp = bpts;
741 for (i = 0; i < NBPTS; ++i, ++bp) {
742 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
743 continue;
744 if (mread(bp->address, &instr, 4) == 4
745 && instr == bpinstr
746 && mwrite(bp->address, &bp->instr, 4) != 4)
747 printf("Couldn't remove breakpoint at %lx\n",
748 bp->address);
749 else
750 store_inst((void *)bp->address);
754 static void remove_cpu_bpts(void)
756 set_controlled_dabr(0);
757 if (cpu_has_feature(CPU_FTR_IABR))
758 set_iabr(0);
761 /* Command interpreting routine */
762 static char *last_cmd;
764 static int
765 cmds(struct pt_regs *excp)
767 int cmd = 0;
769 last_cmd = NULL;
770 xmon_regs = excp;
771 for(;;) {
772 #ifdef CONFIG_SMP
773 printf("%x:", smp_processor_id());
774 #endif /* CONFIG_SMP */
775 printf("mon> ");
776 fflush(stdout);
777 flush_input();
778 termch = 0;
779 cmd = skipbl();
780 if( cmd == '\n' ) {
781 if (last_cmd == NULL)
782 continue;
783 take_input(last_cmd);
784 last_cmd = NULL;
785 cmd = inchar();
787 switch (cmd) {
788 case 'm':
789 cmd = inchar();
790 switch (cmd) {
791 case 'm':
792 case 's':
793 case 'd':
794 memops(cmd);
795 break;
796 case 'l':
797 memlocate();
798 break;
799 case 'z':
800 memzcan();
801 break;
802 case 'i':
803 show_mem();
804 break;
805 default:
806 termch = cmd;
807 memex();
809 break;
810 case 'd':
811 dump();
812 break;
813 case 'l':
814 symbol_lookup();
815 break;
816 case 'r':
817 prregs(excp); /* print regs */
818 break;
819 case 'e':
820 excprint(excp);
821 break;
822 case 'S':
823 super_regs();
824 break;
825 case 't':
826 backtrace(excp);
827 break;
828 case 'f':
829 cacheflush();
830 break;
831 case 's':
832 if (do_step(excp))
833 return cmd;
834 break;
835 case 'x':
836 case 'X':
837 case EOF:
838 return cmd;
839 case '?':
840 printf(help_string);
841 break;
842 case 'p':
843 show_state();
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 'T':
859 debug_trace();
860 break;
861 case 'u':
862 dump_segments();
863 break;
864 default:
865 printf("Unrecognized command: ");
866 do {
867 if (' ' < cmd && cmd <= '~')
868 putchar(cmd);
869 else
870 printf("\\x%x", cmd);
871 cmd = inchar();
872 } while (cmd != '\n');
873 printf(" (type ? for help)\n");
874 break;
880 * Step a single instruction.
881 * Some instructions we emulate, others we execute with MSR_SE set.
883 static int do_step(struct pt_regs *regs)
885 unsigned int instr;
886 int stepped;
888 /* check we are in 64-bit kernel mode, translation enabled */
889 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
890 if (mread(regs->nip, &instr, 4) == 4) {
891 stepped = emulate_step(regs, instr);
892 if (stepped < 0) {
893 printf("Couldn't single-step %s instruction\n",
894 (IS_RFID(instr)? "rfid": "mtmsrd"));
895 return 0;
897 if (stepped > 0) {
898 regs->trap = 0xd00 | (regs->trap & 1);
899 printf("stepped to ");
900 xmon_print_symbol(regs->nip, " ", "\n");
901 ppc_inst_dump(regs->nip, 1, 0);
902 return 0;
906 regs->msr |= MSR_SE;
907 return 1;
910 static void bootcmds(void)
912 int cmd;
914 cmd = inchar();
915 if (cmd == 'r')
916 ppc_md.restart(NULL);
917 else if (cmd == 'h')
918 ppc_md.halt();
919 else if (cmd == 'p')
920 ppc_md.power_off();
923 static int cpu_cmd(void)
925 #ifdef CONFIG_SMP
926 unsigned long cpu;
927 int timeout;
928 int count;
930 if (!scanhex(&cpu)) {
931 /* print cpus waiting or in xmon */
932 printf("cpus stopped:");
933 count = 0;
934 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
935 if (cpu_isset(cpu, cpus_in_xmon)) {
936 if (count == 0)
937 printf(" %x", cpu);
938 ++count;
939 } else {
940 if (count > 1)
941 printf("-%x", cpu - 1);
942 count = 0;
945 if (count > 1)
946 printf("-%x", NR_CPUS - 1);
947 printf("\n");
948 return 0;
950 /* try to switch to cpu specified */
951 if (!cpu_isset(cpu, cpus_in_xmon)) {
952 printf("cpu 0x%x isn't in xmon\n", cpu);
953 return 0;
955 xmon_taken = 0;
956 mb();
957 xmon_owner = cpu;
958 timeout = 10000000;
959 while (!xmon_taken) {
960 if (--timeout == 0) {
961 if (test_and_set_bit(0, &xmon_taken))
962 break;
963 /* take control back */
964 mb();
965 xmon_owner = smp_processor_id();
966 printf("cpu %u didn't take control\n", cpu);
967 return 0;
969 barrier();
971 return 1;
972 #else
973 return 0;
974 #endif /* CONFIG_SMP */
977 static unsigned short fcstab[256] = {
978 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
979 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
980 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
981 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
982 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
983 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
984 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
985 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
986 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
987 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
988 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
989 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
990 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
991 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
992 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
993 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
994 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
995 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
996 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
997 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
998 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
999 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1000 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1001 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1002 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1003 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1004 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1005 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1006 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1007 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1008 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1009 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1012 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1014 static void
1015 csum(void)
1017 unsigned int i;
1018 unsigned short fcs;
1019 unsigned char v;
1021 if (!scanhex(&adrs))
1022 return;
1023 if (!scanhex(&ncsum))
1024 return;
1025 fcs = 0xffff;
1026 for (i = 0; i < ncsum; ++i) {
1027 if (mread(adrs+i, &v, 1) == 0) {
1028 printf("csum stopped at %x\n", adrs+i);
1029 break;
1031 fcs = FCS(fcs, v);
1033 printf("%x\n", fcs);
1037 * Check if this is a suitable place to put a breakpoint.
1039 static long check_bp_loc(unsigned long addr)
1041 unsigned int instr;
1043 addr &= ~3;
1044 if (addr < KERNELBASE) {
1045 printf("Breakpoints may only be placed at kernel addresses\n");
1046 return 0;
1048 if (!mread(addr, &instr, sizeof(instr))) {
1049 printf("Can't read instruction at address %lx\n", addr);
1050 return 0;
1052 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1053 printf("Breakpoints may not be placed on mtmsrd or rfid "
1054 "instructions\n");
1055 return 0;
1057 return 1;
1060 static char *breakpoint_help_string =
1061 "Breakpoint command usage:\n"
1062 "b show breakpoints\n"
1063 "b <addr> [cnt] set breakpoint at given instr addr\n"
1064 "bc clear all breakpoints\n"
1065 "bc <n/addr> clear breakpoint number n or at addr\n"
1066 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1067 "bd <addr> [cnt] set hardware data breakpoint\n"
1070 static void
1071 bpt_cmds(void)
1073 int cmd;
1074 unsigned long a;
1075 int mode, i;
1076 struct bpt *bp;
1077 const char badaddr[] = "Only kernel addresses are permitted "
1078 "for breakpoints\n";
1080 cmd = inchar();
1081 switch (cmd) {
1082 case 'd': /* bd - hardware data breakpoint */
1083 mode = 7;
1084 cmd = inchar();
1085 if (cmd == 'r')
1086 mode = 5;
1087 else if (cmd == 'w')
1088 mode = 6;
1089 else
1090 termch = cmd;
1091 dabr.address = 0;
1092 dabr.enabled = 0;
1093 if (scanhex(&dabr.address)) {
1094 if (dabr.address < KERNELBASE) {
1095 printf(badaddr);
1096 break;
1098 dabr.address &= ~7;
1099 dabr.enabled = mode | BP_DABR;
1101 break;
1103 case 'i': /* bi - hardware instr breakpoint */
1104 if (!cpu_has_feature(CPU_FTR_IABR)) {
1105 printf("Hardware instruction breakpoint "
1106 "not supported on this cpu\n");
1107 break;
1109 if (iabr) {
1110 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1111 iabr = NULL;
1113 if (!scanhex(&a))
1114 break;
1115 if (!check_bp_loc(a))
1116 break;
1117 bp = new_breakpoint(a);
1118 if (bp != NULL) {
1119 bp->enabled |= BP_IABR | BP_IABR_TE;
1120 iabr = bp;
1122 break;
1124 case 'c':
1125 if (!scanhex(&a)) {
1126 /* clear all breakpoints */
1127 for (i = 0; i < NBPTS; ++i)
1128 bpts[i].enabled = 0;
1129 iabr = NULL;
1130 dabr.enabled = 0;
1131 printf("All breakpoints cleared\n");
1132 break;
1135 if (a <= NBPTS && a >= 1) {
1136 /* assume a breakpoint number */
1137 bp = &bpts[a-1]; /* bp nums are 1 based */
1138 } else {
1139 /* assume a breakpoint address */
1140 bp = at_breakpoint(a);
1141 if (bp == 0) {
1142 printf("No breakpoint at %x\n", a);
1143 break;
1147 printf("Cleared breakpoint %x (", BP_NUM(bp));
1148 xmon_print_symbol(bp->address, " ", ")\n");
1149 bp->enabled = 0;
1150 break;
1152 default:
1153 termch = cmd;
1154 cmd = skipbl();
1155 if (cmd == '?') {
1156 printf(breakpoint_help_string);
1157 break;
1159 termch = cmd;
1160 if (!scanhex(&a)) {
1161 /* print all breakpoints */
1162 printf(" type address\n");
1163 if (dabr.enabled) {
1164 printf(" data %.16lx [", dabr.address);
1165 if (dabr.enabled & 1)
1166 printf("r");
1167 if (dabr.enabled & 2)
1168 printf("w");
1169 printf("]\n");
1171 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1172 if (!bp->enabled)
1173 continue;
1174 printf("%2x %s ", BP_NUM(bp),
1175 (bp->enabled & BP_IABR)? "inst": "trap");
1176 xmon_print_symbol(bp->address, " ", "\n");
1178 break;
1181 if (!check_bp_loc(a))
1182 break;
1183 bp = new_breakpoint(a);
1184 if (bp != NULL)
1185 bp->enabled |= BP_TRAP;
1186 break;
1190 /* Very cheap human name for vector lookup. */
1191 static
1192 const char *getvecname(unsigned long vec)
1194 char *ret;
1196 switch (vec) {
1197 case 0x100: ret = "(System Reset)"; break;
1198 case 0x200: ret = "(Machine Check)"; break;
1199 case 0x300: ret = "(Data Access)"; break;
1200 case 0x380: ret = "(Data SLB Access)"; break;
1201 case 0x400: ret = "(Instruction Access)"; break;
1202 case 0x480: ret = "(Instruction SLB Access)"; break;
1203 case 0x500: ret = "(Hardware Interrupt)"; break;
1204 case 0x600: ret = "(Alignment)"; break;
1205 case 0x700: ret = "(Program Check)"; break;
1206 case 0x800: ret = "(FPU Unavailable)"; break;
1207 case 0x900: ret = "(Decrementer)"; break;
1208 case 0xc00: ret = "(System Call)"; break;
1209 case 0xd00: ret = "(Single Step)"; break;
1210 case 0xf00: ret = "(Performance Monitor)"; break;
1211 case 0xf20: ret = "(Altivec Unavailable)"; break;
1212 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1213 default: ret = "";
1215 return ret;
1218 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1219 unsigned long *endp)
1221 unsigned long size, offset;
1222 const char *name;
1223 char *modname;
1225 *startp = *endp = 0;
1226 if (pc == 0)
1227 return;
1228 if (setjmp(bus_error_jmp) == 0) {
1229 catch_memory_errors = 1;
1230 sync();
1231 name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
1232 if (name != NULL) {
1233 *startp = pc - offset;
1234 *endp = pc - offset + size;
1236 sync();
1238 catch_memory_errors = 0;
1241 static int xmon_depth_to_print = 64;
1243 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1244 unsigned long pc)
1246 unsigned long ip;
1247 unsigned long newsp;
1248 unsigned long marker;
1249 int count = 0;
1250 struct pt_regs regs;
1252 do {
1253 if (sp < PAGE_OFFSET) {
1254 if (sp != 0)
1255 printf("SP (%lx) is in userspace\n", sp);
1256 break;
1259 if (!mread(sp + 16, &ip, sizeof(unsigned long))
1260 || !mread(sp, &newsp, sizeof(unsigned long))) {
1261 printf("Couldn't read stack frame at %lx\n", sp);
1262 break;
1266 * For the first stack frame, try to work out if
1267 * LR and/or the saved LR value in the bottommost
1268 * stack frame are valid.
1270 if ((pc | lr) != 0) {
1271 unsigned long fnstart, fnend;
1272 unsigned long nextip;
1273 int printip = 1;
1275 get_function_bounds(pc, &fnstart, &fnend);
1276 nextip = 0;
1277 if (newsp > sp)
1278 mread(newsp + 16, &nextip,
1279 sizeof(unsigned long));
1280 if (lr == ip) {
1281 if (lr < PAGE_OFFSET
1282 || (fnstart <= lr && lr < fnend))
1283 printip = 0;
1284 } else if (lr == nextip) {
1285 printip = 0;
1286 } else if (lr >= PAGE_OFFSET
1287 && !(fnstart <= lr && lr < fnend)) {
1288 printf("[link register ] ");
1289 xmon_print_symbol(lr, " ", "\n");
1291 if (printip) {
1292 printf("[%.16lx] ", sp);
1293 xmon_print_symbol(ip, " ", " (unreliable)\n");
1295 pc = lr = 0;
1297 } else {
1298 printf("[%.16lx] ", sp);
1299 xmon_print_symbol(ip, " ", "\n");
1302 /* Look for "regshere" marker to see if this is
1303 an exception frame. */
1304 if (mread(sp + 0x60, &marker, sizeof(unsigned long))
1305 && marker == 0x7265677368657265ul) {
1306 if (mread(sp + 0x70, &regs, sizeof(regs))
1307 != sizeof(regs)) {
1308 printf("Couldn't read registers at %lx\n",
1309 sp + 0x70);
1310 break;
1312 printf("--- Exception: %lx %s at ", regs.trap,
1313 getvecname(TRAP(&regs)));
1314 pc = regs.nip;
1315 lr = regs.link;
1316 xmon_print_symbol(pc, " ", "\n");
1319 if (newsp == 0)
1320 break;
1322 sp = newsp;
1323 } while (count++ < xmon_depth_to_print);
1326 static void backtrace(struct pt_regs *excp)
1328 unsigned long sp;
1330 if (scanhex(&sp))
1331 xmon_show_stack(sp, 0, 0);
1332 else
1333 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1334 scannl();
1337 static void print_bug_trap(struct pt_regs *regs)
1339 struct bug_entry *bug;
1340 unsigned long addr;
1342 if (regs->msr & MSR_PR)
1343 return; /* not in kernel */
1344 addr = regs->nip; /* address of trap instruction */
1345 if (addr < PAGE_OFFSET)
1346 return;
1347 bug = find_bug(regs->nip);
1348 if (bug == NULL)
1349 return;
1350 if (bug->line & BUG_WARNING_TRAP)
1351 return;
1353 printf("kernel BUG in %s at %s:%d!\n",
1354 bug->function, bug->file, (unsigned int)bug->line);
1357 void excprint(struct pt_regs *fp)
1359 unsigned long trap;
1361 #ifdef CONFIG_SMP
1362 printf("cpu 0x%x: ", smp_processor_id());
1363 #endif /* CONFIG_SMP */
1365 trap = TRAP(fp);
1366 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1367 printf(" pc: ");
1368 xmon_print_symbol(fp->nip, ": ", "\n");
1370 printf(" lr: ", fp->link);
1371 xmon_print_symbol(fp->link, ": ", "\n");
1373 printf(" sp: %lx\n", fp->gpr[1]);
1374 printf(" msr: %lx\n", fp->msr);
1376 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1377 printf(" dar: %lx\n", fp->dar);
1378 if (trap != 0x380)
1379 printf(" dsisr: %lx\n", fp->dsisr);
1382 printf(" current = 0x%lx\n", current);
1383 printf(" paca = 0x%lx\n", get_paca());
1384 if (current) {
1385 printf(" pid = %ld, comm = %s\n",
1386 current->pid, current->comm);
1389 if (trap == 0x700)
1390 print_bug_trap(fp);
1393 void prregs(struct pt_regs *fp)
1395 int n;
1396 unsigned long base;
1397 struct pt_regs regs;
1399 if (scanhex(&base)) {
1400 if (setjmp(bus_error_jmp) == 0) {
1401 catch_memory_errors = 1;
1402 sync();
1403 regs = *(struct pt_regs *)base;
1404 sync();
1405 __delay(200);
1406 } else {
1407 catch_memory_errors = 0;
1408 printf("*** Error reading registers from %.16lx\n",
1409 base);
1410 return;
1412 catch_memory_errors = 0;
1413 fp = &regs;
1416 if (FULL_REGS(fp)) {
1417 for (n = 0; n < 16; ++n)
1418 printf("R%.2ld = %.16lx R%.2ld = %.16lx\n",
1419 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1420 } else {
1421 for (n = 0; n < 7; ++n)
1422 printf("R%.2ld = %.16lx R%.2ld = %.16lx\n",
1423 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1425 printf("pc = ");
1426 xmon_print_symbol(fp->nip, " ", "\n");
1427 printf("lr = ");
1428 xmon_print_symbol(fp->link, " ", "\n");
1429 printf("msr = %.16lx cr = %.8lx\n", fp->msr, fp->ccr);
1430 printf("ctr = %.16lx xer = %.16lx trap = %8lx\n",
1431 fp->ctr, fp->xer, fp->trap);
1434 void cacheflush(void)
1436 int cmd;
1437 unsigned long nflush;
1439 cmd = inchar();
1440 if (cmd != 'i')
1441 termch = cmd;
1442 scanhex((void *)&adrs);
1443 if (termch != '\n')
1444 termch = 0;
1445 nflush = 1;
1446 scanhex(&nflush);
1447 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1448 if (setjmp(bus_error_jmp) == 0) {
1449 catch_memory_errors = 1;
1450 sync();
1452 if (cmd != 'i') {
1453 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1454 cflush((void *) adrs);
1455 } else {
1456 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1457 cinval((void *) adrs);
1459 sync();
1460 /* wait a little while to see if we get a machine check */
1461 __delay(200);
1463 catch_memory_errors = 0;
1466 unsigned long
1467 read_spr(int n)
1469 unsigned int instrs[2];
1470 unsigned long (*code)(void);
1471 unsigned long opd[3];
1472 unsigned long ret = -1UL;
1474 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1475 instrs[1] = 0x4e800020;
1476 opd[0] = (unsigned long)instrs;
1477 opd[1] = 0;
1478 opd[2] = 0;
1479 store_inst(instrs);
1480 store_inst(instrs+1);
1481 code = (unsigned long (*)(void)) opd;
1483 if (setjmp(bus_error_jmp) == 0) {
1484 catch_memory_errors = 1;
1485 sync();
1487 ret = code();
1489 sync();
1490 /* wait a little while to see if we get a machine check */
1491 __delay(200);
1492 n = size;
1495 return ret;
1498 void
1499 write_spr(int n, unsigned long val)
1501 unsigned int instrs[2];
1502 unsigned long (*code)(unsigned long);
1503 unsigned long opd[3];
1505 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1506 instrs[1] = 0x4e800020;
1507 opd[0] = (unsigned long)instrs;
1508 opd[1] = 0;
1509 opd[2] = 0;
1510 store_inst(instrs);
1511 store_inst(instrs+1);
1512 code = (unsigned long (*)(unsigned long)) opd;
1514 if (setjmp(bus_error_jmp) == 0) {
1515 catch_memory_errors = 1;
1516 sync();
1518 code(val);
1520 sync();
1521 /* wait a little while to see if we get a machine check */
1522 __delay(200);
1523 n = size;
1527 static unsigned long regno;
1528 extern char exc_prolog;
1529 extern char dec_exc;
1531 void
1532 super_regs(void)
1534 int cmd;
1535 unsigned long val;
1536 #ifdef CONFIG_PPC_ISERIES
1537 struct paca_struct *ptrPaca = NULL;
1538 struct lppaca *ptrLpPaca = NULL;
1539 struct ItLpRegSave *ptrLpRegSave = NULL;
1540 #endif
1542 cmd = skipbl();
1543 if (cmd == '\n') {
1544 unsigned long sp, toc;
1545 asm("mr %0,1" : "=r" (sp) :);
1546 asm("mr %0,2" : "=r" (toc) :);
1548 printf("msr = %.16lx sprg0= %.16lx\n", get_msr(), get_sprg0());
1549 printf("pvr = %.16lx sprg1= %.16lx\n", get_pvr(), get_sprg1());
1550 printf("dec = %.16lx sprg2= %.16lx\n", get_dec(), get_sprg2());
1551 printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3());
1552 printf("toc = %.16lx dar = %.16lx\n", toc, get_dar());
1553 printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1());
1554 #ifdef CONFIG_PPC_ISERIES
1555 // Dump out relevant Paca data areas.
1556 printf("Paca: \n");
1557 ptrPaca = get_paca();
1559 printf(" Local Processor Control Area (LpPaca): \n");
1560 ptrLpPaca = ptrPaca->lppaca_ptr;
1561 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1562 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1563 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1564 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1565 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1567 printf(" Local Processor Register Save Area (LpRegSave): \n");
1568 ptrLpRegSave = ptrPaca->reg_save_ptr;
1569 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1570 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1571 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1572 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1573 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1574 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1575 #endif
1577 return;
1580 scanhex(&regno);
1581 switch (cmd) {
1582 case 'w':
1583 val = read_spr(regno);
1584 scanhex(&val);
1585 write_spr(regno, val);
1586 /* fall through */
1587 case 'r':
1588 printf("spr %lx = %lx\n", regno, read_spr(regno));
1589 break;
1590 case 'm':
1591 val = get_msr();
1592 scanhex(&val);
1593 set_msrd(val);
1594 break;
1596 scannl();
1600 * Stuff for reading and writing memory safely
1603 mread(unsigned long adrs, void *buf, int size)
1605 volatile int n;
1606 char *p, *q;
1608 n = 0;
1609 if (setjmp(bus_error_jmp) == 0) {
1610 catch_memory_errors = 1;
1611 sync();
1612 p = (char *)adrs;
1613 q = (char *)buf;
1614 switch (size) {
1615 case 2:
1616 *(short *)q = *(short *)p;
1617 break;
1618 case 4:
1619 *(int *)q = *(int *)p;
1620 break;
1621 case 8:
1622 *(long *)q = *(long *)p;
1623 break;
1624 default:
1625 for( ; n < size; ++n) {
1626 *q++ = *p++;
1627 sync();
1630 sync();
1631 /* wait a little while to see if we get a machine check */
1632 __delay(200);
1633 n = size;
1635 catch_memory_errors = 0;
1636 return n;
1640 mwrite(unsigned long adrs, void *buf, int size)
1642 volatile int n;
1643 char *p, *q;
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 *(short *)p = *(short *)q;
1654 break;
1655 case 4:
1656 *(int *)p = *(int *)q;
1657 break;
1658 case 8:
1659 *(long *)p = *(long *)q;
1660 break;
1661 default:
1662 for ( ; n < size; ++n) {
1663 *p++ = *q++;
1664 sync();
1667 sync();
1668 /* wait a little while to see if we get a machine check */
1669 __delay(200);
1670 n = size;
1671 } else {
1672 printf("*** Error writing address %x\n", adrs + n);
1674 catch_memory_errors = 0;
1675 return n;
1678 static int fault_type;
1679 static char *fault_chars[] = { "--", "**", "##" };
1681 static int
1682 handle_fault(struct pt_regs *regs)
1684 switch (TRAP(regs)) {
1685 case 0x200:
1686 fault_type = 0;
1687 break;
1688 case 0x300:
1689 case 0x380:
1690 fault_type = 1;
1691 break;
1692 default:
1693 fault_type = 2;
1696 longjmp(bus_error_jmp, 1);
1698 return 0;
1701 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1703 void
1704 byterev(unsigned char *val, int size)
1706 int t;
1708 switch (size) {
1709 case 2:
1710 SWAP(val[0], val[1], t);
1711 break;
1712 case 4:
1713 SWAP(val[0], val[3], t);
1714 SWAP(val[1], val[2], t);
1715 break;
1716 case 8: /* is there really any use for this? */
1717 SWAP(val[0], val[7], t);
1718 SWAP(val[1], val[6], t);
1719 SWAP(val[2], val[5], t);
1720 SWAP(val[3], val[4], t);
1721 break;
1725 static int brev;
1726 static int mnoread;
1728 static char *memex_help_string =
1729 "Memory examine command usage:\n"
1730 "m [addr] [flags] examine/change memory\n"
1731 " addr is optional. will start where left off.\n"
1732 " flags may include chars from this set:\n"
1733 " b modify by bytes (default)\n"
1734 " w modify by words (2 byte)\n"
1735 " l modify by longs (4 byte)\n"
1736 " d modify by doubleword (8 byte)\n"
1737 " r toggle reverse byte order mode\n"
1738 " n do not read memory (for i/o spaces)\n"
1739 " . ok to read (default)\n"
1740 "NOTE: flags are saved as defaults\n"
1743 static char *memex_subcmd_help_string =
1744 "Memory examine subcommands:\n"
1745 " hexval write this val to current location\n"
1746 " 'string' write chars from string to this location\n"
1747 " ' increment address\n"
1748 " ^ decrement address\n"
1749 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1750 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1751 " ` clear no-read flag\n"
1752 " ; stay at this addr\n"
1753 " v change to byte mode\n"
1754 " w change to word (2 byte) mode\n"
1755 " l change to long (4 byte) mode\n"
1756 " u change to doubleword (8 byte) mode\n"
1757 " m addr change current addr\n"
1758 " n toggle no-read flag\n"
1759 " r toggle byte reverse flag\n"
1760 " < count back up count bytes\n"
1761 " > count skip forward count bytes\n"
1762 " x exit this mode\n"
1765 void
1766 memex(void)
1768 int cmd, inc, i, nslash;
1769 unsigned long n;
1770 unsigned char val[16];
1772 scanhex((void *)&adrs);
1773 cmd = skipbl();
1774 if (cmd == '?') {
1775 printf(memex_help_string);
1776 return;
1777 } else {
1778 termch = cmd;
1780 last_cmd = "m\n";
1781 while ((cmd = skipbl()) != '\n') {
1782 switch( cmd ){
1783 case 'b': size = 1; break;
1784 case 'w': size = 2; break;
1785 case 'l': size = 4; break;
1786 case 'd': size = 8; break;
1787 case 'r': brev = !brev; break;
1788 case 'n': mnoread = 1; break;
1789 case '.': mnoread = 0; break;
1792 if( size <= 0 )
1793 size = 1;
1794 else if( size > 8 )
1795 size = 8;
1796 for(;;){
1797 if (!mnoread)
1798 n = mread(adrs, val, size);
1799 printf("%.16x%c", adrs, brev? 'r': ' ');
1800 if (!mnoread) {
1801 if (brev)
1802 byterev(val, size);
1803 putchar(' ');
1804 for (i = 0; i < n; ++i)
1805 printf("%.2x", val[i]);
1806 for (; i < size; ++i)
1807 printf("%s", fault_chars[fault_type]);
1809 putchar(' ');
1810 inc = size;
1811 nslash = 0;
1812 for(;;){
1813 if( scanhex(&n) ){
1814 for (i = 0; i < size; ++i)
1815 val[i] = n >> (i * 8);
1816 if (!brev)
1817 byterev(val, size);
1818 mwrite(adrs, val, size);
1819 inc = size;
1821 cmd = skipbl();
1822 if (cmd == '\n')
1823 break;
1824 inc = 0;
1825 switch (cmd) {
1826 case '\'':
1827 for(;;){
1828 n = inchar();
1829 if( n == '\\' )
1830 n = bsesc();
1831 else if( n == '\'' )
1832 break;
1833 for (i = 0; i < size; ++i)
1834 val[i] = n >> (i * 8);
1835 if (!brev)
1836 byterev(val, size);
1837 mwrite(adrs, val, size);
1838 adrs += size;
1840 adrs -= size;
1841 inc = size;
1842 break;
1843 case ',':
1844 adrs += size;
1845 break;
1846 case '.':
1847 mnoread = 0;
1848 break;
1849 case ';':
1850 break;
1851 case 'x':
1852 case EOF:
1853 scannl();
1854 return;
1855 case 'b':
1856 case 'v':
1857 size = 1;
1858 break;
1859 case 'w':
1860 size = 2;
1861 break;
1862 case 'l':
1863 size = 4;
1864 break;
1865 case 'u':
1866 size = 8;
1867 break;
1868 case '^':
1869 adrs -= size;
1870 break;
1871 break;
1872 case '/':
1873 if (nslash > 0)
1874 adrs -= 1 << nslash;
1875 else
1876 nslash = 0;
1877 nslash += 4;
1878 adrs += 1 << nslash;
1879 break;
1880 case '\\':
1881 if (nslash < 0)
1882 adrs += 1 << -nslash;
1883 else
1884 nslash = 0;
1885 nslash -= 4;
1886 adrs -= 1 << -nslash;
1887 break;
1888 case 'm':
1889 scanhex((void *)&adrs);
1890 break;
1891 case 'n':
1892 mnoread = 1;
1893 break;
1894 case 'r':
1895 brev = !brev;
1896 break;
1897 case '<':
1898 n = size;
1899 scanhex(&n);
1900 adrs -= n;
1901 break;
1902 case '>':
1903 n = size;
1904 scanhex(&n);
1905 adrs += n;
1906 break;
1907 case '?':
1908 printf(memex_subcmd_help_string);
1909 break;
1912 adrs += inc;
1917 bsesc(void)
1919 int c;
1921 c = inchar();
1922 switch( c ){
1923 case 'n': c = '\n'; break;
1924 case 'r': c = '\r'; break;
1925 case 'b': c = '\b'; break;
1926 case 't': c = '\t'; break;
1928 return c;
1931 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1932 || ('a' <= (c) && (c) <= 'f') \
1933 || ('A' <= (c) && (c) <= 'F'))
1934 void
1935 dump(void)
1937 int c;
1939 c = inchar();
1940 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1941 termch = c;
1942 scanhex((void *)&adrs);
1943 if (termch != '\n')
1944 termch = 0;
1945 if (c == 'i') {
1946 scanhex(&nidump);
1947 if (nidump == 0)
1948 nidump = 16;
1949 else if (nidump > MAX_DUMP)
1950 nidump = MAX_DUMP;
1951 adrs += ppc_inst_dump(adrs, nidump, 1);
1952 last_cmd = "di\n";
1953 } else {
1954 scanhex(&ndump);
1955 if (ndump == 0)
1956 ndump = 64;
1957 else if (ndump > MAX_DUMP)
1958 ndump = MAX_DUMP;
1959 prdump(adrs, ndump);
1960 adrs += ndump;
1961 last_cmd = "d\n";
1965 void
1966 prdump(unsigned long adrs, long ndump)
1968 long n, m, c, r, nr;
1969 unsigned char temp[16];
1971 for (n = ndump; n > 0;) {
1972 printf("%.16lx", adrs);
1973 putchar(' ');
1974 r = n < 16? n: 16;
1975 nr = mread(adrs, temp, r);
1976 adrs += nr;
1977 for (m = 0; m < r; ++m) {
1978 if ((m & 7) == 0 && m > 0)
1979 putchar(' ');
1980 if (m < nr)
1981 printf("%.2x", temp[m]);
1982 else
1983 printf("%s", fault_chars[fault_type]);
1985 if (m <= 8)
1986 printf(" ");
1987 for (; m < 16; ++m)
1988 printf(" ");
1989 printf(" |");
1990 for (m = 0; m < r; ++m) {
1991 if (m < nr) {
1992 c = temp[m];
1993 putchar(' ' <= c && c <= '~'? c: '.');
1994 } else
1995 putchar(' ');
1997 n -= r;
1998 for (; m < 16; ++m)
1999 putchar(' ');
2000 printf("|\n");
2001 if (nr < r)
2002 break;
2007 ppc_inst_dump(unsigned long adr, long count, int praddr)
2009 int nr, dotted;
2010 unsigned long first_adr;
2011 unsigned long inst, last_inst = 0;
2012 unsigned char val[4];
2014 dotted = 0;
2015 for (first_adr = adr; count > 0; --count, adr += 4) {
2016 nr = mread(adr, val, 4);
2017 if (nr == 0) {
2018 if (praddr) {
2019 const char *x = fault_chars[fault_type];
2020 printf("%.16lx %s%s%s%s\n", adr, x, x, x, x);
2022 break;
2024 inst = GETWORD(val);
2025 if (adr > first_adr && inst == last_inst) {
2026 if (!dotted) {
2027 printf(" ...\n");
2028 dotted = 1;
2030 continue;
2032 dotted = 0;
2033 last_inst = inst;
2034 if (praddr)
2035 printf("%.16lx %.8x", adr, inst);
2036 printf("\t");
2037 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2038 printf("\n");
2040 return adr - first_adr;
2043 void
2044 print_address(unsigned long addr)
2046 xmon_print_symbol(addr, "\t# ", "");
2051 * Memory operations - move, set, print differences
2053 static unsigned long mdest; /* destination address */
2054 static unsigned long msrc; /* source address */
2055 static unsigned long mval; /* byte value to set memory to */
2056 static unsigned long mcount; /* # bytes to affect */
2057 static unsigned long mdiffs; /* max # differences to print */
2059 void
2060 memops(int cmd)
2062 scanhex((void *)&mdest);
2063 if( termch != '\n' )
2064 termch = 0;
2065 scanhex((void *)(cmd == 's'? &mval: &msrc));
2066 if( termch != '\n' )
2067 termch = 0;
2068 scanhex((void *)&mcount);
2069 switch( cmd ){
2070 case 'm':
2071 memmove((void *)mdest, (void *)msrc, mcount);
2072 break;
2073 case 's':
2074 memset((void *)mdest, mval, mcount);
2075 break;
2076 case 'd':
2077 if( termch != '\n' )
2078 termch = 0;
2079 scanhex((void *)&mdiffs);
2080 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2081 break;
2085 void
2086 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2088 unsigned n, prt;
2090 prt = 0;
2091 for( n = nb; n > 0; --n )
2092 if( *p1++ != *p2++ )
2093 if( ++prt <= maxpr )
2094 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2095 p1[-1], p2 - 1, p2[-1]);
2096 if( prt > maxpr )
2097 printf("Total of %d differences\n", prt);
2100 static unsigned mend;
2101 static unsigned mask;
2103 void
2104 memlocate(void)
2106 unsigned a, n;
2107 unsigned char val[4];
2109 last_cmd = "ml";
2110 scanhex((void *)&mdest);
2111 if (termch != '\n') {
2112 termch = 0;
2113 scanhex((void *)&mend);
2114 if (termch != '\n') {
2115 termch = 0;
2116 scanhex((void *)&mval);
2117 mask = ~0;
2118 if (termch != '\n') termch = 0;
2119 scanhex((void *)&mask);
2122 n = 0;
2123 for (a = mdest; a < mend; a += 4) {
2124 if (mread(a, val, 4) == 4
2125 && ((GETWORD(val) ^ mval) & mask) == 0) {
2126 printf("%.16x: %.16x\n", a, GETWORD(val));
2127 if (++n >= 10)
2128 break;
2133 static unsigned long mskip = 0x1000;
2134 static unsigned long mlim = 0xffffffff;
2136 void
2137 memzcan(void)
2139 unsigned char v;
2140 unsigned a;
2141 int ok, ook;
2143 scanhex(&mdest);
2144 if (termch != '\n') termch = 0;
2145 scanhex(&mskip);
2146 if (termch != '\n') termch = 0;
2147 scanhex(&mlim);
2148 ook = 0;
2149 for (a = mdest; a < mlim; a += mskip) {
2150 ok = mread(a, &v, 1);
2151 if (ok && !ook) {
2152 printf("%.8x .. ", a);
2153 fflush(stdout);
2154 } else if (!ok && ook)
2155 printf("%.8x\n", a - mskip);
2156 ook = ok;
2157 if (a + mskip < a)
2158 break;
2160 if (ook)
2161 printf("%.8x\n", a - mskip);
2164 /* Input scanning routines */
2166 skipbl(void)
2168 int c;
2170 if( termch != 0 ){
2171 c = termch;
2172 termch = 0;
2173 } else
2174 c = inchar();
2175 while( c == ' ' || c == '\t' )
2176 c = inchar();
2177 return c;
2180 #define N_PTREGS 44
2181 static char *regnames[N_PTREGS] = {
2182 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2183 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2184 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2185 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2186 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "softe",
2187 "trap", "dar", "dsisr", "res"
2191 scanhex(unsigned long *vp)
2193 int c, d;
2194 unsigned long v;
2196 c = skipbl();
2197 if (c == '%') {
2198 /* parse register name */
2199 char regname[8];
2200 int i;
2202 for (i = 0; i < sizeof(regname) - 1; ++i) {
2203 c = inchar();
2204 if (!isalnum(c)) {
2205 termch = c;
2206 break;
2208 regname[i] = c;
2210 regname[i] = 0;
2211 for (i = 0; i < N_PTREGS; ++i) {
2212 if (strcmp(regnames[i], regname) == 0) {
2213 if (xmon_regs == NULL) {
2214 printf("regs not available\n");
2215 return 0;
2217 *vp = ((unsigned long *)xmon_regs)[i];
2218 return 1;
2221 printf("invalid register name '%%%s'\n", regname);
2222 return 0;
2225 /* skip leading "0x" if any */
2227 if (c == '0') {
2228 c = inchar();
2229 if (c == 'x') {
2230 c = inchar();
2231 } else {
2232 d = hexdigit(c);
2233 if (d == EOF) {
2234 termch = c;
2235 *vp = 0;
2236 return 1;
2239 } else if (c == '$') {
2240 int i;
2241 for (i=0; i<63; i++) {
2242 c = inchar();
2243 if (isspace(c)) {
2244 termch = c;
2245 break;
2247 tmpstr[i] = c;
2249 tmpstr[i++] = 0;
2250 *vp = kallsyms_lookup_name(tmpstr);
2251 if (!(*vp)) {
2252 printf("unknown symbol '%s'\n", tmpstr);
2253 return 0;
2255 return 1;
2258 d = hexdigit(c);
2259 if (d == EOF) {
2260 termch = c;
2261 return 0;
2263 v = 0;
2264 do {
2265 v = (v << 4) + d;
2266 c = inchar();
2267 d = hexdigit(c);
2268 } while (d != EOF);
2269 termch = c;
2270 *vp = v;
2271 return 1;
2274 void
2275 scannl(void)
2277 int c;
2279 c = termch;
2280 termch = 0;
2281 while( c != '\n' )
2282 c = inchar();
2286 hexdigit(int c)
2288 if( '0' <= c && c <= '9' )
2289 return c - '0';
2290 if( 'A' <= c && c <= 'F' )
2291 return c - ('A' - 10);
2292 if( 'a' <= c && c <= 'f' )
2293 return c - ('a' - 10);
2294 return EOF;
2297 void
2298 getstring(char *s, int size)
2300 int c;
2302 c = skipbl();
2303 do {
2304 if( size > 1 ){
2305 *s++ = c;
2306 --size;
2308 c = inchar();
2309 } while( c != ' ' && c != '\t' && c != '\n' );
2310 termch = c;
2311 *s = 0;
2314 static char line[256];
2315 static char *lineptr;
2317 void
2318 flush_input(void)
2320 lineptr = NULL;
2324 inchar(void)
2326 if (lineptr == NULL || *lineptr == 0) {
2327 if (fgets(line, sizeof(line), stdin) == NULL) {
2328 lineptr = NULL;
2329 return EOF;
2331 lineptr = line;
2333 return *lineptr++;
2336 void
2337 take_input(char *str)
2339 lineptr = str;
2343 static void
2344 symbol_lookup(void)
2346 int type = inchar();
2347 unsigned long addr;
2348 static char tmp[64];
2350 switch (type) {
2351 case 'a':
2352 if (scanhex(&addr))
2353 xmon_print_symbol(addr, ": ", "\n");
2354 termch = 0;
2355 break;
2356 case 's':
2357 getstring(tmp, 64);
2358 if (setjmp(bus_error_jmp) == 0) {
2359 catch_memory_errors = 1;
2360 sync();
2361 addr = kallsyms_lookup_name(tmp);
2362 if (addr)
2363 printf("%s: %lx\n", tmp, addr);
2364 else
2365 printf("Symbol '%s' not found.\n", tmp);
2366 sync();
2368 catch_memory_errors = 0;
2369 termch = 0;
2370 break;
2375 /* Print an address in numeric and symbolic form (if possible) */
2376 static void xmon_print_symbol(unsigned long address, const char *mid,
2377 const char *after)
2379 char *modname;
2380 const char *name = NULL;
2381 unsigned long offset, size;
2383 printf("%.16lx", address);
2384 if (setjmp(bus_error_jmp) == 0) {
2385 catch_memory_errors = 1;
2386 sync();
2387 name = kallsyms_lookup(address, &size, &offset, &modname,
2388 tmpstr);
2389 sync();
2390 /* wait a little while to see if we get a machine check */
2391 __delay(200);
2394 catch_memory_errors = 0;
2396 if (name) {
2397 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2398 if (modname)
2399 printf(" [%s]", modname);
2401 printf("%s", after);
2404 static void debug_trace(void)
2406 unsigned long val, cmd, on;
2408 cmd = skipbl();
2409 if (cmd == '\n') {
2410 /* show current state */
2411 unsigned long i;
2412 printf("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch);
2413 for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) {
2414 on = PPCDBG_BITVAL(i) & ppc64_debug_switch;
2415 printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : "");
2416 if (((i+1) % 3) == 0)
2417 printf("\n");
2419 printf("\n");
2420 return;
2422 while (cmd != '\n') {
2423 on = 1; /* default if no sign given */
2424 while (cmd == '+' || cmd == '-') {
2425 on = (cmd == '+');
2426 cmd = inchar();
2427 if (cmd == ' ' || cmd == '\n') { /* Turn on or off based on + or - */
2428 ppc64_debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE;
2429 printf("Setting all values to %s...\n", on ? "on" : "off");
2430 if (cmd == '\n') return;
2431 else cmd = skipbl();
2433 else
2434 termch = cmd;
2436 termch = cmd; /* not +/- ... let scanhex see it */
2437 scanhex((void *)&val);
2438 if (val >= 64) {
2439 printf("Value %x out of range:\n", val);
2440 return;
2442 if (on) {
2443 ppc64_debug_switch |= PPCDBG_BITVAL(val);
2444 printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2445 } else {
2446 ppc64_debug_switch &= ~PPCDBG_BITVAL(val);
2447 printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2449 cmd = skipbl();
2453 static void dump_slb(void)
2455 int i;
2456 unsigned long tmp;
2458 printf("SLB contents of cpu %x\n", smp_processor_id());
2460 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2461 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2462 printf("%02d %016lx ", i, tmp);
2464 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2465 printf("%016lx\n", tmp);
2469 static void dump_stab(void)
2471 int i;
2472 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2474 printf("Segment table contents of cpu %x\n", smp_processor_id());
2476 for (i = 0; i < PAGE_SIZE/16; i++) {
2477 unsigned long a, b;
2479 a = *tmp++;
2480 b = *tmp++;
2482 if (a || b) {
2483 printf("%03d %016lx ", i, a);
2484 printf("%016lx\n", b);
2489 void xmon_init(void)
2491 __debugger = xmon;
2492 __debugger_ipi = xmon_ipi;
2493 __debugger_bpt = xmon_bpt;
2494 __debugger_sstep = xmon_sstep;
2495 __debugger_iabr_match = xmon_iabr_match;
2496 __debugger_dabr_match = xmon_dabr_match;
2497 __debugger_fault_handler = xmon_fault_handler;
2500 void dump_segments(void)
2502 if (cpu_has_feature(CPU_FTR_SLB))
2503 dump_slb();
2504 else
2505 dump_stab();