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