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