MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / ppc64 / xmon / xmon.c
blob6ef0b1ec3bc7d3ae146af449501cd57beec04895
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/naca.h>
30 #include <asm/paca.h>
31 #include <asm/ppcdebug.h>
32 #include <asm/cputable.h>
33 #include <asm/rtas.h>
35 #include "nonstdio.h"
36 #include "privinst.h"
38 #define scanhex xmon_scanhex
39 #define skipbl xmon_skipbl
41 #ifdef CONFIG_SMP
42 volatile cpumask_t cpus_in_xmon = CPU_MASK_NONE;
43 static unsigned long xmon_taken = 1;
44 static int xmon_owner;
45 static int xmon_gate;
46 #endif /* CONFIG_SMP */
48 static unsigned long in_xmon = 0;
50 static unsigned long adrs;
51 static int size = 1;
52 static unsigned long ndump = 64;
53 static unsigned long nidump = 16;
54 static unsigned long ncsum = 4096;
55 static int termch;
56 static char tmpstr[128];
58 #define JMP_BUF_LEN (184/sizeof(long))
59 static long bus_error_jmp[JMP_BUF_LEN];
60 static int catch_memory_errors;
61 static long *xmon_fault_jmp[NR_CPUS];
62 #define setjmp xmon_setjmp
63 #define longjmp xmon_longjmp
65 /* Breakpoint stuff */
66 struct bpt {
67 unsigned long address;
68 unsigned int instr[2];
69 atomic_t ref_count;
70 int enabled;
71 unsigned long pad;
74 /* Bits in bpt.enabled */
75 #define BP_IABR_TE 1 /* IABR translation enabled */
76 #define BP_IABR 2
77 #define BP_TRAP 8
78 #define BP_DABR 0x10
80 #define NBPTS 256
81 static struct bpt bpts[NBPTS];
82 static struct bpt dabr;
83 static struct bpt *iabr;
84 static unsigned bpinstr = 0x7fe00008; /* trap */
86 #define BP_NUM(bp) ((bp) - bpts + 1)
88 /* Bits in SRR1 that are copied from MSR */
89 #define MSR_MASK 0xffffffff87c0ffff
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 int emulate_step(struct pt_regs *regs, unsigned int instr);
136 static void xmon_print_symbol(unsigned long address, const char *mid,
137 const char *after);
138 static const char *getvecname(unsigned long vec);
140 static void debug_trace(void);
142 extern int print_insn_powerpc(unsigned long, unsigned long, int);
143 extern void printf(const char *fmt, ...);
144 extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
145 extern int xmon_putc(int c, void *f);
146 extern int putchar(int ch);
147 extern int xmon_read_poll(void);
148 extern int setjmp(long *);
149 extern void longjmp(long *, int);
150 extern unsigned long _ASR;
151 extern char SystemCall_common[];
153 pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va); /* from htab.c */
155 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
157 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
158 || ('a' <= (c) && (c) <= 'f') \
159 || ('A' <= (c) && (c) <= 'F'))
160 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
161 || ('a' <= (c) && (c) <= 'z') \
162 || ('A' <= (c) && (c) <= 'Z'))
163 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
165 static char *help_string = "\
166 Commands:\n\
167 b show breakpoints\n\
168 bd set data breakpoint\n\
169 bi set instruction breakpoint\n\
170 bc clear breakpoint\n"
171 #ifdef CONFIG_SMP
173 c print cpus stopped in xmon\n\
174 c# try to switch to cpu number h (in hex)\n"
175 #endif
177 C checksum\n\
178 d dump bytes\n\
179 di dump instructions\n\
180 df dump float values\n\
181 dd dump double values\n\
182 e print exception information\n\
183 f flush cache\n\
184 la lookup symbol+offset of specified address\n\
185 ls lookup address of specified symbol\n\
186 m examine/change memory\n\
187 mm move a block of memory\n\
188 ms set a block of memory\n\
189 md compare two blocks of memory\n\
190 ml locate a block of memory\n\
191 mz zero a block of memory\n\
192 mi show information about memory allocation\n\
193 p show the task list\n\
194 r print registers\n\
195 s single step\n\
196 S print special registers\n\
197 t print backtrace\n\
198 T Enable/Disable PPCDBG flags\n\
199 x exit monitor and recover\n\
200 X exit monitor and dont recover\n\
201 u dump segment table or SLB\n\
202 ? help\n"
204 zr reboot\n\
205 zh halt\n"
208 static struct pt_regs *xmon_regs;
210 extern inline void sync(void)
212 asm volatile("sync; isync");
215 /* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs).
216 A PPC stack frame looks like this:
218 High Address
219 Back Chain
220 FP reg save area
221 GP reg save area
222 Local var space
223 Parameter save area (SP+48)
224 TOC save area (SP+40)
225 link editor doubleword (SP+32)
226 compiler doubleword (SP+24)
227 LR save (SP+16)
228 CR save (SP+8)
229 Back Chain (SP+0)
231 Note that the LR (ret addr) may not be saved in the current frame if
232 no functions have been called from the current function.
236 * We don't allow single-stepping an mtmsrd that would clear
237 * MSR_RI, since that would make the exception unrecoverable.
238 * Since we need to single-step to proceed from a breakpoint,
239 * we don't allow putting a breakpoint on an mtmsrd instruction.
240 * Similarly we don't allow breakpoints on rfid instructions.
241 * These macros tell us if an instruction is a mtmsrd or rfid.
243 #define IS_MTMSRD(instr) (((instr) & 0xfc0007fe) == 0x7c000164)
244 #define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024)
247 * Disable surveillance (the service processor watchdog function)
248 * while we are in xmon.
249 * XXX we should re-enable it when we leave. :)
251 #define SURVEILLANCE_TOKEN 9000
253 static inline void disable_surveillance(void)
255 #ifdef CONFIG_PPC_PSERIES
256 /* Since this can't be a module, args should end up below 4GB. */
257 static struct rtas_args args;
260 * At this point we have got all the cpus we can into
261 * xmon, so there is hopefully no other cpu calling RTAS
262 * at the moment, even though we don't take rtas.lock.
263 * If we did try to take rtas.lock there would be a
264 * real possibility of deadlock.
266 args.token = rtas_token("set-indicator");
267 if (args.token == RTAS_UNKNOWN_SERVICE)
268 return;
269 args.nargs = 3;
270 args.nret = 1;
271 args.rets = &args.args[3];
272 args.args[0] = SURVEILLANCE_TOKEN;
273 args.args[1] = 0;
274 args.args[2] = 0;
275 enter_rtas(__pa(&args));
276 #endif /* CONFIG_PPC_PSERIES */
279 #ifdef CONFIG_SMP
280 static int xmon_speaker;
282 static void get_output_lock(void)
284 int me = smp_processor_id() + 0x100;
285 int last_speaker = 0, prev;
286 long timeout;
288 if (xmon_speaker == me)
289 return;
290 for (;;) {
291 if (xmon_speaker == 0) {
292 last_speaker = cmpxchg(&xmon_speaker, 0, me);
293 if (last_speaker == 0)
294 return;
296 timeout = 10000000;
297 while (xmon_speaker == last_speaker) {
298 if (--timeout > 0)
299 continue;
300 /* hostile takeover */
301 prev = cmpxchg(&xmon_speaker, last_speaker, me);
302 if (prev == last_speaker)
303 return;
304 break;
309 static void release_output_lock(void)
311 xmon_speaker = 0;
313 #endif
315 int xmon_core(struct pt_regs *regs, int fromipi)
317 int cmd = 0;
318 unsigned long msr;
319 struct bpt *bp;
320 long recurse_jmp[JMP_BUF_LEN];
321 unsigned long offset;
322 #ifdef CONFIG_SMP
323 int cpu;
324 int secondary;
325 unsigned long timeout;
326 #endif
328 msr = get_msr();
329 set_msrd(msr & ~MSR_EE); /* disable interrupts */
331 bp = in_breakpoint_table(regs->nip, &offset);
332 if (bp != NULL) {
333 regs->nip = bp->address + offset;
334 atomic_dec(&bp->ref_count);
337 remove_cpu_bpts();
339 #ifdef CONFIG_SMP
340 cpu = smp_processor_id();
341 if (cpu_isset(cpu, cpus_in_xmon)) {
342 get_output_lock();
343 excprint(regs);
344 printf("cpu 0x%x: Exception %lx %s in xmon, "
345 "returning to main loop\n",
346 cpu, regs->trap, getvecname(TRAP(regs)));
347 longjmp(xmon_fault_jmp[cpu], 1);
350 if (setjmp(recurse_jmp) != 0) {
351 if (!in_xmon || !xmon_gate) {
352 printf("xmon: WARNING: bad recursive fault "
353 "on cpu 0x%x\n", cpu);
354 goto waiting;
356 secondary = !(xmon_taken && cpu == xmon_owner);
357 goto cmdloop;
360 xmon_fault_jmp[cpu] = recurse_jmp;
361 cpu_set(cpu, cpus_in_xmon);
363 bp = NULL;
364 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
365 bp = at_breakpoint(regs->nip);
366 if (bp || (regs->msr & MSR_RI) == 0)
367 fromipi = 0;
369 if (!fromipi) {
370 get_output_lock();
371 excprint(regs);
372 if (bp) {
373 printf("cpu 0x%x stopped at breakpoint 0x%x (",
374 cpu, BP_NUM(bp));
375 xmon_print_symbol(regs->nip, " ", ")\n");
377 if ((regs->msr & MSR_RI) == 0)
378 printf("WARNING: exception is not recoverable, "
379 "can't continue\n");
380 release_output_lock();
383 waiting:
384 secondary = 1;
385 while (secondary && !xmon_gate) {
386 if (in_xmon == 0) {
387 if (fromipi)
388 goto leave;
389 secondary = test_and_set_bit(0, &in_xmon);
391 barrier();
394 if (!secondary && !xmon_gate) {
395 /* we are the first cpu to come in */
396 /* interrupt other cpu(s) */
397 int ncpus = num_online_cpus();
399 xmon_owner = cpu;
400 mb();
401 if (ncpus > 1) {
402 smp_send_debugger_break(MSG_ALL_BUT_SELF);
403 /* wait for other cpus to come in */
404 for (timeout = 100000000; timeout != 0; --timeout)
405 if (cpus_weight(cpus_in_xmon) >= ncpus)
406 break;
408 remove_bpts();
409 disable_surveillance();
410 /* for breakpoint or single step, print the current instr. */
411 if (bp || TRAP(regs) == 0xd00)
412 ppc_inst_dump(regs->nip, 1, 0);
413 printf("enter ? for help\n");
414 mb();
415 xmon_gate = 1;
416 barrier();
419 cmdloop:
420 while (in_xmon) {
421 if (secondary) {
422 if (cpu == xmon_owner) {
423 if (!test_and_set_bit(0, &xmon_taken)) {
424 secondary = 0;
425 continue;
427 /* missed it */
428 while (cpu == xmon_owner)
429 barrier();
431 barrier();
432 } else {
433 cmd = cmds(regs);
434 if (cmd != 0) {
435 /* exiting xmon */
436 insert_bpts();
437 xmon_gate = 0;
438 wmb();
439 in_xmon = 0;
440 break;
442 /* have switched to some other cpu */
443 secondary = 1;
446 leave:
447 cpu_clear(cpu, cpus_in_xmon);
448 xmon_fault_jmp[cpu] = NULL;
450 #else
451 /* UP is simple... */
452 if (in_xmon) {
453 printf("Exception %lx %s in xmon, returning to main loop\n",
454 regs->trap, getvecname(TRAP(regs)));
455 longjmp(xmon_fault_jmp[0], 1);
457 if (setjmp(recurse_jmp) == 0) {
458 xmon_fault_jmp[0] = recurse_jmp;
459 in_xmon = 1;
461 excprint(regs);
462 bp = at_breakpoint(regs->nip);
463 if (bp) {
464 printf("Stopped at breakpoint %x (", BP_NUM(bp));
465 xmon_print_symbol(regs->nip, " ", ")\n");
467 if ((regs->msr & MSR_RI) == 0)
468 printf("WARNING: exception is not recoverable, "
469 "can't continue\n");
470 remove_bpts();
471 disable_surveillance();
472 /* for breakpoint or single step, print the current instr. */
473 if (bp || TRAP(regs) == 0xd00)
474 ppc_inst_dump(regs->nip, 1, 0);
475 printf("enter ? for help\n");
478 cmd = cmds(regs);
480 insert_bpts();
481 in_xmon = 0;
482 #endif
484 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
485 bp = at_breakpoint(regs->nip);
486 if (bp != NULL) {
487 int stepped = emulate_step(regs, bp->instr[0]);
488 if (stepped == 0) {
489 regs->nip = (unsigned long) &bp->instr[0];
490 atomic_inc(&bp->ref_count);
495 insert_cpu_bpts();
497 set_msrd(msr); /* restore interrupt enable */
499 return cmd != 'X';
502 int xmon(struct pt_regs *excp)
504 struct pt_regs regs;
506 if (excp == NULL) {
507 /* Ok, grab regs as they are now.
508 This won't do a particularily good job because the
509 prologue has already been executed.
510 ToDo: We could reach back into the callers save
511 area to do a better job of representing the
512 caller's state.
514 asm volatile ("std 0,0(%0)\n\
515 std 1,8(%0)\n\
516 std 2,16(%0)\n\
517 std 3,24(%0)\n\
518 std 4,32(%0)\n\
519 std 5,40(%0)\n\
520 std 6,48(%0)\n\
521 std 7,56(%0)\n\
522 std 8,64(%0)\n\
523 std 9,72(%0)\n\
524 std 10,80(%0)\n\
525 std 11,88(%0)\n\
526 std 12,96(%0)\n\
527 std 13,104(%0)\n\
528 std 14,112(%0)\n\
529 std 15,120(%0)\n\
530 std 16,128(%0)\n\
531 std 17,136(%0)\n\
532 std 18,144(%0)\n\
533 std 19,152(%0)\n\
534 std 20,160(%0)\n\
535 std 21,168(%0)\n\
536 std 22,176(%0)\n\
537 std 23,184(%0)\n\
538 std 24,192(%0)\n\
539 std 25,200(%0)\n\
540 std 26,208(%0)\n\
541 std 27,216(%0)\n\
542 std 28,224(%0)\n\
543 std 29,232(%0)\n\
544 std 30,240(%0)\n\
545 std 31,248(%0)" : : "b" (&regs));
547 regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
548 regs.msr = get_msr();
549 regs.ctr = get_ctr();
550 regs.xer = get_xer();
551 regs.ccr = get_cr();
552 regs.trap = 0;
553 excp = &regs;
555 return xmon_core(excp, 0);
558 int xmon_bpt(struct pt_regs *regs)
560 struct bpt *bp;
561 unsigned long offset;
563 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
564 return 0;
566 /* Are we at the trap at bp->instr[1] for some bp? */
567 bp = in_breakpoint_table(regs->nip, &offset);
568 if (bp != NULL && offset == 4) {
569 regs->nip = bp->address + 4;
570 atomic_dec(&bp->ref_count);
571 return 1;
574 /* Are we at a breakpoint? */
575 bp = at_breakpoint(regs->nip);
576 if (!bp)
577 return 0;
579 xmon_core(regs, 0);
581 return 1;
584 int xmon_sstep(struct pt_regs *regs)
586 if (user_mode(regs))
587 return 0;
588 xmon_core(regs, 0);
589 return 1;
592 int xmon_dabr_match(struct pt_regs *regs)
594 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
595 return 0;
596 xmon_core(regs, 0);
597 return 1;
600 int xmon_iabr_match(struct pt_regs *regs)
602 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
603 return 0;
604 if (iabr == 0)
605 return 0;
606 xmon_core(regs, 0);
607 return 1;
610 int xmon_ipi(struct pt_regs *regs)
612 #ifdef CONFIG_SMP
613 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
614 xmon_core(regs, 1);
615 #endif
616 return 0;
619 int xmon_fault_handler(struct pt_regs *regs)
621 struct bpt *bp;
622 unsigned long offset;
624 if (in_xmon && catch_memory_errors)
625 handle_fault(regs); /* doesn't return */
627 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
628 bp = in_breakpoint_table(regs->nip, &offset);
629 if (bp != NULL) {
630 regs->nip = bp->address + offset;
631 atomic_dec(&bp->ref_count);
635 return 0;
639 static struct bpt *at_breakpoint(unsigned long pc)
641 int i;
642 struct bpt *bp;
644 bp = bpts;
645 for (i = 0; i < NBPTS; ++i, ++bp)
646 if (bp->enabled && pc == bp->address)
647 return bp;
648 return 0;
651 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
653 unsigned long off;
655 off = nip - (unsigned long) bpts;
656 if (off >= sizeof(bpts))
657 return NULL;
658 off %= sizeof(struct bpt);
659 if (off != offsetof(struct bpt, instr[0])
660 && off != offsetof(struct bpt, instr[1]))
661 return NULL;
662 *offp = off - offsetof(struct bpt, instr[0]);
663 return (struct bpt *) (nip - off);
666 static struct bpt *new_breakpoint(unsigned long a)
668 struct bpt *bp;
670 a &= ~3UL;
671 bp = at_breakpoint(a);
672 if (bp)
673 return bp;
675 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
676 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
677 bp->address = a;
678 bp->instr[1] = bpinstr;
679 store_inst(&bp->instr[1]);
680 return bp;
684 printf("Sorry, no free breakpoints. Please clear one first.\n");
685 return NULL;
688 static void insert_bpts(void)
690 int i;
691 struct bpt *bp;
693 bp = bpts;
694 for (i = 0; i < NBPTS; ++i, ++bp) {
695 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
696 continue;
697 if (mread(bp->address, &bp->instr[0], 4) != 4) {
698 printf("Couldn't read instruction at %lx, "
699 "disabling breakpoint there\n", bp->address);
700 bp->enabled = 0;
701 continue;
703 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
704 printf("Breakpoint at %lx is on an mtmsrd or rfid "
705 "instruction, disabling it\n", bp->address);
706 bp->enabled = 0;
707 continue;
709 store_inst(&bp->instr[0]);
710 if (bp->enabled & BP_IABR)
711 continue;
712 if (mwrite(bp->address, &bpinstr, 4) != 4) {
713 printf("Couldn't write instruction at %lx, "
714 "disabling breakpoint there\n", bp->address);
715 bp->enabled &= ~BP_TRAP;
716 continue;
718 store_inst((void *)bp->address);
722 static void insert_cpu_bpts(void)
724 if (dabr.enabled)
725 set_dabr(dabr.address | (dabr.enabled & 7));
726 if (iabr && (cur_cpu_spec->cpu_features & CPU_FTR_IABR))
727 set_iabr(iabr->address
728 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
731 static void remove_bpts(void)
733 int i;
734 struct bpt *bp;
735 unsigned instr;
737 bp = bpts;
738 for (i = 0; i < NBPTS; ++i, ++bp) {
739 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
740 continue;
741 if (mread(bp->address, &instr, 4) == 4
742 && instr == bpinstr
743 && mwrite(bp->address, &bp->instr, 4) != 4)
744 printf("Couldn't remove breakpoint at %lx\n",
745 bp->address);
746 else
747 store_inst((void *)bp->address);
751 static void remove_cpu_bpts(void)
753 set_dabr(0);
754 if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR))
755 set_iabr(0);
758 static int branch_taken(unsigned int instr, struct pt_regs *regs)
760 unsigned int bo = (instr >> 21) & 0x1f;
761 unsigned int bi;
763 if ((bo & 4) == 0) {
764 /* decrement counter */
765 --regs->ctr;
766 if (((bo >> 1) & 1) ^ (regs->ctr == 0))
767 return 0;
769 if ((bo & 0x10) == 0) {
770 /* check bit from CR */
771 bi = (instr >> 16) & 0x1f;
772 if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
773 return 0;
775 return 1;
779 * Emulate instructions that cause a transfer of control.
780 * Returns 1 if the step was emulated, 0 if not,
781 * or -1 if the instruction is one that should not be stepped,
782 * such as an rfid, or a mtmsrd that would clear MSR_RI.
784 static int emulate_step(struct pt_regs *regs, unsigned int instr)
786 unsigned int opcode, rd;
787 unsigned long int imm;
789 opcode = instr >> 26;
790 switch (opcode) {
791 case 16: /* bc */
792 imm = (signed short)(instr & 0xfffc);
793 if ((instr & 2) == 0)
794 imm += regs->nip;
795 regs->nip += 4; /* XXX check 32-bit mode */
796 if (instr & 1)
797 regs->link = regs->nip;
798 if (branch_taken(instr, regs))
799 regs->nip = imm;
800 return 1;
801 case 17: /* sc */
802 regs->gpr[9] = regs->gpr[13];
803 regs->gpr[11] = regs->nip + 4;
804 regs->gpr[12] = regs->msr & MSR_MASK;
805 regs->gpr[13] = (unsigned long) get_paca();
806 regs->nip = (unsigned long) &SystemCall_common;
807 regs->msr = MSR_KERNEL;
808 return 1;
809 case 18: /* b */
810 imm = instr & 0x03fffffc;
811 if (imm & 0x02000000)
812 imm -= 0x04000000;
813 if ((instr & 2) == 0)
814 imm += regs->nip;
815 if (instr & 1)
816 regs->link = regs->nip + 4;
817 regs->nip = imm;
818 return 1;
819 case 19:
820 switch (instr & 0x7fe) {
821 case 0x20: /* bclr */
822 case 0x420: /* bcctr */
823 imm = (instr & 0x400)? regs->ctr: regs->link;
824 regs->nip += 4; /* XXX check 32-bit mode */
825 if (instr & 1)
826 regs->link = regs->nip;
827 if (branch_taken(instr, regs))
828 regs->nip = imm;
829 return 1;
830 case 0x24: /* rfid, scary */
831 printf("Can't single-step an rfid instruction\n");
832 return -1;
834 case 31:
835 rd = (instr >> 21) & 0x1f;
836 switch (instr & 0x7fe) {
837 case 0xa6: /* mfmsr */
838 regs->gpr[rd] = regs->msr & MSR_MASK;
839 regs->nip += 4;
840 return 1;
841 case 0x164: /* mtmsrd */
842 /* only MSR_EE and MSR_RI get changed if bit 15 set */
843 /* mtmsrd doesn't change MSR_HV and MSR_ME */
844 imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
845 imm = (regs->msr & MSR_MASK & ~imm)
846 | (regs->gpr[rd] & imm);
847 if ((imm & MSR_RI) == 0) {
848 printf("Can't step an instruction that would "
849 "clear MSR.RI\n");
850 return -1;
852 regs->msr = imm;
853 regs->nip += 4;
854 return 1;
857 return 0;
860 /* Command interpreting routine */
861 static char *last_cmd;
863 static int
864 cmds(struct pt_regs *excp)
866 int cmd = 0;
868 last_cmd = NULL;
869 xmon_regs = excp;
870 for(;;) {
871 #ifdef CONFIG_SMP
872 printf("%x:", smp_processor_id());
873 #endif /* CONFIG_SMP */
874 printf("mon> ");
875 fflush(stdout);
876 flush_input();
877 termch = 0;
878 cmd = skipbl();
879 if( cmd == '\n' ) {
880 if (last_cmd == NULL)
881 continue;
882 take_input(last_cmd);
883 last_cmd = NULL;
884 cmd = inchar();
886 switch (cmd) {
887 case 'm':
888 cmd = inchar();
889 switch (cmd) {
890 case 'm':
891 case 's':
892 case 'd':
893 memops(cmd);
894 break;
895 case 'l':
896 memlocate();
897 break;
898 case 'z':
899 memzcan();
900 break;
901 case 'i':
902 show_mem();
903 break;
904 default:
905 termch = cmd;
906 memex();
908 break;
909 case 'd':
910 dump();
911 break;
912 case 'l':
913 symbol_lookup();
914 break;
915 case 'r':
916 prregs(excp); /* print regs */
917 break;
918 case 'e':
919 excprint(excp);
920 break;
921 case 'S':
922 super_regs();
923 break;
924 case 't':
925 backtrace(excp);
926 break;
927 case 'f':
928 cacheflush();
929 break;
930 case 's':
931 if (do_step(excp))
932 return cmd;
933 break;
934 case 'x':
935 case 'X':
936 case EOF:
937 return cmd;
938 case '?':
939 printf(help_string);
940 break;
941 case 'p':
942 show_state();
943 break;
944 case 'b':
945 bpt_cmds();
946 break;
947 case 'C':
948 csum();
949 break;
950 case 'c':
951 if (cpu_cmd())
952 return 0;
953 break;
954 case 'z':
955 bootcmds();
956 break;
957 case 'T':
958 debug_trace();
959 break;
960 case 'u':
961 dump_segments();
962 break;
963 default:
964 printf("Unrecognized command: ");
965 do {
966 if (' ' < cmd && cmd <= '~')
967 putchar(cmd);
968 else
969 printf("\\x%x", cmd);
970 cmd = inchar();
971 } while (cmd != '\n');
972 printf(" (type ? for help)\n");
973 break;
979 * Step a single instruction.
980 * Some instructions we emulate, others we execute with MSR_SE set.
982 static int do_step(struct pt_regs *regs)
984 unsigned int instr;
985 int stepped;
987 /* check we are in 64-bit kernel mode, translation enabled */
988 if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
989 if (mread(regs->nip, &instr, 4) == 4) {
990 stepped = emulate_step(regs, instr);
991 if (stepped < 0)
992 return 0;
993 if (stepped > 0) {
994 regs->trap = 0xd00 | (regs->trap & 1);
995 printf("stepped to ");
996 xmon_print_symbol(regs->nip, " ", "\n");
997 ppc_inst_dump(regs->nip, 1, 0);
998 return 0;
1002 regs->msr |= MSR_SE;
1003 return 1;
1006 static void bootcmds(void)
1008 int cmd;
1010 cmd = inchar();
1011 if (cmd == 'r')
1012 ppc_md.restart(NULL);
1013 else if (cmd == 'h')
1014 ppc_md.halt();
1015 else if (cmd == 'p')
1016 ppc_md.power_off();
1019 static int cpu_cmd(void)
1021 #ifdef CONFIG_SMP
1022 unsigned long cpu;
1023 int timeout;
1024 int count;
1026 if (!scanhex(&cpu)) {
1027 /* print cpus waiting or in xmon */
1028 printf("cpus stopped:");
1029 count = 0;
1030 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
1031 if (cpu_isset(cpu, cpus_in_xmon)) {
1032 if (count == 0)
1033 printf(" %x", cpu);
1034 ++count;
1035 } else {
1036 if (count > 1)
1037 printf("-%x", cpu - 1);
1038 count = 0;
1041 if (count > 1)
1042 printf("-%x", NR_CPUS - 1);
1043 printf("\n");
1044 return 0;
1046 /* try to switch to cpu specified */
1047 if (!cpu_isset(cpu, cpus_in_xmon)) {
1048 printf("cpu 0x%x isn't in xmon\n", cpu);
1049 return 0;
1051 xmon_taken = 0;
1052 mb();
1053 xmon_owner = cpu;
1054 timeout = 10000000;
1055 while (!xmon_taken) {
1056 if (--timeout == 0) {
1057 if (test_and_set_bit(0, &xmon_taken))
1058 break;
1059 /* take control back */
1060 mb();
1061 xmon_owner = smp_processor_id();
1062 printf("cpu %u didn't take control\n", cpu);
1063 return 0;
1065 barrier();
1067 return 1;
1068 #else
1069 return 0;
1070 #endif /* CONFIG_SMP */
1073 static unsigned short fcstab[256] = {
1074 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1075 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1076 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1077 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1078 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1079 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1080 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1081 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1082 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1083 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1084 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1085 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1086 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1087 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1088 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1089 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1090 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1091 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1092 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1093 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1094 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1095 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1096 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1097 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1098 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1099 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1100 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1101 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1102 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1103 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1104 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1105 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1108 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1110 static void
1111 csum(void)
1113 unsigned int i;
1114 unsigned short fcs;
1115 unsigned char v;
1117 if (!scanhex(&adrs))
1118 return;
1119 if (!scanhex(&ncsum))
1120 return;
1121 fcs = 0xffff;
1122 for (i = 0; i < ncsum; ++i) {
1123 if (mread(adrs+i, &v, 1) == 0) {
1124 printf("csum stopped at %x\n", adrs+i);
1125 break;
1127 fcs = FCS(fcs, v);
1129 printf("%x\n", fcs);
1133 * Check if this is a suitable place to put a breakpoint.
1135 static long check_bp_loc(unsigned long addr)
1137 unsigned int instr;
1139 addr &= ~3;
1140 if (addr < KERNELBASE) {
1141 printf("Breakpoints may only be placed at kernel addresses\n");
1142 return 0;
1144 if (!mread(addr, &instr, sizeof(instr))) {
1145 printf("Can't read instruction at address %lx\n", addr);
1146 return 0;
1148 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1149 printf("Breakpoints may not be placed on mtmsrd or rfid "
1150 "instructions\n");
1151 return 0;
1153 return 1;
1156 static char *breakpoint_help_string =
1157 "Breakpoint command usage:\n"
1158 "b show breakpoints\n"
1159 "b <addr> [cnt] set breakpoint at given instr addr\n"
1160 "bc clear all breakpoints\n"
1161 "bc <n/addr> clear breakpoint number n or at addr\n"
1162 "bi <addr> [cnt] set hardware instr breakpoint (broken?)\n"
1163 "bd <addr> [cnt] set hardware data breakpoint (broken?)\n"
1166 static void
1167 bpt_cmds(void)
1169 int cmd;
1170 unsigned long a;
1171 int mode, i;
1172 struct bpt *bp;
1173 const char badaddr[] = "Only kernel addresses are permitted "
1174 "for breakpoints\n";
1176 cmd = inchar();
1177 switch (cmd) {
1178 case 'd': /* bd - hardware data breakpoint */
1179 mode = 7;
1180 cmd = inchar();
1181 if (cmd == 'r')
1182 mode = 5;
1183 else if (cmd == 'w')
1184 mode = 6;
1185 else
1186 termch = cmd;
1187 dabr.address = 0;
1188 dabr.enabled = 0;
1189 if (scanhex(&dabr.address)) {
1190 if (dabr.address < KERNELBASE) {
1191 printf(badaddr);
1192 break;
1194 dabr.address &= ~7;
1195 dabr.enabled = mode | BP_DABR;
1197 break;
1199 case 'i': /* bi - hardware instr breakpoint */
1200 if (!(cur_cpu_spec->cpu_features & CPU_FTR_IABR)) {
1201 printf("Hardware instruction breakpoint "
1202 "not supported on this cpu\n");
1203 break;
1205 if (iabr) {
1206 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1207 iabr = NULL;
1209 if (!scanhex(&a))
1210 break;
1211 if (!check_bp_loc(a))
1212 break;
1213 bp = new_breakpoint(a);
1214 if (bp != NULL) {
1215 bp->enabled |= BP_IABR | BP_IABR_TE;
1216 iabr = bp;
1218 break;
1220 case 'c':
1221 if (!scanhex(&a)) {
1222 /* clear all breakpoints */
1223 for (i = 0; i < NBPTS; ++i)
1224 bpts[i].enabled = 0;
1225 iabr = NULL;
1226 dabr.enabled = 0;
1227 printf("All breakpoints cleared\n");
1228 break;
1231 if (a <= NBPTS && a >= 1) {
1232 /* assume a breakpoint number */
1233 bp = &bpts[a-1]; /* bp nums are 1 based */
1234 } else {
1235 /* assume a breakpoint address */
1236 bp = at_breakpoint(a);
1237 if (bp == 0) {
1238 printf("No breakpoint at %x\n", a);
1239 break;
1243 printf("Cleared breakpoint %x (", BP_NUM(bp));
1244 xmon_print_symbol(bp->address, " ", ")\n");
1245 bp->enabled = 0;
1246 break;
1248 default:
1249 termch = cmd;
1250 cmd = skipbl();
1251 if (cmd == '?') {
1252 printf(breakpoint_help_string);
1253 break;
1255 termch = cmd;
1256 if (!scanhex(&a)) {
1257 /* print all breakpoints */
1258 printf(" type address\n");
1259 if (dabr.enabled) {
1260 printf(" data %.16lx [", dabr.address);
1261 if (dabr.enabled & 1)
1262 printf("r");
1263 if (dabr.enabled & 2)
1264 printf("w");
1265 printf("]\n");
1267 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1268 if (!bp->enabled)
1269 continue;
1270 printf("%2x %s ", BP_NUM(bp),
1271 (bp->enabled & BP_IABR)? "inst": "trap");
1272 xmon_print_symbol(bp->address, " ", "\n");
1274 break;
1277 if (!check_bp_loc(a))
1278 break;
1279 bp = new_breakpoint(a);
1280 if (bp != NULL)
1281 bp->enabled |= BP_TRAP;
1282 break;
1286 /* Very cheap human name for vector lookup. */
1287 static
1288 const char *getvecname(unsigned long vec)
1290 char *ret;
1292 switch (vec) {
1293 case 0x100: ret = "(System Reset)"; break;
1294 case 0x200: ret = "(Machine Check)"; break;
1295 case 0x300: ret = "(Data Access)"; break;
1296 case 0x380: ret = "(Data SLB Access)"; break;
1297 case 0x400: ret = "(Instruction Access)"; break;
1298 case 0x480: ret = "(Instruction SLB Access)"; break;
1299 case 0x500: ret = "(Hardware Interrupt)"; break;
1300 case 0x600: ret = "(Alignment)"; break;
1301 case 0x700: ret = "(Program Check)"; break;
1302 case 0x800: ret = "(FPU Unavailable)"; break;
1303 case 0x900: ret = "(Decrementer)"; break;
1304 case 0xc00: ret = "(System Call)"; break;
1305 case 0xd00: ret = "(Single Step)"; break;
1306 case 0xf00: ret = "(Performance Monitor)"; break;
1307 case 0xf20: ret = "(Altivec Unavailable)"; break;
1308 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1309 default: ret = "";
1311 return ret;
1314 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1315 unsigned long *endp)
1317 unsigned long size, offset;
1318 const char *name;
1319 char *modname;
1321 *startp = *endp = 0;
1322 if (pc == 0)
1323 return;
1324 if (setjmp(bus_error_jmp) == 0) {
1325 catch_memory_errors = 1;
1326 sync();
1327 name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
1328 if (name != NULL) {
1329 *startp = pc - offset;
1330 *endp = pc - offset + size;
1332 sync();
1334 catch_memory_errors = 0;
1337 static int xmon_depth_to_print = 64;
1339 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1340 unsigned long pc)
1342 unsigned long ip;
1343 unsigned long newsp;
1344 unsigned long marker;
1345 int count = 0;
1346 struct pt_regs regs;
1348 do {
1349 if (sp < PAGE_OFFSET) {
1350 if (sp != 0)
1351 printf("SP (%lx) is in userspace\n", sp);
1352 break;
1355 if (!mread(sp + 16, &ip, sizeof(unsigned long))
1356 || !mread(sp, &newsp, sizeof(unsigned long))) {
1357 printf("Couldn't read stack frame at %lx\n", sp);
1358 break;
1362 * For the first stack frame, try to work out if
1363 * LR and/or the saved LR value in the bottommost
1364 * stack frame are valid.
1366 if ((pc | lr) != 0) {
1367 unsigned long fnstart, fnend;
1368 unsigned long nextip;
1369 int printip = 1;
1371 get_function_bounds(pc, &fnstart, &fnend);
1372 nextip = 0;
1373 if (newsp > sp)
1374 mread(newsp + 16, &nextip,
1375 sizeof(unsigned long));
1376 if (lr == ip) {
1377 if (lr < PAGE_OFFSET
1378 || (fnstart <= lr && lr < fnend))
1379 printip = 0;
1380 } else if (lr == nextip) {
1381 printip = 0;
1382 } else if (lr >= PAGE_OFFSET
1383 && !(fnstart <= lr && lr < fnend)) {
1384 printf("[link register ] ");
1385 xmon_print_symbol(lr, " ", "\n");
1387 if (printip) {
1388 printf("[%.16lx] ", sp);
1389 xmon_print_symbol(ip, " ", " (unreliable)\n");
1391 pc = lr = 0;
1393 } else {
1394 printf("[%.16lx] ", sp);
1395 xmon_print_symbol(ip, " ", "\n");
1398 /* Look for "regshere" marker to see if this is
1399 an exception frame. */
1400 if (mread(sp + 0x60, &marker, sizeof(unsigned long))
1401 && marker == 0x7265677368657265ul) {
1402 if (mread(sp + 0x70, &regs, sizeof(regs))
1403 != sizeof(regs)) {
1404 printf("Couldn't read registers at %lx\n",
1405 sp + 0x70);
1406 break;
1408 printf("--- Exception: %lx %s at ", regs.trap,
1409 getvecname(TRAP(&regs)));
1410 pc = regs.nip;
1411 lr = regs.link;
1412 xmon_print_symbol(pc, " ", "\n");
1415 if (newsp == 0)
1416 break;
1418 sp = newsp;
1419 } while (count++ < xmon_depth_to_print);
1422 static void backtrace(struct pt_regs *excp)
1424 unsigned long sp;
1426 if (scanhex(&sp))
1427 xmon_show_stack(sp, 0, 0);
1428 else
1429 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1430 scannl();
1433 void excprint(struct pt_regs *fp)
1435 unsigned long trap;
1437 #ifdef CONFIG_SMP
1438 printf("cpu 0x%x: ", smp_processor_id());
1439 #endif /* CONFIG_SMP */
1441 trap = TRAP(fp);
1442 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1443 printf(" pc: ");
1444 xmon_print_symbol(fp->nip, ": ", "\n");
1446 printf(" lr: ", fp->link);
1447 xmon_print_symbol(fp->link, ": ", "\n");
1449 printf(" sp: %lx\n", fp->gpr[1]);
1450 printf(" msr: %lx\n", fp->msr);
1452 if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1453 printf(" dar: %lx\n", fp->dar);
1454 if (trap != 0x380)
1455 printf(" dsisr: %lx\n", fp->dsisr);
1458 printf(" current = 0x%lx\n", current);
1459 printf(" paca = 0x%lx\n", get_paca());
1460 if (current) {
1461 printf(" pid = %ld, comm = %s\n",
1462 current->pid, current->comm);
1466 void prregs(struct pt_regs *fp)
1468 int n;
1469 unsigned long base;
1470 struct pt_regs regs;
1472 if (scanhex(&base)) {
1473 if (setjmp(bus_error_jmp) == 0) {
1474 catch_memory_errors = 1;
1475 sync();
1476 regs = *(struct pt_regs *)base;
1477 sync();
1478 __delay(200);
1479 } else {
1480 catch_memory_errors = 0;
1481 printf("*** Error reading registers from %.16lx\n",
1482 base);
1483 return;
1485 catch_memory_errors = 0;
1486 fp = &regs;
1489 if (FULL_REGS(fp)) {
1490 for (n = 0; n < 16; ++n)
1491 printf("R%.2ld = %.16lx R%.2ld = %.16lx\n",
1492 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1493 } else {
1494 for (n = 0; n < 7; ++n)
1495 printf("R%.2ld = %.16lx R%.2ld = %.16lx\n",
1496 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1498 printf("pc = ");
1499 xmon_print_symbol(fp->nip, " ", "\n");
1500 printf("lr = ");
1501 xmon_print_symbol(fp->link, " ", "\n");
1502 printf("msr = %.16lx cr = %.8lx\n", fp->msr, fp->ccr);
1503 printf("ctr = %.16lx xer = %.16lx trap = %8lx\n",
1504 fp->ctr, fp->xer, fp->trap);
1507 void cacheflush(void)
1509 int cmd;
1510 unsigned long nflush;
1512 cmd = inchar();
1513 if (cmd != 'i')
1514 termch = cmd;
1515 scanhex((void *)&adrs);
1516 if (termch != '\n')
1517 termch = 0;
1518 nflush = 1;
1519 scanhex(&nflush);
1520 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1521 if (setjmp(bus_error_jmp) == 0) {
1522 catch_memory_errors = 1;
1523 sync();
1525 if (cmd != 'i') {
1526 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1527 cflush((void *) adrs);
1528 } else {
1529 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1530 cinval((void *) adrs);
1532 sync();
1533 /* wait a little while to see if we get a machine check */
1534 __delay(200);
1536 catch_memory_errors = 0;
1539 unsigned long
1540 read_spr(int n)
1542 unsigned int instrs[2];
1543 unsigned long (*code)(void);
1544 unsigned long opd[3];
1545 unsigned long ret = -1UL;
1547 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1548 instrs[1] = 0x4e800020;
1549 opd[0] = (unsigned long)instrs;
1550 opd[1] = 0;
1551 opd[2] = 0;
1552 store_inst(instrs);
1553 store_inst(instrs+1);
1554 code = (unsigned long (*)(void)) opd;
1556 ret = code();
1558 return ret;
1561 void
1562 write_spr(int n, unsigned long val)
1564 unsigned int instrs[2];
1565 unsigned long (*code)(unsigned long);
1566 unsigned long opd[3];
1568 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1569 instrs[1] = 0x4e800020;
1570 opd[0] = (unsigned long)instrs;
1571 opd[1] = 0;
1572 opd[2] = 0;
1573 store_inst(instrs);
1574 store_inst(instrs+1);
1575 code = (unsigned long (*)(unsigned long)) opd;
1577 code(val);
1580 static unsigned long regno;
1581 extern char exc_prolog;
1582 extern char dec_exc;
1584 void
1585 super_regs()
1587 int cmd;
1588 unsigned long val;
1589 #ifdef CONFIG_PPC_ISERIES
1590 struct paca_struct *ptrPaca = NULL;
1591 struct ItLpPaca *ptrLpPaca = NULL;
1592 struct ItLpRegSave *ptrLpRegSave = NULL;
1593 #endif
1595 cmd = skipbl();
1596 if (cmd == '\n') {
1597 unsigned long sp, toc;
1598 asm("mr %0,1" : "=r" (sp) :);
1599 asm("mr %0,2" : "=r" (toc) :);
1601 printf("msr = %.16lx sprg0= %.16lx\n", get_msr(), get_sprg0());
1602 printf("pvr = %.16lx sprg1= %.16lx\n", get_pvr(), get_sprg1());
1603 printf("dec = %.16lx sprg2= %.16lx\n", get_dec(), get_sprg2());
1604 printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3());
1605 printf("toc = %.16lx dar = %.16lx\n", toc, get_dar());
1606 printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1());
1607 #ifdef CONFIG_PPC_ISERIES
1608 // Dump out relevant Paca data areas.
1609 printf("Paca: \n");
1610 ptrPaca = get_paca();
1612 printf(" Local Processor Control Area (LpPaca): \n");
1613 ptrLpPaca = ptrPaca->lppaca_ptr;
1614 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1615 ptrLpPaca->xSavedSrr0, ptrLpPaca->xSavedSrr1);
1616 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1617 ptrLpPaca->xSavedGpr3, ptrLpPaca->xSavedGpr4);
1618 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->xSavedGpr5);
1620 printf(" Local Processor Register Save Area (LpRegSave): \n");
1621 ptrLpRegSave = ptrPaca->reg_save_ptr;
1622 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1623 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1624 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1625 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1626 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1627 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1628 #endif
1630 return;
1633 scanhex(&regno);
1634 switch (cmd) {
1635 case 'w':
1636 val = read_spr(regno);
1637 scanhex(&val);
1638 write_spr(regno, val);
1639 /* fall through */
1640 case 'r':
1641 printf("spr %lx = %lx\n", regno, read_spr(regno));
1642 break;
1643 case 'm':
1644 val = get_msr();
1645 scanhex(&val);
1646 set_msrd(val);
1647 break;
1649 scannl();
1653 * Stuff for reading and writing memory safely
1656 mread(unsigned long adrs, void *buf, int size)
1658 volatile int n;
1659 char *p, *q;
1661 n = 0;
1662 if (setjmp(bus_error_jmp) == 0) {
1663 catch_memory_errors = 1;
1664 sync();
1665 p = (char *)adrs;
1666 q = (char *)buf;
1667 switch (size) {
1668 case 2:
1669 *(short *)q = *(short *)p;
1670 break;
1671 case 4:
1672 *(int *)q = *(int *)p;
1673 break;
1674 case 8:
1675 *(long *)q = *(long *)p;
1676 break;
1677 default:
1678 for( ; n < size; ++n) {
1679 *q++ = *p++;
1680 sync();
1683 sync();
1684 /* wait a little while to see if we get a machine check */
1685 __delay(200);
1686 n = size;
1688 catch_memory_errors = 0;
1689 return n;
1693 mwrite(unsigned long adrs, void *buf, int size)
1695 volatile int n;
1696 char *p, *q;
1698 n = 0;
1699 if (setjmp(bus_error_jmp) == 0) {
1700 catch_memory_errors = 1;
1701 sync();
1702 p = (char *) adrs;
1703 q = (char *) buf;
1704 switch (size) {
1705 case 2:
1706 *(short *)p = *(short *)q;
1707 break;
1708 case 4:
1709 *(int *)p = *(int *)q;
1710 break;
1711 case 8:
1712 *(long *)p = *(long *)q;
1713 break;
1714 default:
1715 for ( ; n < size; ++n) {
1716 *p++ = *q++;
1717 sync();
1720 sync();
1721 /* wait a little while to see if we get a machine check */
1722 __delay(200);
1723 n = size;
1724 } else {
1725 printf("*** Error writing address %x\n", adrs + n);
1727 catch_memory_errors = 0;
1728 return n;
1731 static int fault_type;
1732 static char *fault_chars[] = { "--", "**", "##" };
1734 static int
1735 handle_fault(struct pt_regs *regs)
1737 switch (TRAP(regs)) {
1738 case 0x200:
1739 fault_type = 0;
1740 break;
1741 case 0x300:
1742 case 0x380:
1743 fault_type = 1;
1744 break;
1745 default:
1746 fault_type = 2;
1749 longjmp(bus_error_jmp, 1);
1751 return 0;
1754 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1756 void
1757 byterev(unsigned char *val, int size)
1759 int t;
1761 switch (size) {
1762 case 2:
1763 SWAP(val[0], val[1], t);
1764 break;
1765 case 4:
1766 SWAP(val[0], val[3], t);
1767 SWAP(val[1], val[2], t);
1768 break;
1769 case 8: /* is there really any use for this? */
1770 SWAP(val[0], val[7], t);
1771 SWAP(val[1], val[6], t);
1772 SWAP(val[2], val[5], t);
1773 SWAP(val[3], val[4], t);
1774 break;
1778 static int brev;
1779 static int mnoread;
1781 static char *memex_help_string =
1782 "Memory examine command usage:\n"
1783 "m [addr] [flags] examine/change memory\n"
1784 " addr is optional. will start where left off.\n"
1785 " flags may include chars from this set:\n"
1786 " b modify by bytes (default)\n"
1787 " w modify by words (2 byte)\n"
1788 " l modify by longs (4 byte)\n"
1789 " d modify by doubleword (8 byte)\n"
1790 " r toggle reverse byte order mode\n"
1791 " n do not read memory (for i/o spaces)\n"
1792 " . ok to read (default)\n"
1793 "NOTE: flags are saved as defaults\n"
1796 static char *memex_subcmd_help_string =
1797 "Memory examine subcommands:\n"
1798 " hexval write this val to current location\n"
1799 " 'string' write chars from string to this location\n"
1800 " ' increment address\n"
1801 " ^ decrement address\n"
1802 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1803 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1804 " ` clear no-read flag\n"
1805 " ; stay at this addr\n"
1806 " v change to byte mode\n"
1807 " w change to word (2 byte) mode\n"
1808 " l change to long (4 byte) mode\n"
1809 " u change to doubleword (8 byte) mode\n"
1810 " m addr change current addr\n"
1811 " n toggle no-read flag\n"
1812 " r toggle byte reverse flag\n"
1813 " < count back up count bytes\n"
1814 " > count skip forward count bytes\n"
1815 " x exit this mode\n"
1818 void
1819 memex()
1821 int cmd, inc, i, nslash;
1822 unsigned long n;
1823 unsigned char val[16];
1825 scanhex((void *)&adrs);
1826 cmd = skipbl();
1827 if (cmd == '?') {
1828 printf(memex_help_string);
1829 return;
1830 } else {
1831 termch = cmd;
1833 last_cmd = "m\n";
1834 while ((cmd = skipbl()) != '\n') {
1835 switch( cmd ){
1836 case 'b': size = 1; break;
1837 case 'w': size = 2; break;
1838 case 'l': size = 4; break;
1839 case 'd': size = 8; break;
1840 case 'r': brev = !brev; break;
1841 case 'n': mnoread = 1; break;
1842 case '.': mnoread = 0; break;
1845 if( size <= 0 )
1846 size = 1;
1847 else if( size > 8 )
1848 size = 8;
1849 for(;;){
1850 if (!mnoread)
1851 n = mread(adrs, val, size);
1852 printf("%.16x%c", adrs, brev? 'r': ' ');
1853 if (!mnoread) {
1854 if (brev)
1855 byterev(val, size);
1856 putchar(' ');
1857 for (i = 0; i < n; ++i)
1858 printf("%.2x", val[i]);
1859 for (; i < size; ++i)
1860 printf("%s", fault_chars[fault_type]);
1862 putchar(' ');
1863 inc = size;
1864 nslash = 0;
1865 for(;;){
1866 if( scanhex(&n) ){
1867 for (i = 0; i < size; ++i)
1868 val[i] = n >> (i * 8);
1869 if (!brev)
1870 byterev(val, size);
1871 mwrite(adrs, val, size);
1872 inc = size;
1874 cmd = skipbl();
1875 if (cmd == '\n')
1876 break;
1877 inc = 0;
1878 switch (cmd) {
1879 case '\'':
1880 for(;;){
1881 n = inchar();
1882 if( n == '\\' )
1883 n = bsesc();
1884 else if( n == '\'' )
1885 break;
1886 for (i = 0; i < size; ++i)
1887 val[i] = n >> (i * 8);
1888 if (!brev)
1889 byterev(val, size);
1890 mwrite(adrs, val, size);
1891 adrs += size;
1893 adrs -= size;
1894 inc = size;
1895 break;
1896 case ',':
1897 adrs += size;
1898 break;
1899 case '.':
1900 mnoread = 0;
1901 break;
1902 case ';':
1903 break;
1904 case 'x':
1905 case EOF:
1906 scannl();
1907 return;
1908 case 'b':
1909 case 'v':
1910 size = 1;
1911 break;
1912 case 'w':
1913 size = 2;
1914 break;
1915 case 'l':
1916 size = 4;
1917 break;
1918 case 'u':
1919 size = 8;
1920 break;
1921 case '^':
1922 adrs -= size;
1923 break;
1924 break;
1925 case '/':
1926 if (nslash > 0)
1927 adrs -= 1 << nslash;
1928 else
1929 nslash = 0;
1930 nslash += 4;
1931 adrs += 1 << nslash;
1932 break;
1933 case '\\':
1934 if (nslash < 0)
1935 adrs += 1 << -nslash;
1936 else
1937 nslash = 0;
1938 nslash -= 4;
1939 adrs -= 1 << -nslash;
1940 break;
1941 case 'm':
1942 scanhex((void *)&adrs);
1943 break;
1944 case 'n':
1945 mnoread = 1;
1946 break;
1947 case 'r':
1948 brev = !brev;
1949 break;
1950 case '<':
1951 n = size;
1952 scanhex(&n);
1953 adrs -= n;
1954 break;
1955 case '>':
1956 n = size;
1957 scanhex(&n);
1958 adrs += n;
1959 break;
1960 case '?':
1961 printf(memex_subcmd_help_string);
1962 break;
1965 adrs += inc;
1970 bsesc()
1972 int c;
1974 c = inchar();
1975 switch( c ){
1976 case 'n': c = '\n'; break;
1977 case 'r': c = '\r'; break;
1978 case 'b': c = '\b'; break;
1979 case 't': c = '\t'; break;
1981 return c;
1984 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1985 || ('a' <= (c) && (c) <= 'f') \
1986 || ('A' <= (c) && (c) <= 'F'))
1987 void
1988 dump()
1990 int c;
1992 c = inchar();
1993 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1994 termch = c;
1995 scanhex((void *)&adrs);
1996 if( termch != '\n')
1997 termch = 0;
1998 if( c == 'i' ){
1999 scanhex(&nidump);
2000 if( nidump == 0 )
2001 nidump = 16;
2002 adrs += ppc_inst_dump(adrs, nidump, 1);
2003 last_cmd = "di\n";
2004 } else {
2005 scanhex(&ndump);
2006 if( ndump == 0 )
2007 ndump = 64;
2008 prdump(adrs, ndump);
2009 adrs += ndump;
2010 last_cmd = "d\n";
2014 void
2015 prdump(unsigned long adrs, long ndump)
2017 long n, m, c, r, nr;
2018 unsigned char temp[16];
2020 for (n = ndump; n > 0;) {
2021 printf("%.16lx", adrs);
2022 putchar(' ');
2023 r = n < 16? n: 16;
2024 nr = mread(adrs, temp, r);
2025 adrs += nr;
2026 for (m = 0; m < r; ++m) {
2027 if ((m & 7) == 0 && m > 0)
2028 putchar(' ');
2029 if (m < nr)
2030 printf("%.2x", temp[m]);
2031 else
2032 printf("%s", fault_chars[fault_type]);
2034 if (m <= 8)
2035 printf(" ");
2036 for (; m < 16; ++m)
2037 printf(" ");
2038 printf(" |");
2039 for (m = 0; m < r; ++m) {
2040 if (m < nr) {
2041 c = temp[m];
2042 putchar(' ' <= c && c <= '~'? c: '.');
2043 } else
2044 putchar(' ');
2046 n -= r;
2047 for (; m < 16; ++m)
2048 putchar(' ');
2049 printf("|\n");
2050 if (nr < r)
2051 break;
2056 ppc_inst_dump(unsigned long adr, long count, int praddr)
2058 int nr, dotted;
2059 unsigned long first_adr;
2060 unsigned long inst, last_inst = 0;
2061 unsigned char val[4];
2063 dotted = 0;
2064 for (first_adr = adr; count > 0; --count, adr += 4) {
2065 nr = mread(adr, val, 4);
2066 if (nr == 0) {
2067 if (praddr) {
2068 const char *x = fault_chars[fault_type];
2069 printf("%.16lx %s%s%s%s\n", adr, x, x, x, x);
2071 break;
2073 inst = GETWORD(val);
2074 if (adr > first_adr && inst == last_inst) {
2075 if (!dotted) {
2076 printf(" ...\n");
2077 dotted = 1;
2079 continue;
2081 dotted = 0;
2082 last_inst = inst;
2083 if (praddr)
2084 printf("%.16lx %.8x", adr, inst);
2085 printf("\t");
2086 print_insn_powerpc(inst, adr, 0); /* always returns 4 */
2087 printf("\n");
2089 return adr - first_adr;
2092 void
2093 print_address(unsigned long addr)
2095 xmon_print_symbol(addr, "\t# ", "");
2100 * Memory operations - move, set, print differences
2102 static unsigned long mdest; /* destination address */
2103 static unsigned long msrc; /* source address */
2104 static unsigned long mval; /* byte value to set memory to */
2105 static unsigned long mcount; /* # bytes to affect */
2106 static unsigned long mdiffs; /* max # differences to print */
2108 void
2109 memops(int cmd)
2111 scanhex((void *)&mdest);
2112 if( termch != '\n' )
2113 termch = 0;
2114 scanhex((void *)(cmd == 's'? &mval: &msrc));
2115 if( termch != '\n' )
2116 termch = 0;
2117 scanhex((void *)&mcount);
2118 switch( cmd ){
2119 case 'm':
2120 memmove((void *)mdest, (void *)msrc, mcount);
2121 break;
2122 case 's':
2123 memset((void *)mdest, mval, mcount);
2124 break;
2125 case 'd':
2126 if( termch != '\n' )
2127 termch = 0;
2128 scanhex((void *)&mdiffs);
2129 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2130 break;
2134 void
2135 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2137 unsigned n, prt;
2139 prt = 0;
2140 for( n = nb; n > 0; --n )
2141 if( *p1++ != *p2++ )
2142 if( ++prt <= maxpr )
2143 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2144 p1[-1], p2 - 1, p2[-1]);
2145 if( prt > maxpr )
2146 printf("Total of %d differences\n", prt);
2149 static unsigned mend;
2150 static unsigned mask;
2152 void
2153 memlocate()
2155 unsigned a, n;
2156 unsigned char val[4];
2158 last_cmd = "ml";
2159 scanhex((void *)&mdest);
2160 if (termch != '\n') {
2161 termch = 0;
2162 scanhex((void *)&mend);
2163 if (termch != '\n') {
2164 termch = 0;
2165 scanhex((void *)&mval);
2166 mask = ~0;
2167 if (termch != '\n') termch = 0;
2168 scanhex((void *)&mask);
2171 n = 0;
2172 for (a = mdest; a < mend; a += 4) {
2173 if (mread(a, val, 4) == 4
2174 && ((GETWORD(val) ^ mval) & mask) == 0) {
2175 printf("%.16x: %.16x\n", a, GETWORD(val));
2176 if (++n >= 10)
2177 break;
2182 static unsigned long mskip = 0x1000;
2183 static unsigned long mlim = 0xffffffff;
2185 void
2186 memzcan()
2188 unsigned char v;
2189 unsigned a;
2190 int ok, ook;
2192 scanhex(&mdest);
2193 if (termch != '\n') termch = 0;
2194 scanhex(&mskip);
2195 if (termch != '\n') termch = 0;
2196 scanhex(&mlim);
2197 ook = 0;
2198 for (a = mdest; a < mlim; a += mskip) {
2199 ok = mread(a, &v, 1);
2200 if (ok && !ook) {
2201 printf("%.8x .. ", a);
2202 fflush(stdout);
2203 } else if (!ok && ook)
2204 printf("%.8x\n", a - mskip);
2205 ook = ok;
2206 if (a + mskip < a)
2207 break;
2209 if (ook)
2210 printf("%.8x\n", a - mskip);
2213 /* Input scanning routines */
2215 skipbl()
2217 int c;
2219 if( termch != 0 ){
2220 c = termch;
2221 termch = 0;
2222 } else
2223 c = inchar();
2224 while( c == ' ' || c == '\t' )
2225 c = inchar();
2226 return c;
2229 #define N_PTREGS 44
2230 static char *regnames[N_PTREGS] = {
2231 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2232 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2233 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2234 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2235 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "softe",
2236 "trap", "dar", "dsisr", "res"
2240 scanhex(vp)
2241 unsigned long *vp;
2243 int c, d;
2244 unsigned long v;
2246 c = skipbl();
2247 if (c == '%') {
2248 /* parse register name */
2249 char regname[8];
2250 int i;
2252 for (i = 0; i < sizeof(regname) - 1; ++i) {
2253 c = inchar();
2254 if (!isalnum(c)) {
2255 termch = c;
2256 break;
2258 regname[i] = c;
2260 regname[i] = 0;
2261 for (i = 0; i < N_PTREGS; ++i) {
2262 if (strcmp(regnames[i], regname) == 0) {
2263 if (xmon_regs == NULL) {
2264 printf("regs not available\n");
2265 return 0;
2267 *vp = ((unsigned long *)xmon_regs)[i];
2268 return 1;
2271 printf("invalid register name '%%%s'\n", regname);
2272 return 0;
2275 /* skip leading "0x" if any */
2277 if (c == '0') {
2278 c = inchar();
2279 if (c == 'x') {
2280 c = inchar();
2281 } else {
2282 d = hexdigit(c);
2283 if (d == EOF) {
2284 termch = c;
2285 *vp = 0;
2286 return 1;
2289 } else if (c == '$') {
2290 int i;
2291 for (i=0; i<63; i++) {
2292 c = inchar();
2293 if (isspace(c)) {
2294 termch = c;
2295 break;
2297 tmpstr[i] = c;
2299 tmpstr[i++] = 0;
2300 *vp = kallsyms_lookup_name(tmpstr);
2301 if (!(*vp)) {
2302 printf("unknown symbol '%s'\n", tmpstr);
2303 return 0;
2305 return 1;
2308 d = hexdigit(c);
2309 if (d == EOF) {
2310 termch = c;
2311 return 0;
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;
2324 void
2325 scannl()
2327 int c;
2329 c = termch;
2330 termch = 0;
2331 while( c != '\n' )
2332 c = inchar();
2336 hexdigit(int c)
2338 if( '0' <= c && c <= '9' )
2339 return c - '0';
2340 if( 'A' <= c && c <= 'F' )
2341 return c - ('A' - 10);
2342 if( 'a' <= c && c <= 'f' )
2343 return c - ('a' - 10);
2344 return EOF;
2347 void
2348 getstring(char *s, int size)
2350 int c;
2352 c = skipbl();
2353 do {
2354 if( size > 1 ){
2355 *s++ = c;
2356 --size;
2358 c = inchar();
2359 } while( c != ' ' && c != '\t' && c != '\n' );
2360 termch = c;
2361 *s = 0;
2364 static char line[256];
2365 static char *lineptr;
2367 void
2368 flush_input()
2370 lineptr = NULL;
2374 inchar()
2376 if (lineptr == NULL || *lineptr == 0) {
2377 if (fgets(line, sizeof(line), stdin) == NULL) {
2378 lineptr = NULL;
2379 return EOF;
2381 lineptr = line;
2383 return *lineptr++;
2386 void
2387 take_input(str)
2388 char *str;
2390 lineptr = str;
2394 static void
2395 symbol_lookup(void)
2397 int type = inchar();
2398 unsigned long addr;
2399 static char tmp[64];
2401 switch (type) {
2402 case 'a':
2403 if (scanhex(&addr))
2404 xmon_print_symbol(addr, ": ", "\n");
2405 termch = 0;
2406 break;
2407 case 's':
2408 getstring(tmp, 64);
2409 if (setjmp(bus_error_jmp) == 0) {
2410 catch_memory_errors = 1;
2411 sync();
2412 addr = kallsyms_lookup_name(tmp);
2413 if (addr)
2414 printf("%s: %lx\n", tmp, addr);
2415 else
2416 printf("Symbol '%s' not found.\n", tmp);
2417 sync();
2419 catch_memory_errors = 0;
2420 termch = 0;
2421 break;
2426 /* Print an address in numeric and symbolic form (if possible) */
2427 static void xmon_print_symbol(unsigned long address, const char *mid,
2428 const char *after)
2430 char *modname;
2431 const char *name = NULL;
2432 unsigned long offset, size;
2434 printf("%.16lx", address);
2435 if (setjmp(bus_error_jmp) == 0) {
2436 catch_memory_errors = 1;
2437 sync();
2438 name = kallsyms_lookup(address, &size, &offset, &modname,
2439 tmpstr);
2440 sync();
2441 /* wait a little while to see if we get a machine check */
2442 __delay(200);
2445 catch_memory_errors = 0;
2447 if (name) {
2448 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2449 if (modname)
2450 printf(" [%s]", modname);
2452 printf("%s", after);
2455 static void debug_trace(void)
2457 unsigned long val, cmd, on;
2459 cmd = skipbl();
2460 if (cmd == '\n') {
2461 /* show current state */
2462 unsigned long i;
2463 printf("naca->debug_switch = 0x%lx\n", naca->debug_switch);
2464 for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) {
2465 on = PPCDBG_BITVAL(i) & naca->debug_switch;
2466 printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : "");
2467 if (((i+1) % 3) == 0)
2468 printf("\n");
2470 printf("\n");
2471 return;
2473 while (cmd != '\n') {
2474 on = 1; /* default if no sign given */
2475 while (cmd == '+' || cmd == '-') {
2476 on = (cmd == '+');
2477 cmd = inchar();
2478 if (cmd == ' ' || cmd == '\n') { /* Turn on or off based on + or - */
2479 naca->debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE;
2480 printf("Setting all values to %s...\n", on ? "on" : "off");
2481 if (cmd == '\n') return;
2482 else cmd = skipbl();
2484 else
2485 termch = cmd;
2487 termch = cmd; /* not +/- ... let scanhex see it */
2488 scanhex((void *)&val);
2489 if (val >= 64) {
2490 printf("Value %x out of range:\n", val);
2491 return;
2493 if (on) {
2494 naca->debug_switch |= PPCDBG_BITVAL(val);
2495 printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2496 } else {
2497 naca->debug_switch &= ~PPCDBG_BITVAL(val);
2498 printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2500 cmd = skipbl();
2504 static void dump_slb(void)
2506 int i;
2507 unsigned long tmp;
2509 printf("SLB contents of cpu %x\n", smp_processor_id());
2511 for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2512 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2513 printf("%02d %016lx ", i, tmp);
2515 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2516 printf("%016lx\n", tmp);
2520 static void dump_stab(void)
2522 int i;
2523 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2525 printf("Segment table contents of cpu %x\n", smp_processor_id());
2527 for (i = 0; i < PAGE_SIZE/16; i++) {
2528 unsigned long a, b;
2530 a = *tmp++;
2531 b = *tmp++;
2533 if (a || b) {
2534 printf("%03d %016lx ", i, a);
2535 printf("%016lx\n", b);
2540 void xmon_init(void)
2542 __debugger = xmon;
2543 __debugger_ipi = xmon_ipi;
2544 __debugger_bpt = xmon_bpt;
2545 __debugger_sstep = xmon_sstep;
2546 __debugger_iabr_match = xmon_iabr_match;
2547 __debugger_dabr_match = xmon_dabr_match;
2548 __debugger_fault_handler = xmon_fault_handler;
2551 void dump_segments(void)
2553 if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
2554 dump_slb();
2555 else
2556 dump_stab();