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