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