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