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