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