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