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>
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>
24 #include <asm/machdep.h>
25 #include <asm/processor.h>
26 #include <asm/pgtable.h>
28 #include <asm/mmu_context.h>
31 #include <asm/ppcdebug.h>
32 #include <asm/cputable.h>
38 #define scanhex xmon_scanhex
39 #define skipbl xmon_skipbl
42 volatile cpumask_t cpus_in_xmon
= CPU_MASK_NONE
;
43 static unsigned long xmon_taken
= 1;
44 static int xmon_owner
;
46 #endif /* CONFIG_SMP */
48 static unsigned long in_xmon
= 0;
50 static unsigned long adrs
;
52 static unsigned long ndump
= 64;
53 static unsigned long nidump
= 16;
54 static unsigned long ncsum
= 4096;
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 */
67 unsigned long address
;
68 unsigned int instr
[2];
74 /* Bits in bpt.enabled */
75 #define BP_IABR_TE 1 /* IABR translation enabled */
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
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);
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
,
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
= "\
167 b show breakpoints\n\
168 bd set data breakpoint\n\
169 bi set instruction breakpoint\n\
170 bc clear breakpoint\n"
173 c print cpus stopped in xmon\n\
174 c# try to switch to cpu number h (in hex)\n"
179 di dump instructions\n\
180 df dump float values\n\
181 dd dump double values\n\
182 e print exception information\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\
196 S print special registers\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\
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:
223 Parameter save area (SP+48)
224 TOC save area (SP+40)
225 link editor doubleword (SP+32)
226 compiler doubleword (SP+24)
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
)
271 args
.rets
= &args
.args
[3];
272 args
.args
[0] = SURVEILLANCE_TOKEN
;
275 enter_rtas(__pa(&args
));
276 #endif /* CONFIG_PPC_PSERIES */
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
;
288 if (xmon_speaker
== me
)
291 if (xmon_speaker
== 0) {
292 last_speaker
= cmpxchg(&xmon_speaker
, 0, me
);
293 if (last_speaker
== 0)
297 while (xmon_speaker
== last_speaker
) {
300 /* hostile takeover */
301 prev
= cmpxchg(&xmon_speaker
, last_speaker
, me
);
302 if (prev
== last_speaker
)
309 static void release_output_lock(void)
315 int xmon_core(struct pt_regs
*regs
, int fromipi
)
320 long recurse_jmp
[JMP_BUF_LEN
];
321 unsigned long offset
;
325 unsigned long timeout
;
329 set_msrd(msr
& ~MSR_EE
); /* disable interrupts */
331 bp
= in_breakpoint_table(regs
->nip
, &offset
);
333 regs
->nip
= bp
->address
+ offset
;
334 atomic_dec(&bp
->ref_count
);
340 cpu
= smp_processor_id();
341 if (cpu_isset(cpu
, cpus_in_xmon
)) {
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
);
356 secondary
= !(xmon_taken
&& cpu
== xmon_owner
);
360 xmon_fault_jmp
[cpu
] = recurse_jmp
;
361 cpu_set(cpu
, cpus_in_xmon
);
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)
373 printf("cpu 0x%x stopped at breakpoint 0x%x (",
375 xmon_print_symbol(regs
->nip
, " ", ")\n");
377 if ((regs
->msr
& MSR_RI
) == 0)
378 printf("WARNING: exception is not recoverable, "
380 release_output_lock();
385 while (secondary
&& !xmon_gate
) {
389 secondary
= test_and_set_bit(0, &in_xmon
);
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();
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
)
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");
422 if (cpu
== xmon_owner
) {
423 if (!test_and_set_bit(0, &xmon_taken
)) {
428 while (cpu
== xmon_owner
)
442 /* have switched to some other cpu */
447 cpu_clear(cpu
, cpus_in_xmon
);
448 xmon_fault_jmp
[cpu
] = NULL
;
451 /* UP is simple... */
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
;
462 bp
= at_breakpoint(regs
->nip
);
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, "
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");
484 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
)) {
485 bp
= at_breakpoint(regs
->nip
);
487 int stepped
= emulate_step(regs
, bp
->instr
[0]);
489 regs
->nip
= (unsigned long) &bp
->instr
[0];
490 atomic_inc(&bp
->ref_count
);
497 set_msrd(msr
); /* restore interrupt enable */
502 int xmon(struct pt_regs
*excp
)
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
514 asm volatile ("std 0,0(%0)\n\
545 std 31,248(%0)" : : "b" (®s
));
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();
555 return xmon_core(excp
, 0);
558 int xmon_bpt(struct pt_regs
*regs
)
561 unsigned long offset
;
563 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
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
);
574 /* Are we at a breakpoint? */
575 bp
= at_breakpoint(regs
->nip
);
584 int xmon_sstep(struct pt_regs
*regs
)
592 int xmon_dabr_match(struct pt_regs
*regs
)
594 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
600 int xmon_iabr_match(struct pt_regs
*regs
)
602 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
610 int xmon_ipi(struct pt_regs
*regs
)
613 if (in_xmon
&& !cpu_isset(smp_processor_id(), cpus_in_xmon
))
619 int xmon_fault_handler(struct pt_regs
*regs
)
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
);
630 regs
->nip
= bp
->address
+ offset
;
631 atomic_dec(&bp
->ref_count
);
639 static struct bpt
*at_breakpoint(unsigned long pc
)
645 for (i
= 0; i
< NBPTS
; ++i
, ++bp
)
646 if (bp
->enabled
&& pc
== bp
->address
)
651 static struct bpt
*in_breakpoint_table(unsigned long nip
, unsigned long *offp
)
655 off
= nip
- (unsigned long) bpts
;
656 if (off
>= sizeof(bpts
))
658 off
%= sizeof(struct bpt
);
659 if (off
!= offsetof(struct bpt
, instr
[0])
660 && off
!= offsetof(struct bpt
, instr
[1]))
662 *offp
= off
- offsetof(struct bpt
, instr
[0]);
663 return (struct bpt
*) (nip
- off
);
666 static struct bpt
*new_breakpoint(unsigned long a
)
671 bp
= at_breakpoint(a
);
675 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
676 if (!bp
->enabled
&& atomic_read(&bp
->ref_count
) == 0) {
678 bp
->instr
[1] = bpinstr
;
679 store_inst(&bp
->instr
[1]);
684 printf("Sorry, no free breakpoints. Please clear one first.\n");
688 static void insert_bpts(void)
694 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
695 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) == 0)
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
);
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
);
709 store_inst(&bp
->instr
[0]);
710 if (bp
->enabled
& BP_IABR
)
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
;
718 store_inst((void *)bp
->address
);
722 static void insert_cpu_bpts(void)
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)
738 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
739 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) != BP_TRAP
)
741 if (mread(bp
->address
, &instr
, 4) == 4
743 && mwrite(bp
->address
, &bp
->instr
, 4) != 4)
744 printf("Couldn't remove breakpoint at %lx\n",
747 store_inst((void *)bp
->address
);
751 static void remove_cpu_bpts(void)
754 if ((cur_cpu_spec
->cpu_features
& CPU_FTR_IABR
))
758 static int branch_taken(unsigned int instr
, struct pt_regs
*regs
)
760 unsigned int bo
= (instr
>> 21) & 0x1f;
764 /* decrement counter */
766 if (((bo
>> 1) & 1) ^ (regs
->ctr
== 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))
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;
792 imm
= (signed short)(instr
& 0xfffc);
793 if ((instr
& 2) == 0)
795 regs
->nip
+= 4; /* XXX check 32-bit mode */
797 regs
->link
= regs
->nip
;
798 if (branch_taken(instr
, regs
))
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
;
810 imm
= instr
& 0x03fffffc;
811 if (imm
& 0x02000000)
813 if ((instr
& 2) == 0)
816 regs
->link
= regs
->nip
+ 4;
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 */
826 regs
->link
= regs
->nip
;
827 if (branch_taken(instr
, regs
))
830 case 0x24: /* rfid, scary */
831 printf("Can't single-step an rfid instruction\n");
835 rd
= (instr
>> 21) & 0x1f;
836 switch (instr
& 0x7fe) {
837 case 0xa6: /* mfmsr */
838 regs
->gpr
[rd
] = regs
->msr
& MSR_MASK
;
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 "
860 /* Command interpreting routine */
861 static char *last_cmd
;
864 cmds(struct pt_regs
*excp
)
872 printf("%x:", smp_processor_id());
873 #endif /* CONFIG_SMP */
880 if (last_cmd
== NULL
)
882 take_input(last_cmd
);
916 prregs(excp
); /* print regs */
964 printf("Unrecognized command: ");
966 if (' ' < cmd
&& cmd
<= '~')
969 printf("\\x%x", cmd
);
971 } while (cmd
!= '\n');
972 printf(" (type ? for help)\n");
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
)
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
);
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);
1002 regs
->msr
|= MSR_SE
;
1006 static void bootcmds(void)
1012 ppc_md
.restart(NULL
);
1013 else if (cmd
== 'h')
1015 else if (cmd
== 'p')
1019 static int cpu_cmd(void)
1026 if (!scanhex(&cpu
)) {
1027 /* print cpus waiting or in xmon */
1028 printf("cpus stopped:");
1030 for (cpu
= 0; cpu
< NR_CPUS
; ++cpu
) {
1031 if (cpu_isset(cpu
, cpus_in_xmon
)) {
1037 printf("-%x", cpu
- 1);
1042 printf("-%x", NR_CPUS
- 1);
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
);
1055 while (!xmon_taken
) {
1056 if (--timeout
== 0) {
1057 if (test_and_set_bit(0, &xmon_taken
))
1059 /* take control back */
1061 xmon_owner
= smp_processor_id();
1062 printf("cpu %u didn't take control\n", cpu
);
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])
1117 if (!scanhex(&adrs
))
1119 if (!scanhex(&ncsum
))
1122 for (i
= 0; i
< ncsum
; ++i
) {
1123 if (mread(adrs
+i
, &v
, 1) == 0) {
1124 printf("csum stopped at %x\n", adrs
+i
);
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
)
1140 if (addr
< KERNELBASE
) {
1141 printf("Breakpoints may only be placed at kernel addresses\n");
1144 if (!mread(addr
, &instr
, sizeof(instr
))) {
1145 printf("Can't read instruction at address %lx\n", addr
);
1148 if (IS_MTMSRD(instr
) || IS_RFID(instr
)) {
1149 printf("Breakpoints may not be placed on mtmsrd or rfid "
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"
1173 const char badaddr
[] = "Only kernel addresses are permitted "
1174 "for breakpoints\n";
1178 case 'd': /* bd - hardware data breakpoint */
1183 else if (cmd
== 'w')
1189 if (scanhex(&dabr
.address
)) {
1190 if (dabr
.address
< KERNELBASE
) {
1195 dabr
.enabled
= mode
| BP_DABR
;
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");
1206 iabr
->enabled
&= ~(BP_IABR
| BP_IABR_TE
);
1211 if (!check_bp_loc(a
))
1213 bp
= new_breakpoint(a
);
1215 bp
->enabled
|= BP_IABR
| BP_IABR_TE
;
1222 /* clear all breakpoints */
1223 for (i
= 0; i
< NBPTS
; ++i
)
1224 bpts
[i
].enabled
= 0;
1227 printf("All breakpoints cleared\n");
1231 if (a
<= NBPTS
&& a
>= 1) {
1232 /* assume a breakpoint number */
1233 bp
= &bpts
[a
-1]; /* bp nums are 1 based */
1235 /* assume a breakpoint address */
1236 bp
= at_breakpoint(a
);
1238 printf("No breakpoint at %x\n", a
);
1243 printf("Cleared breakpoint %x (", BP_NUM(bp
));
1244 xmon_print_symbol(bp
->address
, " ", ")\n");
1252 printf(breakpoint_help_string
);
1257 /* print all breakpoints */
1258 printf(" type address\n");
1260 printf(" data %.16lx [", dabr
.address
);
1261 if (dabr
.enabled
& 1)
1263 if (dabr
.enabled
& 2)
1267 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
1270 printf("%2x %s ", BP_NUM(bp
),
1271 (bp
->enabled
& BP_IABR
)? "inst": "trap");
1272 xmon_print_symbol(bp
->address
, " ", "\n");
1277 if (!check_bp_loc(a
))
1279 bp
= new_breakpoint(a
);
1281 bp
->enabled
|= BP_TRAP
;
1286 /* Very cheap human name for vector lookup. */
1288 const char *getvecname(unsigned long 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;
1314 static void get_function_bounds(unsigned long pc
, unsigned long *startp
,
1315 unsigned long *endp
)
1317 unsigned long size
, offset
;
1321 *startp
= *endp
= 0;
1324 if (setjmp(bus_error_jmp
) == 0) {
1325 catch_memory_errors
= 1;
1327 name
= kallsyms_lookup(pc
, &size
, &offset
, &modname
, tmpstr
);
1329 *startp
= pc
- offset
;
1330 *endp
= pc
- offset
+ size
;
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
,
1343 unsigned long newsp
;
1344 unsigned long marker
;
1346 struct pt_regs regs
;
1349 if (sp
< PAGE_OFFSET
) {
1351 printf("SP (%lx) is in userspace\n", sp
);
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
);
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
;
1371 get_function_bounds(pc
, &fnstart
, &fnend
);
1374 mread(newsp
+ 16, &nextip
,
1375 sizeof(unsigned long));
1377 if (lr
< PAGE_OFFSET
1378 || (fnstart
<= lr
&& lr
< fnend
))
1380 } else if (lr
== nextip
) {
1382 } else if (lr
>= PAGE_OFFSET
1383 && !(fnstart
<= lr
&& lr
< fnend
)) {
1384 printf("[link register ] ");
1385 xmon_print_symbol(lr
, " ", "\n");
1388 printf("[%.16lx] ", sp
);
1389 xmon_print_symbol(ip
, " ", " (unreliable)\n");
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, ®s
, sizeof(regs
))
1404 printf("Couldn't read registers at %lx\n",
1408 printf("--- Exception: %lx %s at ", regs
.trap
,
1409 getvecname(TRAP(®s
)));
1412 xmon_print_symbol(pc
, " ", "\n");
1419 } while (count
++ < xmon_depth_to_print
);
1422 static void backtrace(struct pt_regs
*excp
)
1427 xmon_show_stack(sp
, 0, 0);
1429 xmon_show_stack(excp
->gpr
[1], excp
->link
, excp
->nip
);
1433 void excprint(struct pt_regs
*fp
)
1438 printf("cpu 0x%x: ", smp_processor_id());
1439 #endif /* CONFIG_SMP */
1442 printf("Vector: %lx %s at [%lx]\n", fp
->trap
, getvecname(trap
), fp
);
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
);
1455 printf(" dsisr: %lx\n", fp
->dsisr
);
1458 printf(" current = 0x%lx\n", current
);
1459 printf(" paca = 0x%lx\n", get_paca());
1461 printf(" pid = %ld, comm = %s\n",
1462 current
->pid
, current
->comm
);
1466 void prregs(struct pt_regs
*fp
)
1470 struct pt_regs regs
;
1472 if (scanhex(&base
)) {
1473 if (setjmp(bus_error_jmp
) == 0) {
1474 catch_memory_errors
= 1;
1476 regs
= *(struct pt_regs
*)base
;
1480 catch_memory_errors
= 0;
1481 printf("*** Error reading registers from %.16lx\n",
1485 catch_memory_errors
= 0;
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]);
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]);
1499 xmon_print_symbol(fp
->nip
, " ", "\n");
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)
1510 unsigned long nflush
;
1515 scanhex((void *)&adrs
);
1520 nflush
= (nflush
+ L1_CACHE_BYTES
- 1) / L1_CACHE_BYTES
;
1521 if (setjmp(bus_error_jmp
) == 0) {
1522 catch_memory_errors
= 1;
1526 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1527 cflush((void *) adrs
);
1529 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1530 cinval((void *) adrs
);
1533 /* wait a little while to see if we get a machine check */
1536 catch_memory_errors
= 0;
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
;
1553 store_inst(instrs
+1);
1554 code
= (unsigned long (*)(void)) opd
;
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
;
1574 store_inst(instrs
+1);
1575 code
= (unsigned long (*)(unsigned long)) opd
;
1580 static unsigned long regno
;
1581 extern char exc_prolog
;
1582 extern char dec_exc
;
1589 #ifdef CONFIG_PPC_ISERIES
1590 struct paca_struct
*ptrPaca
= NULL
;
1591 struct ItLpPaca
*ptrLpPaca
= NULL
;
1592 struct ItLpRegSave
*ptrLpRegSave
= NULL
;
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.
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
);
1636 val
= read_spr(regno
);
1638 write_spr(regno
, val
);
1641 printf("spr %lx = %lx\n", regno
, read_spr(regno
));
1653 * Stuff for reading and writing memory safely
1656 mread(unsigned long adrs
, void *buf
, int size
)
1662 if (setjmp(bus_error_jmp
) == 0) {
1663 catch_memory_errors
= 1;
1669 *(short *)q
= *(short *)p
;
1672 *(int *)q
= *(int *)p
;
1675 *(long *)q
= *(long *)p
;
1678 for( ; n
< size
; ++n
) {
1684 /* wait a little while to see if we get a machine check */
1688 catch_memory_errors
= 0;
1693 mwrite(unsigned long adrs
, void *buf
, int size
)
1699 if (setjmp(bus_error_jmp
) == 0) {
1700 catch_memory_errors
= 1;
1706 *(short *)p
= *(short *)q
;
1709 *(int *)p
= *(int *)q
;
1712 *(long *)p
= *(long *)q
;
1715 for ( ; n
< size
; ++n
) {
1721 /* wait a little while to see if we get a machine check */
1725 printf("*** Error writing address %x\n", adrs
+ n
);
1727 catch_memory_errors
= 0;
1731 static int fault_type
;
1732 static char *fault_chars
[] = { "--", "**", "##" };
1735 handle_fault(struct pt_regs
*regs
)
1737 switch (TRAP(regs
)) {
1749 longjmp(bus_error_jmp
, 1);
1754 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1757 byterev(unsigned char *val
, int size
)
1763 SWAP(val
[0], val
[1], t
);
1766 SWAP(val
[0], val
[3], t
);
1767 SWAP(val
[1], val
[2], t
);
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
);
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"
1821 int cmd
, inc
, i
, nslash
;
1823 unsigned char val
[16];
1825 scanhex((void *)&adrs
);
1828 printf(memex_help_string
);
1834 while ((cmd
= skipbl()) != '\n') {
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;
1851 n
= mread(adrs
, val
, size
);
1852 printf("%.16x%c", adrs
, brev
? 'r': ' ');
1857 for (i
= 0; i
< n
; ++i
)
1858 printf("%.2x", val
[i
]);
1859 for (; i
< size
; ++i
)
1860 printf("%s", fault_chars
[fault_type
]);
1867 for (i
= 0; i
< size
; ++i
)
1868 val
[i
] = n
>> (i
* 8);
1871 mwrite(adrs
, val
, size
);
1884 else if( n
== '\'' )
1886 for (i
= 0; i
< size
; ++i
)
1887 val
[i
] = n
>> (i
* 8);
1890 mwrite(adrs
, val
, size
);
1927 adrs
-= 1 << nslash
;
1931 adrs
+= 1 << nslash
;
1935 adrs
+= 1 << -nslash
;
1939 adrs
-= 1 << -nslash
;
1942 scanhex((void *)&adrs
);
1961 printf(memex_subcmd_help_string
);
1976 case 'n': c
= '\n'; break;
1977 case 'r': c
= '\r'; break;
1978 case 'b': c
= '\b'; break;
1979 case 't': c
= '\t'; break;
1984 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1985 || ('a' <= (c) && (c) <= 'f') \
1986 || ('A' <= (c) && (c) <= 'F'))
1993 if ((isxdigit(c
) && c
!= 'f' && c
!= 'd') || c
== '\n')
1995 scanhex((void *)&adrs
);
2002 adrs
+= ppc_inst_dump(adrs
, nidump
, 1);
2008 prdump(adrs
, ndump
);
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
);
2024 nr
= mread(adrs
, temp
, r
);
2026 for (m
= 0; m
< r
; ++m
) {
2027 if ((m
& 7) == 0 && m
> 0)
2030 printf("%.2x", temp
[m
]);
2032 printf("%s", fault_chars
[fault_type
]);
2039 for (m
= 0; m
< r
; ++m
) {
2042 putchar(' ' <= c
&& c
<= '~'? c
: '.');
2056 ppc_inst_dump(unsigned long adr
, long count
, int praddr
)
2059 unsigned long first_adr
;
2060 unsigned long inst
, last_inst
= 0;
2061 unsigned char val
[4];
2064 for (first_adr
= adr
; count
> 0; --count
, adr
+= 4) {
2065 nr
= mread(adr
, val
, 4);
2068 const char *x
= fault_chars
[fault_type
];
2069 printf("%.16lx %s%s%s%s\n", adr
, x
, x
, x
, x
);
2073 inst
= GETWORD(val
);
2074 if (adr
> first_adr
&& inst
== last_inst
) {
2084 printf("%.16lx %.8x", adr
, inst
);
2086 print_insn_powerpc(inst
, adr
, 0); /* always returns 4 */
2089 return adr
- first_adr
;
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 */
2111 scanhex((void *)&mdest
);
2112 if( termch
!= '\n' )
2114 scanhex((void *)(cmd
== 's'? &mval
: &msrc
));
2115 if( termch
!= '\n' )
2117 scanhex((void *)&mcount
);
2120 memmove((void *)mdest
, (void *)msrc
, mcount
);
2123 memset((void *)mdest
, mval
, mcount
);
2126 if( termch
!= '\n' )
2128 scanhex((void *)&mdiffs
);
2129 memdiffs((unsigned char *)mdest
, (unsigned char *)msrc
, mcount
, mdiffs
);
2135 memdiffs(unsigned char *p1
, unsigned char *p2
, unsigned nb
, unsigned maxpr
)
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]);
2146 printf("Total of %d differences\n", prt
);
2149 static unsigned mend
;
2150 static unsigned mask
;
2156 unsigned char val
[4];
2159 scanhex((void *)&mdest
);
2160 if (termch
!= '\n') {
2162 scanhex((void *)&mend
);
2163 if (termch
!= '\n') {
2165 scanhex((void *)&mval
);
2167 if (termch
!= '\n') termch
= 0;
2168 scanhex((void *)&mask
);
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
));
2182 static unsigned long mskip
= 0x1000;
2183 static unsigned long mlim
= 0xffffffff;
2193 if (termch
!= '\n') termch
= 0;
2195 if (termch
!= '\n') termch
= 0;
2198 for (a
= mdest
; a
< mlim
; a
+= mskip
) {
2199 ok
= mread(a
, &v
, 1);
2201 printf("%.8x .. ", a
);
2203 } else if (!ok
&& ook
)
2204 printf("%.8x\n", a
- mskip
);
2210 printf("%.8x\n", a
- mskip
);
2213 /* Input scanning routines */
2224 while( c
== ' ' || c
== '\t' )
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"
2248 /* parse register name */
2252 for (i
= 0; i
< sizeof(regname
) - 1; ++i
) {
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");
2267 *vp
= ((unsigned long *)xmon_regs
)[i
];
2271 printf("invalid register name '%%%s'\n", regname
);
2275 /* skip leading "0x" if any */
2289 } else if (c
== '$') {
2291 for (i
=0; i
<63; i
++) {
2300 *vp
= kallsyms_lookup_name(tmpstr
);
2302 printf("unknown symbol '%s'\n", tmpstr
);
2338 if( '0' <= c
&& c
<= '9' )
2340 if( 'A' <= c
&& c
<= 'F' )
2341 return c
- ('A' - 10);
2342 if( 'a' <= c
&& c
<= 'f' )
2343 return c
- ('a' - 10);
2348 getstring(char *s
, int size
)
2359 } while( c
!= ' ' && c
!= '\t' && c
!= '\n' );
2364 static char line
[256];
2365 static char *lineptr
;
2376 if (lineptr
== NULL
|| *lineptr
== 0) {
2377 if (fgets(line
, sizeof(line
), stdin
) == NULL
) {
2397 int type
= inchar();
2399 static char tmp
[64];
2404 xmon_print_symbol(addr
, ": ", "\n");
2409 if (setjmp(bus_error_jmp
) == 0) {
2410 catch_memory_errors
= 1;
2412 addr
= kallsyms_lookup_name(tmp
);
2414 printf("%s: %lx\n", tmp
, addr
);
2416 printf("Symbol '%s' not found.\n", tmp
);
2419 catch_memory_errors
= 0;
2426 /* Print an address in numeric and symbolic form (if possible) */
2427 static void xmon_print_symbol(unsigned long address
, const char *mid
,
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;
2438 name
= kallsyms_lookup(address
, &size
, &offset
, &modname
,
2441 /* wait a little while to see if we get a machine check */
2445 catch_memory_errors
= 0;
2448 printf("%s%s+%#lx/%#lx", mid
, name
, offset
, size
);
2450 printf(" [%s]", modname
);
2452 printf("%s", after
);
2455 static void debug_trace(void)
2457 unsigned long val
, cmd
, on
;
2461 /* show current state */
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)
2473 while (cmd
!= '\n') {
2474 on
= 1; /* default if no sign given */
2475 while (cmd
== '+' || cmd
== '-') {
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();
2487 termch
= cmd
; /* not +/- ... let scanhex see it */
2488 scanhex((void *)&val
);
2490 printf("Value %x out of range:\n", val
);
2494 naca
->debug_switch
|= PPCDBG_BITVAL(val
);
2495 printf("enable debug %x %s\n", val
, trace_names
[val
] ? trace_names
[val
] : "");
2497 naca
->debug_switch
&= ~PPCDBG_BITVAL(val
);
2498 printf("disable debug %x %s\n", val
, trace_names
[val
] ? trace_names
[val
] : "");
2504 static void dump_slb(void)
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)
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
++) {
2534 printf("%03d %016lx ", i
, a
);
2535 printf("%016lx\n", b
);
2540 void xmon_init(void)
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
)