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