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