]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - arch/powerpc/xmon/xmon.c
powerpc/64: Use array of paca pointers and allocate pacas individually
[mirror_ubuntu-focal-kernel.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 */
56144ec7
ME
13
14#include <linux/kernel.h>
1da177e4 15#include <linux/errno.h>
3f07c014 16#include <linux/sched/signal.h>
1da177e4
LT
17#include <linux/smp.h>
18#include <linux/mm.h>
19#include <linux/reboot.h>
20#include <linux/delay.h>
21#include <linux/kallsyms.h>
ca5dd395 22#include <linux/kmsg_dump.h>
1da177e4 23#include <linux/cpumask.h>
4b16f8e2 24#include <linux/export.h>
fca5dcd4 25#include <linux/sysrq.h>
4694ca02 26#include <linux/interrupt.h>
7d12e780 27#include <linux/irq.h>
73c9ceab 28#include <linux/bug.h>
a71d64b4 29#include <linux/nmi.h>
05b981f4 30#include <linux/ctype.h>
80eff6c4 31#include <linux/highmem.h>
1da177e4 32
7644d581 33#include <asm/debugfs.h>
1da177e4 34#include <asm/ptrace.h>
243e2511 35#include <asm/smp.h>
1da177e4
LT
36#include <asm/string.h>
37#include <asm/prom.h>
38#include <asm/machdep.h>
f78541dc 39#include <asm/xmon.h>
1da177e4
LT
40#include <asm/processor.h>
41#include <asm/pgtable.h>
42#include <asm/mmu.h>
43#include <asm/mmu_context.h>
1da177e4
LT
44#include <asm/cputable.h>
45#include <asm/rtas.h>
46#include <asm/sstep.h>
f583ffce 47#include <asm/irq_regs.h>
ff8a8f25
ME
48#include <asm/spu.h>
49#include <asm/spu_priv1.h>
c3b75bd7 50#include <asm/setjmp.h>
322b4394 51#include <asm/reg.h>
ae3a197e 52#include <asm/debug.h>
9422de3e 53#include <asm/hw_breakpoint.h>
243e2511 54#include <asm/xive.h>
fde93a0f
AD
55#include <asm/opal.h>
56#include <asm/firmware.h>
efe4fbb1 57#include <asm/code-patching.h>
fde93a0f 58
f78541dc 59#ifdef CONFIG_PPC64
1da177e4 60#include <asm/hvcall.h>
f78541dc
PM
61#include <asm/paca.h>
62#endif
1da177e4 63
1ad7d705
AK
64#if defined(CONFIG_PPC_SPLPAR)
65#include <asm/plpar_wrappers.h>
66#else
67static inline long plapr_set_ciabr(unsigned long ciabr) {return 0; };
68#endif
69
1da177e4 70#include "nonstdio.h"
e0426047 71#include "dis-asm.h"
1da177e4 72
1da177e4 73#ifdef CONFIG_SMP
1c8950ff 74static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
1da177e4
LT
75static unsigned long xmon_taken = 1;
76static int xmon_owner;
77static int xmon_gate;
ddadb6b8
ME
78#else
79#define xmon_owner 0
1da177e4
LT
80#endif /* CONFIG_SMP */
81
5be3492f 82static unsigned long in_xmon __read_mostly = 0;
3b5bf42b 83static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT);
1da177e4
LT
84
85static unsigned long adrs;
86static int size = 1;
87#define MAX_DUMP (128 * 1024)
88static unsigned long ndump = 64;
89static unsigned long nidump = 16;
90static unsigned long ncsum = 4096;
91static int termch;
92static char tmpstr[128];
ed49f7fd 93static int tracing_enabled;
1da177e4 94
1da177e4
LT
95static long bus_error_jmp[JMP_BUF_LEN];
96static int catch_memory_errors;
31cdd0c3 97static int catch_spr_faults;
1da177e4 98static long *xmon_fault_jmp[NR_CPUS];
1da177e4
LT
99
100/* Breakpoint stuff */
101struct bpt {
102 unsigned long address;
103 unsigned int instr[2];
104 atomic_t ref_count;
105 int enabled;
106 unsigned long pad;
107};
108
109/* Bits in bpt.enabled */
abb90ee7
ME
110#define BP_CIABR 1
111#define BP_TRAP 2
112#define BP_DABR 4
1da177e4
LT
113
114#define NBPTS 256
115static struct bpt bpts[NBPTS];
116static struct bpt dabr;
117static struct bpt *iabr;
118static unsigned bpinstr = 0x7fe00008; /* trap */
119
120#define BP_NUM(bp) ((bp) - bpts + 1)
121
122/* Prototypes */
123static int cmds(struct pt_regs *);
124static int mread(unsigned long, void *, int);
125static int mwrite(unsigned long, void *, int);
126static int handle_fault(struct pt_regs *);
127static void byterev(unsigned char *, int);
128static void memex(void);
129static int bsesc(void);
130static void dump(void);
80eff6c4 131static void show_pte(unsigned long);
1da177e4
LT
132static void prdump(unsigned long, long);
133static int ppc_inst_dump(unsigned long, long, int);
f312deb4 134static void dump_log_buf(void);
fde93a0f
AD
135
136#ifdef CONFIG_PPC_POWERNV
137static void dump_opal_msglog(void);
138#else
139static inline void dump_opal_msglog(void)
140{
141 printf("Machine is not running OPAL firmware.\n");
142}
143#endif
144
1da177e4
LT
145static void backtrace(struct pt_regs *);
146static void excprint(struct pt_regs *);
147static void prregs(struct pt_regs *);
148static void memops(int);
149static void memlocate(void);
150static void memzcan(void);
151static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
152int skipbl(void);
153int scanhex(unsigned long *valp);
154static void scannl(void);
155static int hexdigit(int);
156void getstring(char *, int);
157static void flush_input(void);
158static int inchar(void);
159static void take_input(char *);
31cdd0c3 160static int read_spr(int, unsigned long *);
1da177e4
LT
161static void write_spr(int, unsigned long);
162static void super_regs(void);
163static void remove_bpts(void);
164static void insert_bpts(void);
165static void remove_cpu_bpts(void);
166static void insert_cpu_bpts(void);
167static struct bpt *at_breakpoint(unsigned long pc);
168static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
169static int do_step(struct pt_regs *);
170static void bpt_cmds(void);
171static void cacheflush(void);
172static int cpu_cmd(void);
173static void csum(void);
174static void bootcmds(void);
f78541dc 175static void proccall(void);
6dfb5404 176static void show_tasks(void);
1da177e4
LT
177void dump_segments(void);
178static void symbol_lookup(void);
26c8af5f
OH
179static void xmon_show_stack(unsigned long sp, unsigned long lr,
180 unsigned long pc);
1da177e4
LT
181static void xmon_print_symbol(unsigned long address, const char *mid,
182 const char *after);
183static const char *getvecname(unsigned long vec);
184
ff8a8f25
ME
185static int do_spu_cmd(void);
186
5a8a1a28
BH
187#ifdef CONFIG_44x
188static void dump_tlb_44x(void);
189#endif
03247157
BH
190#ifdef CONFIG_PPC_BOOK3E
191static void dump_tlb_book3e(void);
192#endif
5a8a1a28 193
f78541dc
PM
194#ifdef CONFIG_PPC64
195#define REG "%.16lx"
f78541dc
PM
196#else
197#define REG "%.8lx"
f78541dc 198#endif
1da177e4 199
72eceef6
PB
200#ifdef __LITTLE_ENDIAN__
201#define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
202#else
1da177e4 203#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
72eceef6 204#endif
1da177e4 205
1da177e4
LT
206static char *help_string = "\
207Commands:\n\
208 b show breakpoints\n\
209 bd set data breakpoint\n\
210 bi set instruction breakpoint\n\
211 bc clear breakpoint\n"
212#ifdef CONFIG_SMP
213 "\
214 c print cpus stopped in xmon\n\
215 c# try to switch to cpu number h (in hex)\n"
216#endif
217 "\
218 C checksum\n\
219 d dump bytes\n\
5e48dc0a
DM
220 d1 dump 1 byte values\n\
221 d2 dump 2 byte values\n\
222 d4 dump 4 byte values\n\
223 d8 dump 8 byte values\n\
1da177e4
LT
224 di dump instructions\n\
225 df dump float values\n\
226 dd dump double values\n\
ddadb6b8 227 dl dump the kernel log buffer\n"
fde93a0f
AD
228#ifdef CONFIG_PPC_POWERNV
229 "\
230 do dump the OPAL message log\n"
231#endif
ddadb6b8
ME
232#ifdef CONFIG_PPC64
233 "\
234 dp[#] dump paca for current cpu, or cpu #\n\
235 dpa dump paca for all possible cpus\n"
236#endif
237 "\
7e5b5938 238 dr dump stream of raw bytes\n\
80eff6c4 239 dv dump virtual address translation \n\
56144ec7 240 dt dump the tracing buffers (uses printk)\n\
4125d012 241 dtc dump the tracing buffers for current CPU (uses printk)\n\
243e2511
BH
242"
243#ifdef CONFIG_PPC_POWERNV
244" dx# dump xive on CPU #\n\
245 dxi# dump xive irq state #\n\
246 dxa dump xive on all CPUs\n"
247#endif
248" e print exception information\n\
1da177e4
LT
249 f flush cache\n\
250 la lookup symbol+offset of specified address\n\
251 ls lookup address of specified symbol\n\
252 m examine/change memory\n\
253 mm move a block of memory\n\
254 ms set a block of memory\n\
255 md compare two blocks of memory\n\
256 ml locate a block of memory\n\
257 mz zero a block of memory\n\
258 mi show information about memory allocation\n\
f78541dc 259 p call a procedure\n\
6dfb5404 260 P list processes/tasks\n\
1da177e4 261 r print registers\n\
ff8a8f25 262 s single step\n"
e055595d 263#ifdef CONFIG_SPU_BASE
ff8a8f25 264" ss stop execution on all spus\n\
a8984970 265 sr restore execution on stopped spus\n\
24a24c85 266 sf # dump spu fields for spu # (in hex)\n\
c99176a2 267 sd # dump spu local store for spu # (in hex)\n\
af89fb80 268 sdi # disassemble spu local store for spu # (in hex)\n"
ff8a8f25
ME
269#endif
270" S print special registers\n\
31cdd0c3
PM
271 Sa print all SPRs\n\
272 Sr # read SPR #\n\
273 Sw #v write v to SPR #\n\
1da177e4 274 t print backtrace\n\
1da177e4 275 x exit monitor and recover\n\
2e340579 276 X exit monitor and don't recover\n"
79873e8d 277#if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
f78541dc 278" u dump segment table or SLB\n"
79873e8d 279#elif defined(CONFIG_PPC_STD_MMU_32)
f78541dc 280" u dump segment registers\n"
79873e8d 281#elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
5a8a1a28
BH
282" u dump TLB\n"
283#endif
59d3391e 284" U show uptime information\n"
f78541dc 285" ? help\n"
0c23a88c 286" # n limit output to n lines per page (for dp, dpa, dl)\n"
f78541dc 287" zr reboot\n\
1da177e4
LT
288 zh halt\n"
289;
290
291static struct pt_regs *xmon_regs;
292
f78541dc 293static inline void sync(void)
1da177e4
LT
294{
295 asm volatile("sync; isync");
296}
297
f78541dc
PM
298static inline void store_inst(void *p)
299{
300 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
301}
302
303static inline void cflush(void *p)
304{
305 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
306}
307
308static inline void cinval(void *p)
309{
310 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
311}
1da177e4 312
1ad7d705
AK
313/**
314 * write_ciabr() - write the CIABR SPR
315 * @ciabr: The value to write.
316 *
317 * This function writes a value to the CIARB register either directly
318 * through mtspr instruction if the kernel is in HV privilege mode or
319 * call a hypervisor function to achieve the same in case the kernel
320 * is in supervisor privilege mode.
321 */
322static void write_ciabr(unsigned long ciabr)
323{
324 if (!cpu_has_feature(CPU_FTR_ARCH_207S))
325 return;
326
327 if (cpu_has_feature(CPU_FTR_HVMODE)) {
328 mtspr(SPRN_CIABR, ciabr);
329 return;
330 }
331 plapr_set_ciabr(ciabr);
332}
333
334/**
335 * set_ciabr() - set the CIABR
336 * @addr: The value to set.
337 *
338 * This function sets the correct privilege value into the the HW
339 * breakpoint address before writing it up in the CIABR register.
340 */
341static void set_ciabr(unsigned long addr)
342{
343 addr &= ~CIABR_PRIV;
344
345 if (cpu_has_feature(CPU_FTR_HVMODE))
346 addr |= CIABR_PRIV_HYPER;
347 else
348 addr |= CIABR_PRIV_SUPER;
349 write_ciabr(addr);
350}
351
1da177e4
LT
352/*
353 * Disable surveillance (the service processor watchdog function)
354 * while we are in xmon.
355 * XXX we should re-enable it when we leave. :)
356 */
357#define SURVEILLANCE_TOKEN 9000
358
359static inline void disable_surveillance(void)
360{
361#ifdef CONFIG_PPC_PSERIES
362 /* Since this can't be a module, args should end up below 4GB. */
363 static struct rtas_args args;
08eb105a 364 int token;
1da177e4
LT
365
366 /*
367 * At this point we have got all the cpus we can into
368 * xmon, so there is hopefully no other cpu calling RTAS
369 * at the moment, even though we don't take rtas.lock.
370 * If we did try to take rtas.lock there would be a
371 * real possibility of deadlock.
372 */
08eb105a
ME
373 token = rtas_token("set-indicator");
374 if (token == RTAS_UNKNOWN_SERVICE)
1da177e4 375 return;
08eb105a
ME
376
377 rtas_call_unlocked(&args, token, 3, 1, NULL, SURVEILLANCE_TOKEN, 0, 0);
378
1da177e4
LT
379#endif /* CONFIG_PPC_PSERIES */
380}
381
382#ifdef CONFIG_SMP
383static int xmon_speaker;
384
385static void get_output_lock(void)
386{
387 int me = smp_processor_id() + 0x100;
388 int last_speaker = 0, prev;
389 long timeout;
390
391 if (xmon_speaker == me)
392 return;
730efb61 393
1da177e4 394 for (;;) {
730efb61
ME
395 last_speaker = cmpxchg(&xmon_speaker, 0, me);
396 if (last_speaker == 0)
397 return;
398
15075897
ME
399 /*
400 * Wait a full second for the lock, we might be on a slow
401 * console, but check every 100us.
402 */
403 timeout = 10000;
1da177e4 404 while (xmon_speaker == last_speaker) {
15075897
ME
405 if (--timeout > 0) {
406 udelay(100);
1da177e4 407 continue;
15075897
ME
408 }
409
1da177e4
LT
410 /* hostile takeover */
411 prev = cmpxchg(&xmon_speaker, last_speaker, me);
412 if (prev == last_speaker)
413 return;
414 break;
415 }
416 }
417}
418
419static void release_output_lock(void)
420{
421 xmon_speaker = 0;
422}
1c8950ff
ME
423
424int cpus_are_in_xmon(void)
425{
104699c0 426 return !cpumask_empty(&cpus_in_xmon);
1c8950ff 427}
1cd6ed7c
NP
428
429static bool wait_for_other_cpus(int ncpus)
430{
431 unsigned long timeout;
432
433 /* We wait for 2s, which is a metric "little while" */
434 for (timeout = 20000; timeout != 0; --timeout) {
435 if (cpumask_weight(&cpus_in_xmon) >= ncpus)
436 return true;
437 udelay(100);
438 barrier();
439 }
440
441 return false;
442}
443#endif /* CONFIG_SMP */
1da177e4 444
daf8f403
JB
445static inline int unrecoverable_excp(struct pt_regs *regs)
446{
08f6d6ab 447#if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
66857b3a 448 /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
daf8f403
JB
449 return 0;
450#else
451 return ((regs->msr & MSR_RI) == 0);
452#endif
453}
454
b0da9856 455static int xmon_core(struct pt_regs *regs, int fromipi)
1da177e4
LT
456{
457 int cmd = 0;
1da177e4
LT
458 struct bpt *bp;
459 long recurse_jmp[JMP_BUF_LEN];
460 unsigned long offset;
f13659e0 461 unsigned long flags;
1da177e4
LT
462#ifdef CONFIG_SMP
463 int cpu;
464 int secondary;
1da177e4
LT
465#endif
466
f13659e0 467 local_irq_save(flags);
a71d64b4 468 hard_irq_disable();
1da177e4 469
ed49f7fd
BL
470 tracing_enabled = tracing_is_on();
471 tracing_off();
472
1da177e4
LT
473 bp = in_breakpoint_table(regs->nip, &offset);
474 if (bp != NULL) {
475 regs->nip = bp->address + offset;
476 atomic_dec(&bp->ref_count);
477 }
478
479 remove_cpu_bpts();
480
481#ifdef CONFIG_SMP
482 cpu = smp_processor_id();
104699c0 483 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
31cdd0c3
PM
484 /*
485 * We catch SPR read/write faults here because the 0x700, 0xf60
486 * etc. handlers don't call debugger_fault_handler().
487 */
488 if (catch_spr_faults)
489 longjmp(bus_error_jmp, 1);
1da177e4
LT
490 get_output_lock();
491 excprint(regs);
492 printf("cpu 0x%x: Exception %lx %s in xmon, "
493 "returning to main loop\n",
494 cpu, regs->trap, getvecname(TRAP(regs)));
5cb4cc0d 495 release_output_lock();
1da177e4
LT
496 longjmp(xmon_fault_jmp[cpu], 1);
497 }
498
499 if (setjmp(recurse_jmp) != 0) {
500 if (!in_xmon || !xmon_gate) {
5cb4cc0d 501 get_output_lock();
1da177e4
LT
502 printf("xmon: WARNING: bad recursive fault "
503 "on cpu 0x%x\n", cpu);
5cb4cc0d 504 release_output_lock();
1da177e4
LT
505 goto waiting;
506 }
507 secondary = !(xmon_taken && cpu == xmon_owner);
508 goto cmdloop;
509 }
510
511 xmon_fault_jmp[cpu] = recurse_jmp;
1da177e4
LT
512
513 bp = NULL;
9f0b0793 514 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
1da177e4 515 bp = at_breakpoint(regs->nip);
daf8f403 516 if (bp || unrecoverable_excp(regs))
1da177e4
LT
517 fromipi = 0;
518
519 if (!fromipi) {
520 get_output_lock();
521 excprint(regs);
522 if (bp) {
736256e4 523 printf("cpu 0x%x stopped at breakpoint 0x%lx (",
1da177e4
LT
524 cpu, BP_NUM(bp));
525 xmon_print_symbol(regs->nip, " ", ")\n");
526 }
daf8f403 527 if (unrecoverable_excp(regs))
1da177e4
LT
528 printf("WARNING: exception is not recoverable, "
529 "can't continue\n");
530 release_output_lock();
531 }
532
d2b496e5
ME
533 cpumask_set_cpu(cpu, &cpus_in_xmon);
534
1da177e4
LT
535 waiting:
536 secondary = 1;
064996d6 537 spin_begin();
1da177e4
LT
538 while (secondary && !xmon_gate) {
539 if (in_xmon == 0) {
064996d6
NP
540 if (fromipi) {
541 spin_end();
1da177e4 542 goto leave;
064996d6 543 }
1da177e4
LT
544 secondary = test_and_set_bit(0, &in_xmon);
545 }
064996d6
NP
546 spin_cpu_relax();
547 touch_nmi_watchdog();
1da177e4 548 }
064996d6 549 spin_end();
1da177e4
LT
550
551 if (!secondary && !xmon_gate) {
552 /* we are the first cpu to come in */
553 /* interrupt other cpu(s) */
554 int ncpus = num_online_cpus();
555
556 xmon_owner = cpu;
557 mb();
558 if (ncpus > 1) {
1cd6ed7c
NP
559 /*
560 * A system reset (trap == 0x100) can be triggered on
561 * all CPUs, so when we come in via 0x100 try waiting
562 * for the other CPUs to come in before we send the
563 * debugger break (IPI). This is similar to
564 * crash_kexec_secondary().
565 */
566 if (TRAP(regs) != 0x100 || !wait_for_other_cpus(ncpus))
567 smp_send_debugger_break();
568
569 wait_for_other_cpus(ncpus);
1da177e4
LT
570 }
571 remove_bpts();
572 disable_surveillance();
573 /* for breakpoint or single step, print the current instr. */
574 if (bp || TRAP(regs) == 0xd00)
575 ppc_inst_dump(regs->nip, 1, 0);
576 printf("enter ? for help\n");
577 mb();
578 xmon_gate = 1;
579 barrier();
064996d6 580 touch_nmi_watchdog();
1da177e4
LT
581 }
582
583 cmdloop:
584 while (in_xmon) {
585 if (secondary) {
064996d6 586 spin_begin();
1da177e4
LT
587 if (cpu == xmon_owner) {
588 if (!test_and_set_bit(0, &xmon_taken)) {
589 secondary = 0;
064996d6 590 spin_end();
1da177e4
LT
591 continue;
592 }
593 /* missed it */
594 while (cpu == xmon_owner)
064996d6 595 spin_cpu_relax();
1da177e4 596 }
064996d6
NP
597 spin_cpu_relax();
598 touch_nmi_watchdog();
1da177e4
LT
599 } else {
600 cmd = cmds(regs);
601 if (cmd != 0) {
602 /* exiting xmon */
603 insert_bpts();
604 xmon_gate = 0;
605 wmb();
606 in_xmon = 0;
607 break;
608 }
609 /* have switched to some other cpu */
610 secondary = 1;
611 }
612 }
613 leave:
104699c0 614 cpumask_clear_cpu(cpu, &cpus_in_xmon);
1da177e4 615 xmon_fault_jmp[cpu] = NULL;
1da177e4
LT
616#else
617 /* UP is simple... */
618 if (in_xmon) {
619 printf("Exception %lx %s in xmon, returning to main loop\n",
620 regs->trap, getvecname(TRAP(regs)));
621 longjmp(xmon_fault_jmp[0], 1);
622 }
623 if (setjmp(recurse_jmp) == 0) {
624 xmon_fault_jmp[0] = recurse_jmp;
625 in_xmon = 1;
626
627 excprint(regs);
628 bp = at_breakpoint(regs->nip);
629 if (bp) {
736256e4 630 printf("Stopped at breakpoint %lx (", BP_NUM(bp));
1da177e4
LT
631 xmon_print_symbol(regs->nip, " ", ")\n");
632 }
daf8f403 633 if (unrecoverable_excp(regs))
1da177e4
LT
634 printf("WARNING: exception is not recoverable, "
635 "can't continue\n");
636 remove_bpts();
637 disable_surveillance();
638 /* for breakpoint or single step, print the current instr. */
639 if (bp || TRAP(regs) == 0xd00)
640 ppc_inst_dump(regs->nip, 1, 0);
641 printf("enter ? for help\n");
642 }
643
644 cmd = cmds(regs);
645
646 insert_bpts();
647 in_xmon = 0;
648#endif
649
cdd3904d
JB
650#ifdef CONFIG_BOOKE
651 if (regs->msr & MSR_DE) {
652 bp = at_breakpoint(regs->nip);
653 if (bp != NULL) {
654 regs->nip = (unsigned long) &bp->instr[0];
655 atomic_inc(&bp->ref_count);
656 }
657 }
658#else
9f0b0793 659 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
1da177e4
LT
660 bp = at_breakpoint(regs->nip);
661 if (bp != NULL) {
662 int stepped = emulate_step(regs, bp->instr[0]);
663 if (stepped == 0) {
664 regs->nip = (unsigned long) &bp->instr[0];
665 atomic_inc(&bp->ref_count);
666 } else if (stepped < 0) {
667 printf("Couldn't single-step %s instruction\n",
668 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
669 }
670 }
671 }
cdd3904d 672#endif
1da177e4
LT
673 insert_cpu_bpts();
674
a71d64b4 675 touch_nmi_watchdog();
f13659e0 676 local_irq_restore(flags);
1da177e4 677
0a730ae5 678 return cmd != 'X' && cmd != EOF;
1da177e4
LT
679}
680
681int xmon(struct pt_regs *excp)
682{
683 struct pt_regs regs;
684
685 if (excp == NULL) {
322b4394 686 ppc_save_regs(&regs);
1da177e4
LT
687 excp = &regs;
688 }
ff8a8f25 689
1da177e4
LT
690 return xmon_core(excp, 0);
691}
f78541dc
PM
692EXPORT_SYMBOL(xmon);
693
f583ffce 694irqreturn_t xmon_irq(int irq, void *d)
f78541dc
PM
695{
696 unsigned long flags;
697 local_irq_save(flags);
698 printf("Keyboard interrupt\n");
f583ffce 699 xmon(get_irq_regs());
f78541dc
PM
700 local_irq_restore(flags);
701 return IRQ_HANDLED;
702}
1da177e4 703
b0da9856 704static int xmon_bpt(struct pt_regs *regs)
1da177e4
LT
705{
706 struct bpt *bp;
707 unsigned long offset;
708
9f0b0793 709 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
1da177e4
LT
710 return 0;
711
712 /* Are we at the trap at bp->instr[1] for some bp? */
713 bp = in_breakpoint_table(regs->nip, &offset);
714 if (bp != NULL && offset == 4) {
715 regs->nip = bp->address + 4;
716 atomic_dec(&bp->ref_count);
717 return 1;
718 }
719
720 /* Are we at a breakpoint? */
721 bp = at_breakpoint(regs->nip);
722 if (!bp)
723 return 0;
724
725 xmon_core(regs, 0);
726
727 return 1;
728}
729
b0da9856 730static int xmon_sstep(struct pt_regs *regs)
1da177e4
LT
731{
732 if (user_mode(regs))
733 return 0;
734 xmon_core(regs, 0);
735 return 1;
736}
737
9422de3e 738static int xmon_break_match(struct pt_regs *regs)
1da177e4 739{
9f0b0793 740 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
1da177e4 741 return 0;
fd9648df
AB
742 if (dabr.enabled == 0)
743 return 0;
1da177e4
LT
744 xmon_core(regs, 0);
745 return 1;
746}
747
b0da9856 748static int xmon_iabr_match(struct pt_regs *regs)
1da177e4 749{
9f0b0793 750 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
1da177e4 751 return 0;
9f1067c2 752 if (iabr == NULL)
1da177e4
LT
753 return 0;
754 xmon_core(regs, 0);
755 return 1;
756}
757
b0da9856 758static int xmon_ipi(struct pt_regs *regs)
1da177e4
LT
759{
760#ifdef CONFIG_SMP
104699c0 761 if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
1da177e4
LT
762 xmon_core(regs, 1);
763#endif
764 return 0;
765}
766
b0da9856 767static int xmon_fault_handler(struct pt_regs *regs)
1da177e4
LT
768{
769 struct bpt *bp;
770 unsigned long offset;
771
772 if (in_xmon && catch_memory_errors)
773 handle_fault(regs); /* doesn't return */
774
9f0b0793 775 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
1da177e4
LT
776 bp = in_breakpoint_table(regs->nip, &offset);
777 if (bp != NULL) {
778 regs->nip = bp->address + offset;
779 atomic_dec(&bp->ref_count);
780 }
781 }
782
783 return 0;
784}
785
1da177e4
LT
786static struct bpt *at_breakpoint(unsigned long pc)
787{
788 int i;
789 struct bpt *bp;
790
791 bp = bpts;
792 for (i = 0; i < NBPTS; ++i, ++bp)
793 if (bp->enabled && pc == bp->address)
794 return bp;
795 return NULL;
796}
797
798static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
799{
800 unsigned long off;
801
802 off = nip - (unsigned long) bpts;
803 if (off >= sizeof(bpts))
804 return NULL;
805 off %= sizeof(struct bpt);
806 if (off != offsetof(struct bpt, instr[0])
807 && off != offsetof(struct bpt, instr[1]))
808 return NULL;
809 *offp = off - offsetof(struct bpt, instr[0]);
810 return (struct bpt *) (nip - off);
811}
812
813static struct bpt *new_breakpoint(unsigned long a)
814{
815 struct bpt *bp;
816
817 a &= ~3UL;
818 bp = at_breakpoint(a);
819 if (bp)
820 return bp;
821
822 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
823 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
824 bp->address = a;
825 bp->instr[1] = bpinstr;
826 store_inst(&bp->instr[1]);
827 return bp;
828 }
829 }
830
831 printf("Sorry, no free breakpoints. Please clear one first.\n");
832 return NULL;
833}
834
835static void insert_bpts(void)
836{
837 int i;
838 struct bpt *bp;
839
840 bp = bpts;
841 for (i = 0; i < NBPTS; ++i, ++bp) {
abb90ee7 842 if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
1da177e4
LT
843 continue;
844 if (mread(bp->address, &bp->instr[0], 4) != 4) {
845 printf("Couldn't read instruction at %lx, "
846 "disabling breakpoint there\n", bp->address);
847 bp->enabled = 0;
848 continue;
849 }
850 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
851 printf("Breakpoint at %lx is on an mtmsrd or rfid "
852 "instruction, disabling it\n", bp->address);
853 bp->enabled = 0;
854 continue;
855 }
856 store_inst(&bp->instr[0]);
abb90ee7 857 if (bp->enabled & BP_CIABR)
1da177e4 858 continue;
efe4fbb1
BS
859 if (patch_instruction((unsigned int *)bp->address,
860 bpinstr) != 0) {
1da177e4
LT
861 printf("Couldn't write instruction at %lx, "
862 "disabling breakpoint there\n", bp->address);
863 bp->enabled &= ~BP_TRAP;
864 continue;
865 }
866 store_inst((void *)bp->address);
867 }
868}
869
870static void insert_cpu_bpts(void)
871{
9422de3e
MN
872 struct arch_hw_breakpoint brk;
873
874 if (dabr.enabled) {
875 brk.address = dabr.address;
876 brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
877 brk.len = 8;
21f58507 878 __set_breakpoint(&brk);
9422de3e 879 }
1ad7d705
AK
880
881 if (iabr)
882 set_ciabr(iabr->address);
1da177e4
LT
883}
884
885static void remove_bpts(void)
886{
887 int i;
888 struct bpt *bp;
889 unsigned instr;
890
891 bp = bpts;
892 for (i = 0; i < NBPTS; ++i, ++bp) {
abb90ee7 893 if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
1da177e4
LT
894 continue;
895 if (mread(bp->address, &instr, 4) == 4
896 && instr == bpinstr
efe4fbb1
BS
897 && patch_instruction(
898 (unsigned int *)bp->address, bp->instr[0]) != 0)
1da177e4
LT
899 printf("Couldn't remove breakpoint at %lx\n",
900 bp->address);
901 else
902 store_inst((void *)bp->address);
903 }
904}
905
906static void remove_cpu_bpts(void)
907{
9422de3e 908 hw_breakpoint_disable();
1ad7d705 909 write_ciabr(0);
1da177e4
LT
910}
911
59d3391e
GP
912/* Based on uptime_proc_show(). */
913static void
914show_uptime(void)
915{
916 struct timespec uptime;
917
918 if (setjmp(bus_error_jmp) == 0) {
919 catch_memory_errors = 1;
920 sync();
921
922 get_monotonic_boottime(&uptime);
923 printf("Uptime: %lu.%.2lu seconds\n", (unsigned long)uptime.tv_sec,
924 ((unsigned long)uptime.tv_nsec / (NSEC_PER_SEC/100)));
925
926 sync();
927 __delay(200); \
928 }
929 catch_memory_errors = 0;
930}
931
958b7c80
S
932static void set_lpp_cmd(void)
933{
934 unsigned long lpp;
935
936 if (!scanhex(&lpp)) {
937 printf("Invalid number.\n");
938 lpp = 0;
939 }
940 xmon_set_pagination_lpp(lpp);
941}
1da177e4
LT
942/* Command interpreting routine */
943static char *last_cmd;
944
945static int
946cmds(struct pt_regs *excp)
947{
948 int cmd = 0;
949
950 last_cmd = NULL;
951 xmon_regs = excp;
26c8af5f 952
b561783c 953 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
26c8af5f 954
1da177e4
LT
955 for(;;) {
956#ifdef CONFIG_SMP
957 printf("%x:", smp_processor_id());
958#endif /* CONFIG_SMP */
959 printf("mon> ");
1da177e4
LT
960 flush_input();
961 termch = 0;
962 cmd = skipbl();
963 if( cmd == '\n' ) {
964 if (last_cmd == NULL)
965 continue;
966 take_input(last_cmd);
967 last_cmd = NULL;
968 cmd = inchar();
969 }
970 switch (cmd) {
971 case 'm':
972 cmd = inchar();
973 switch (cmd) {
974 case 'm':
975 case 's':
976 case 'd':
977 memops(cmd);
978 break;
979 case 'l':
980 memlocate();
981 break;
982 case 'z':
983 memzcan();
984 break;
985 case 'i':
9af744d7 986 show_mem(0, NULL);
1da177e4
LT
987 break;
988 default:
989 termch = cmd;
990 memex();
991 }
992 break;
993 case 'd':
994 dump();
995 break;
996 case 'l':
997 symbol_lookup();
998 break;
999 case 'r':
1000 prregs(excp); /* print regs */
1001 break;
1002 case 'e':
1003 excprint(excp);
1004 break;
1005 case 'S':
1006 super_regs();
1007 break;
1008 case 't':
1009 backtrace(excp);
1010 break;
1011 case 'f':
1012 cacheflush();
1013 break;
1014 case 's':
ff8a8f25
ME
1015 if (do_spu_cmd() == 0)
1016 break;
1da177e4
LT
1017 if (do_step(excp))
1018 return cmd;
1019 break;
1020 case 'x':
1021 case 'X':
ed49f7fd
BL
1022 if (tracing_enabled)
1023 tracing_on();
bb6b9b28 1024 return cmd;
1da177e4 1025 case EOF:
bb6b9b28
BH
1026 printf(" <no input ...>\n");
1027 mdelay(2000);
1da177e4
LT
1028 return cmd;
1029 case '?':
4d404edc 1030 xmon_puts(help_string);
1da177e4 1031 break;
958b7c80
S
1032 case '#':
1033 set_lpp_cmd();
1034 break;
1da177e4
LT
1035 case 'b':
1036 bpt_cmds();
1037 break;
1038 case 'C':
1039 csum();
1040 break;
1041 case 'c':
1042 if (cpu_cmd())
1043 return 0;
1044 break;
1045 case 'z':
1046 bootcmds();
1047 break;
f78541dc
PM
1048 case 'p':
1049 proccall();
1da177e4 1050 break;
6dfb5404
DM
1051 case 'P':
1052 show_tasks();
1053 break;
f78541dc 1054#ifdef CONFIG_PPC_STD_MMU
1da177e4
LT
1055 case 'u':
1056 dump_segments();
1057 break;
d8ee6f34 1058#elif defined(CONFIG_44x)
5a8a1a28
BH
1059 case 'u':
1060 dump_tlb_44x();
1061 break;
79873e8d 1062#elif defined(CONFIG_PPC_BOOK3E)
03247157
BH
1063 case 'u':
1064 dump_tlb_book3e();
1065 break;
f78541dc 1066#endif
59d3391e
GP
1067 case 'U':
1068 show_uptime();
1069 break;
1da177e4
LT
1070 default:
1071 printf("Unrecognized command: ");
e3bc8049 1072 do {
1da177e4
LT
1073 if (' ' < cmd && cmd <= '~')
1074 putchar(cmd);
1075 else
1076 printf("\\x%x", cmd);
1077 cmd = inchar();
e3bc8049 1078 } while (cmd != '\n');
1da177e4
LT
1079 printf(" (type ? for help)\n");
1080 break;
1081 }
1082 }
1083}
1084
cdd3904d
JB
1085#ifdef CONFIG_BOOKE
1086static int do_step(struct pt_regs *regs)
1087{
1088 regs->msr |= MSR_DE;
1089 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
1090 return 1;
1091}
1092#else
1da177e4
LT
1093/*
1094 * Step a single instruction.
1095 * Some instructions we emulate, others we execute with MSR_SE set.
1096 */
1097static int do_step(struct pt_regs *regs)
1098{
1099 unsigned int instr;
1100 int stepped;
1101
1102 /* check we are in 64-bit kernel mode, translation enabled */
9f0b0793 1103 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
1da177e4
LT
1104 if (mread(regs->nip, &instr, 4) == 4) {
1105 stepped = emulate_step(regs, instr);
1106 if (stepped < 0) {
1107 printf("Couldn't single-step %s instruction\n",
1108 (IS_RFID(instr)? "rfid": "mtmsrd"));
1109 return 0;
1110 }
1111 if (stepped > 0) {
1112 regs->trap = 0xd00 | (regs->trap & 1);
1113 printf("stepped to ");
1114 xmon_print_symbol(regs->nip, " ", "\n");
1115 ppc_inst_dump(regs->nip, 1, 0);
1116 return 0;
1117 }
1118 }
1119 }
1120 regs->msr |= MSR_SE;
1121 return 1;
1122}
cdd3904d 1123#endif
1da177e4
LT
1124
1125static void bootcmds(void)
1126{
1127 int cmd;
1128
1129 cmd = inchar();
1130 if (cmd == 'r')
1131 ppc_md.restart(NULL);
1132 else if (cmd == 'h')
1133 ppc_md.halt();
1134 else if (cmd == 'p')
9178ba29
AG
1135 if (pm_power_off)
1136 pm_power_off();
1da177e4
LT
1137}
1138
1139static int cpu_cmd(void)
1140{
1141#ifdef CONFIG_SMP
fd3bb912 1142 unsigned long cpu, first_cpu, last_cpu;
1da177e4 1143 int timeout;
1da177e4
LT
1144
1145 if (!scanhex(&cpu)) {
1146 /* print cpus waiting or in xmon */
1147 printf("cpus stopped:");
fd3bb912 1148 last_cpu = first_cpu = NR_CPUS;
bc1d7702 1149 for_each_possible_cpu(cpu) {
104699c0 1150 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
fd3bb912
PM
1151 if (cpu == last_cpu + 1) {
1152 last_cpu = cpu;
1153 } else {
1154 if (last_cpu != first_cpu)
736256e4 1155 printf("-0x%lx", last_cpu);
fd3bb912 1156 last_cpu = first_cpu = cpu;
736256e4 1157 printf(" 0x%lx", cpu);
fd3bb912 1158 }
1da177e4
LT
1159 }
1160 }
fd3bb912 1161 if (last_cpu != first_cpu)
736256e4 1162 printf("-0x%lx", last_cpu);
1da177e4
LT
1163 printf("\n");
1164 return 0;
1165 }
1166 /* try to switch to cpu specified */
104699c0 1167 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1da177e4
LT
1168 printf("cpu 0x%x isn't in xmon\n", cpu);
1169 return 0;
1170 }
1171 xmon_taken = 0;
1172 mb();
1173 xmon_owner = cpu;
1174 timeout = 10000000;
1175 while (!xmon_taken) {
1176 if (--timeout == 0) {
1177 if (test_and_set_bit(0, &xmon_taken))
1178 break;
1179 /* take control back */
1180 mb();
1181 xmon_owner = smp_processor_id();
736256e4 1182 printf("cpu 0x%x didn't take control\n", cpu);
1da177e4
LT
1183 return 0;
1184 }
1185 barrier();
1186 }
1187 return 1;
1188#else
1189 return 0;
1190#endif /* CONFIG_SMP */
1191}
1192
1193static unsigned short fcstab[256] = {
1194 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1195 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1196 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1197 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1198 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1199 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1200 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1201 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1202 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1203 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1204 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1205 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1206 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1207 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1208 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1209 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1210 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1211 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1212 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1213 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1214 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1215 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1216 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1217 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1218 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1219 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1220 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1221 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1222 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1223 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1224 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1225 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1226};
1227
1228#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1229
1230static void
1231csum(void)
1232{
1233 unsigned int i;
1234 unsigned short fcs;
1235 unsigned char v;
1236
1237 if (!scanhex(&adrs))
1238 return;
1239 if (!scanhex(&ncsum))
1240 return;
1241 fcs = 0xffff;
1242 for (i = 0; i < ncsum; ++i) {
1243 if (mread(adrs+i, &v, 1) == 0) {
736256e4 1244 printf("csum stopped at "REG"\n", adrs+i);
1da177e4
LT
1245 break;
1246 }
1247 fcs = FCS(fcs, v);
1248 }
1249 printf("%x\n", fcs);
1250}
1251
1252/*
1253 * Check if this is a suitable place to put a breakpoint.
1254 */
1255static long check_bp_loc(unsigned long addr)
1256{
1257 unsigned int instr;
1258
1259 addr &= ~3;
51fae6de 1260 if (!is_kernel_addr(addr)) {
1da177e4
LT
1261 printf("Breakpoints may only be placed at kernel addresses\n");
1262 return 0;
1263 }
1264 if (!mread(addr, &instr, sizeof(instr))) {
1265 printf("Can't read instruction at address %lx\n", addr);
1266 return 0;
1267 }
1268 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1269 printf("Breakpoints may not be placed on mtmsrd or rfid "
1270 "instructions\n");
1271 return 0;
1272 }
1273 return 1;
1274}
1275
e3bc8049 1276static char *breakpoint_help_string =
1da177e4
LT
1277 "Breakpoint command usage:\n"
1278 "b show breakpoints\n"
1279 "b <addr> [cnt] set breakpoint at given instr addr\n"
1280 "bc clear all breakpoints\n"
1281 "bc <n/addr> clear breakpoint number n or at addr\n"
1ad7d705 1282 "bi <addr> [cnt] set hardware instr breakpoint (POWER8 only)\n"
1da177e4
LT
1283 "bd <addr> [cnt] set hardware data breakpoint\n"
1284 "";
1285
1286static void
1287bpt_cmds(void)
1288{
1289 int cmd;
1290 unsigned long a;
09b6c112 1291 int i;
1da177e4 1292 struct bpt *bp;
1da177e4
LT
1293
1294 cmd = inchar();
1295 switch (cmd) {
09b6c112
NP
1296#ifndef CONFIG_PPC_8xx
1297 static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n";
1298 int mode;
1da177e4
LT
1299 case 'd': /* bd - hardware data breakpoint */
1300 mode = 7;
1301 cmd = inchar();
1302 if (cmd == 'r')
1303 mode = 5;
1304 else if (cmd == 'w')
1305 mode = 6;
1306 else
1307 termch = cmd;
1308 dabr.address = 0;
1309 dabr.enabled = 0;
1310 if (scanhex(&dabr.address)) {
51fae6de 1311 if (!is_kernel_addr(dabr.address)) {
1da177e4
LT
1312 printf(badaddr);
1313 break;
1314 }
9422de3e 1315 dabr.address &= ~HW_BRK_TYPE_DABR;
1da177e4
LT
1316 dabr.enabled = mode | BP_DABR;
1317 }
1318 break;
1319
1320 case 'i': /* bi - hardware instr breakpoint */
1ad7d705 1321 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) {
1da177e4
LT
1322 printf("Hardware instruction breakpoint "
1323 "not supported on this cpu\n");
1324 break;
1325 }
1326 if (iabr) {
abb90ee7 1327 iabr->enabled &= ~BP_CIABR;
1da177e4
LT
1328 iabr = NULL;
1329 }
1330 if (!scanhex(&a))
1331 break;
1332 if (!check_bp_loc(a))
1333 break;
1334 bp = new_breakpoint(a);
1335 if (bp != NULL) {
abb90ee7 1336 bp->enabled |= BP_CIABR;
1da177e4
LT
1337 iabr = bp;
1338 }
1339 break;
f78541dc 1340#endif
1da177e4
LT
1341
1342 case 'c':
1343 if (!scanhex(&a)) {
1344 /* clear all breakpoints */
1345 for (i = 0; i < NBPTS; ++i)
1346 bpts[i].enabled = 0;
1347 iabr = NULL;
1348 dabr.enabled = 0;
1349 printf("All breakpoints cleared\n");
1350 break;
1351 }
1352
1353 if (a <= NBPTS && a >= 1) {
1354 /* assume a breakpoint number */
1355 bp = &bpts[a-1]; /* bp nums are 1 based */
1356 } else {
1357 /* assume a breakpoint address */
1358 bp = at_breakpoint(a);
9f1067c2 1359 if (bp == NULL) {
736256e4 1360 printf("No breakpoint at %lx\n", a);
1da177e4
LT
1361 break;
1362 }
1363 }
1364
736256e4 1365 printf("Cleared breakpoint %lx (", BP_NUM(bp));
1da177e4
LT
1366 xmon_print_symbol(bp->address, " ", ")\n");
1367 bp->enabled = 0;
1368 break;
1369
1370 default:
1371 termch = cmd;
e3bc8049 1372 cmd = skipbl();
1da177e4
LT
1373 if (cmd == '?') {
1374 printf(breakpoint_help_string);
1375 break;
1376 }
1377 termch = cmd;
1378 if (!scanhex(&a)) {
1379 /* print all breakpoints */
1380 printf(" type address\n");
1381 if (dabr.enabled) {
f78541dc 1382 printf(" data "REG" [", dabr.address);
1da177e4
LT
1383 if (dabr.enabled & 1)
1384 printf("r");
1385 if (dabr.enabled & 2)
1386 printf("w");
1387 printf("]\n");
1388 }
1389 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1390 if (!bp->enabled)
1391 continue;
1392 printf("%2x %s ", BP_NUM(bp),
abb90ee7 1393 (bp->enabled & BP_CIABR) ? "inst": "trap");
1da177e4
LT
1394 xmon_print_symbol(bp->address, " ", "\n");
1395 }
1396 break;
1397 }
1398
1399 if (!check_bp_loc(a))
1400 break;
1401 bp = new_breakpoint(a);
1402 if (bp != NULL)
1403 bp->enabled |= BP_TRAP;
1404 break;
1405 }
1406}
1407
1408/* Very cheap human name for vector lookup. */
1409static
1410const char *getvecname(unsigned long vec)
1411{
1412 char *ret;
1413
1414 switch (vec) {
1415 case 0x100: ret = "(System Reset)"; break;
1416 case 0x200: ret = "(Machine Check)"; break;
1417 case 0x300: ret = "(Data Access)"; break;
8915bcd6
MN
1418 case 0x380:
1419 if (radix_enabled())
1420 ret = "(Data Access Out of Range)";
1421 else
1422 ret = "(Data SLB Access)";
1423 break;
1da177e4 1424 case 0x400: ret = "(Instruction Access)"; break;
8915bcd6
MN
1425 case 0x480:
1426 if (radix_enabled())
1427 ret = "(Instruction Access Out of Range)";
1428 else
1429 ret = "(Instruction SLB Access)";
1430 break;
1da177e4
LT
1431 case 0x500: ret = "(Hardware Interrupt)"; break;
1432 case 0x600: ret = "(Alignment)"; break;
1433 case 0x700: ret = "(Program Check)"; break;
1434 case 0x800: ret = "(FPU Unavailable)"; break;
1435 case 0x900: ret = "(Decrementer)"; break;
660e034c
ME
1436 case 0x980: ret = "(Hypervisor Decrementer)"; break;
1437 case 0xa00: ret = "(Doorbell)"; break;
1da177e4
LT
1438 case 0xc00: ret = "(System Call)"; break;
1439 case 0xd00: ret = "(Single Step)"; break;
660e034c
ME
1440 case 0xe40: ret = "(Emulation Assist)"; break;
1441 case 0xe60: ret = "(HMI)"; break;
1442 case 0xe80: ret = "(Hypervisor Doorbell)"; break;
1da177e4
LT
1443 case 0xf00: ret = "(Performance Monitor)"; break;
1444 case 0xf20: ret = "(Altivec Unavailable)"; break;
1445 case 0x1300: ret = "(Instruction Breakpoint)"; break;
660e034c
ME
1446 case 0x1500: ret = "(Denormalisation)"; break;
1447 case 0x1700: ret = "(Altivec Assist)"; break;
1da177e4
LT
1448 default: ret = "";
1449 }
1450 return ret;
1451}
1452
1453static void get_function_bounds(unsigned long pc, unsigned long *startp,
1454 unsigned long *endp)
1455{
1456 unsigned long size, offset;
1457 const char *name;
1da177e4
LT
1458
1459 *startp = *endp = 0;
1460 if (pc == 0)
1461 return;
1462 if (setjmp(bus_error_jmp) == 0) {
1463 catch_memory_errors = 1;
1464 sync();
ffb45122 1465 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1da177e4
LT
1466 if (name != NULL) {
1467 *startp = pc - offset;
1468 *endp = pc - offset + size;
1469 }
1470 sync();
1471 }
1472 catch_memory_errors = 0;
1473}
1474
ec2b36b9
BH
1475#define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1476#define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1477
1da177e4
LT
1478static void xmon_show_stack(unsigned long sp, unsigned long lr,
1479 unsigned long pc)
1480{
0104cd68 1481 int max_to_print = 64;
1da177e4
LT
1482 unsigned long ip;
1483 unsigned long newsp;
1484 unsigned long marker;
1da177e4
LT
1485 struct pt_regs regs;
1486
0104cd68 1487 while (max_to_print--) {
e71ff89c 1488 if (!is_kernel_addr(sp)) {
1da177e4
LT
1489 if (sp != 0)
1490 printf("SP (%lx) is in userspace\n", sp);
1491 break;
1492 }
1493
f78541dc 1494 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1da177e4
LT
1495 || !mread(sp, &newsp, sizeof(unsigned long))) {
1496 printf("Couldn't read stack frame at %lx\n", sp);
1497 break;
1498 }
1499
1500 /*
1501 * For the first stack frame, try to work out if
1502 * LR and/or the saved LR value in the bottommost
1503 * stack frame are valid.
1504 */
1505 if ((pc | lr) != 0) {
1506 unsigned long fnstart, fnend;
1507 unsigned long nextip;
1508 int printip = 1;
1509
1510 get_function_bounds(pc, &fnstart, &fnend);
1511 nextip = 0;
1512 if (newsp > sp)
f78541dc 1513 mread(newsp + LRSAVE_OFFSET, &nextip,
1da177e4
LT
1514 sizeof(unsigned long));
1515 if (lr == ip) {
e71ff89c 1516 if (!is_kernel_addr(lr)
1da177e4
LT
1517 || (fnstart <= lr && lr < fnend))
1518 printip = 0;
1519 } else if (lr == nextip) {
1520 printip = 0;
e71ff89c 1521 } else if (is_kernel_addr(lr)
1da177e4
LT
1522 && !(fnstart <= lr && lr < fnend)) {
1523 printf("[link register ] ");
1524 xmon_print_symbol(lr, " ", "\n");
1525 }
1526 if (printip) {
f78541dc 1527 printf("["REG"] ", sp);
1da177e4
LT
1528 xmon_print_symbol(ip, " ", " (unreliable)\n");
1529 }
1530 pc = lr = 0;
1531
1532 } else {
f78541dc 1533 printf("["REG"] ", sp);
1da177e4
LT
1534 xmon_print_symbol(ip, " ", "\n");
1535 }
1536
1537 /* Look for "regshere" marker to see if this is
1538 an exception frame. */
f78541dc 1539 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
ec2b36b9 1540 && marker == STACK_FRAME_REGS_MARKER) {
c4de3809 1541 if (mread(sp + STACK_FRAME_OVERHEAD, &regs, sizeof(regs))
1da177e4
LT
1542 != sizeof(regs)) {
1543 printf("Couldn't read registers at %lx\n",
c4de3809 1544 sp + STACK_FRAME_OVERHEAD);
1da177e4
LT
1545 break;
1546 }
e3bc8049 1547 printf("--- Exception: %lx %s at ", regs.trap,
1da177e4
LT
1548 getvecname(TRAP(&regs)));
1549 pc = regs.nip;
1550 lr = regs.link;
1551 xmon_print_symbol(pc, " ", "\n");
1552 }
1553
1554 if (newsp == 0)
1555 break;
1556
1557 sp = newsp;
0104cd68 1558 }
1da177e4
LT
1559}
1560
1561static void backtrace(struct pt_regs *excp)
1562{
1563 unsigned long sp;
1564
1565 if (scanhex(&sp))
1566 xmon_show_stack(sp, 0, 0);
1567 else
1568 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1569 scannl();
1570}
1571
1572static void print_bug_trap(struct pt_regs *regs)
1573{
ebdba9af 1574#ifdef CONFIG_BUG
73c9ceab 1575 const struct bug_entry *bug;
1da177e4
LT
1576 unsigned long addr;
1577
1578 if (regs->msr & MSR_PR)
1579 return; /* not in kernel */
1580 addr = regs->nip; /* address of trap instruction */
e71ff89c 1581 if (!is_kernel_addr(addr))
1da177e4
LT
1582 return;
1583 bug = find_bug(regs->nip);
1584 if (bug == NULL)
1585 return;
73c9ceab 1586 if (is_warning_bug(bug))
1da177e4
LT
1587 return;
1588
0a7c7efc 1589#ifdef CONFIG_DEBUG_BUGVERBOSE
73c9ceab
JF
1590 printf("kernel BUG at %s:%u!\n",
1591 bug->file, bug->line);
0a7c7efc 1592#else
d8104182 1593 printf("kernel BUG at %px!\n", (void *)bug->bug_addr);
0a7c7efc 1594#endif
ebdba9af 1595#endif /* CONFIG_BUG */
1da177e4
LT
1596}
1597
9f1067c2 1598static void excprint(struct pt_regs *fp)
1da177e4
LT
1599{
1600 unsigned long trap;
1601
1602#ifdef CONFIG_SMP
1603 printf("cpu 0x%x: ", smp_processor_id());
1604#endif /* CONFIG_SMP */
1605
1606 trap = TRAP(fp);
1607 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1608 printf(" pc: ");
1609 xmon_print_symbol(fp->nip, ": ", "\n");
1610
1611 printf(" lr: ", fp->link);
1612 xmon_print_symbol(fp->link, ": ", "\n");
1613
1614 printf(" sp: %lx\n", fp->gpr[1]);
1615 printf(" msr: %lx\n", fp->msr);
1616
ce54152f 1617 if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
1da177e4
LT
1618 printf(" dar: %lx\n", fp->dar);
1619 if (trap != 0x380)
1620 printf(" dsisr: %lx\n", fp->dsisr);
1621 }
1622
1623 printf(" current = 0x%lx\n", current);
f78541dc 1624#ifdef CONFIG_PPC64
7230c564 1625 printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
4e26bc4a 1626 local_paca, local_paca->irq_soft_mask, local_paca->irq_happened);
f78541dc 1627#endif
1da177e4
LT
1628 if (current) {
1629 printf(" pid = %ld, comm = %s\n",
1630 current->pid, current->comm);
1631 }
1632
1633 if (trap == 0x700)
1634 print_bug_trap(fp);
eb925d64
RG
1635
1636 printf(linux_banner);
1da177e4
LT
1637}
1638
9f1067c2 1639static void prregs(struct pt_regs *fp)
1da177e4 1640{
f78541dc 1641 int n, trap;
1da177e4
LT
1642 unsigned long base;
1643 struct pt_regs regs;
1644
1645 if (scanhex(&base)) {
1646 if (setjmp(bus_error_jmp) == 0) {
1647 catch_memory_errors = 1;
1648 sync();
1649 regs = *(struct pt_regs *)base;
1650 sync();
1651 __delay(200);
1652 } else {
1653 catch_memory_errors = 0;
f78541dc 1654 printf("*** Error reading registers from "REG"\n",
1da177e4
LT
1655 base);
1656 return;
1657 }
1658 catch_memory_errors = 0;
1659 fp = &regs;
1660 }
1661
f78541dc 1662#ifdef CONFIG_PPC64
1da177e4
LT
1663 if (FULL_REGS(fp)) {
1664 for (n = 0; n < 16; ++n)
f78541dc 1665 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1da177e4
LT
1666 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1667 } else {
1668 for (n = 0; n < 7; ++n)
f78541dc 1669 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1da177e4
LT
1670 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1671 }
f78541dc
PM
1672#else
1673 for (n = 0; n < 32; ++n) {
1674 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1675 (n & 3) == 3? "\n": " ");
1676 if (n == 12 && !FULL_REGS(fp)) {
1677 printf("\n");
1678 break;
1679 }
1680 }
1681#endif
1da177e4
LT
1682 printf("pc = ");
1683 xmon_print_symbol(fp->nip, " ", "\n");
48404f2e
PM
1684 if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1685 printf("cfar= ");
1686 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1687 }
1da177e4
LT
1688 printf("lr = ");
1689 xmon_print_symbol(fp->link, " ", "\n");
f78541dc
PM
1690 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1691 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1da177e4 1692 fp->ctr, fp->xer, fp->trap);
f78541dc
PM
1693 trap = TRAP(fp);
1694 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1695 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1da177e4
LT
1696}
1697
9f1067c2 1698static void cacheflush(void)
1da177e4
LT
1699{
1700 int cmd;
1701 unsigned long nflush;
1702
1703 cmd = inchar();
1704 if (cmd != 'i')
1705 termch = cmd;
1706 scanhex((void *)&adrs);
1707 if (termch != '\n')
1708 termch = 0;
1709 nflush = 1;
1710 scanhex(&nflush);
1711 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1712 if (setjmp(bus_error_jmp) == 0) {
1713 catch_memory_errors = 1;
1714 sync();
1715
1716 if (cmd != 'i') {
1717 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1718 cflush((void *) adrs);
1719 } else {
1720 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1721 cinval((void *) adrs);
1722 }
1723 sync();
1724 /* wait a little while to see if we get a machine check */
1725 __delay(200);
1726 }
1727 catch_memory_errors = 0;
1728}
1729
31cdd0c3
PM
1730extern unsigned long xmon_mfspr(int spr, unsigned long default_value);
1731extern void xmon_mtspr(int spr, unsigned long value);
1732
1733static int
1734read_spr(int n, unsigned long *vp)
1da177e4 1735{
1da177e4 1736 unsigned long ret = -1UL;
31cdd0c3 1737 int ok = 0;
1da177e4
LT
1738
1739 if (setjmp(bus_error_jmp) == 0) {
31cdd0c3 1740 catch_spr_faults = 1;
1da177e4
LT
1741 sync();
1742
31cdd0c3 1743 ret = xmon_mfspr(n, *vp);
1da177e4
LT
1744
1745 sync();
31cdd0c3
PM
1746 *vp = ret;
1747 ok = 1;
1da177e4 1748 }
31cdd0c3 1749 catch_spr_faults = 0;
1da177e4 1750
31cdd0c3 1751 return ok;
1da177e4
LT
1752}
1753
9f1067c2 1754static void
1da177e4
LT
1755write_spr(int n, unsigned long val)
1756{
1da177e4 1757 if (setjmp(bus_error_jmp) == 0) {
31cdd0c3 1758 catch_spr_faults = 1;
1da177e4
LT
1759 sync();
1760
31cdd0c3 1761 xmon_mtspr(n, val);
1da177e4
LT
1762
1763 sync();
31cdd0c3
PM
1764 } else {
1765 printf("SPR 0x%03x (%4d) Faulted during write\n", n, n);
1da177e4 1766 }
31cdd0c3 1767 catch_spr_faults = 0;
1da177e4
LT
1768}
1769
1846193b
ME
1770static void dump_206_sprs(void)
1771{
1772#ifdef CONFIG_PPC64
1773 if (!cpu_has_feature(CPU_FTR_ARCH_206))
1774 return;
1775
1776 /* Actually some of these pre-date 2.06, but whatevs */
1777
c47a9403 1778 printf("srr0 = %.16lx srr1 = %.16lx dsisr = %.8x\n",
1846193b 1779 mfspr(SPRN_SRR0), mfspr(SPRN_SRR1), mfspr(SPRN_DSISR));
c47a9403 1780 printf("dscr = %.16lx ppr = %.16lx pir = %.8x\n",
1846193b 1781 mfspr(SPRN_DSCR), mfspr(SPRN_PPR), mfspr(SPRN_PIR));
64d66aa0
BS
1782 printf("amr = %.16lx uamor = %.16lx\n",
1783 mfspr(SPRN_AMR), mfspr(SPRN_UAMOR));
1846193b
ME
1784
1785 if (!(mfmsr() & MSR_HV))
1786 return;
1787
c47a9403 1788 printf("sdr1 = %.16lx hdar = %.16lx hdsisr = %.8x\n",
1846193b 1789 mfspr(SPRN_SDR1), mfspr(SPRN_HDAR), mfspr(SPRN_HDSISR));
64d66aa0 1790 printf("hsrr0 = %.16lx hsrr1 = %.16lx hdec = %.16lx\n",
1846193b 1791 mfspr(SPRN_HSRR0), mfspr(SPRN_HSRR1), mfspr(SPRN_HDEC));
64d66aa0 1792 printf("lpcr = %.16lx pcr = %.16lx lpidr = %.8x\n",
1846193b 1793 mfspr(SPRN_LPCR), mfspr(SPRN_PCR), mfspr(SPRN_LPID));
64d66aa0
BS
1794 printf("hsprg0 = %.16lx hsprg1 = %.16lx amor = %.16lx\n",
1795 mfspr(SPRN_HSPRG0), mfspr(SPRN_HSPRG1), mfspr(SPRN_AMOR));
c47a9403 1796 printf("dabr = %.16lx dabrx = %.16lx\n",
1846193b
ME
1797 mfspr(SPRN_DABR), mfspr(SPRN_DABRX));
1798#endif
1799}
1800
e0ddf7a2
ME
1801static void dump_207_sprs(void)
1802{
1803#ifdef CONFIG_PPC64
1804 unsigned long msr;
1805
1806 if (!cpu_has_feature(CPU_FTR_ARCH_207S))
1807 return;
1808
c47a9403 1809 printf("dpdes = %.16lx tir = %.16lx cir = %.8x\n",
e0ddf7a2
ME
1810 mfspr(SPRN_DPDES), mfspr(SPRN_TIR), mfspr(SPRN_CIR));
1811
c47a9403 1812 printf("fscr = %.16lx tar = %.16lx pspb = %.8x\n",
e0ddf7a2
ME
1813 mfspr(SPRN_FSCR), mfspr(SPRN_TAR), mfspr(SPRN_PSPB));
1814
1815 msr = mfmsr();
1816 if (msr & MSR_TM) {
1817 /* Only if TM has been enabled in the kernel */
c47a9403 1818 printf("tfhar = %.16lx tfiar = %.16lx texasr = %.16lx\n",
e0ddf7a2
ME
1819 mfspr(SPRN_TFHAR), mfspr(SPRN_TFIAR),
1820 mfspr(SPRN_TEXASR));
1821 }
1822
c47a9403 1823 printf("mmcr0 = %.16lx mmcr1 = %.16lx mmcr2 = %.16lx\n",
e0ddf7a2
ME
1824 mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCR2));
1825 printf("pmc1 = %.8x pmc2 = %.8x pmc3 = %.8x pmc4 = %.8x\n",
1826 mfspr(SPRN_PMC1), mfspr(SPRN_PMC2),
1827 mfspr(SPRN_PMC3), mfspr(SPRN_PMC4));
c47a9403 1828 printf("mmcra = %.16lx siar = %.16lx pmc5 = %.8x\n",
e0ddf7a2 1829 mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR), mfspr(SPRN_PMC5));
c47a9403 1830 printf("sdar = %.16lx sier = %.16lx pmc6 = %.8x\n",
e0ddf7a2 1831 mfspr(SPRN_SDAR), mfspr(SPRN_SIER), mfspr(SPRN_PMC6));
c47a9403 1832 printf("ebbhr = %.16lx ebbrr = %.16lx bescr = %.16lx\n",
e0ddf7a2 1833 mfspr(SPRN_EBBHR), mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR));
64d66aa0 1834 printf("iamr = %.16lx\n", mfspr(SPRN_IAMR));
e0ddf7a2
ME
1835
1836 if (!(msr & MSR_HV))
1837 return;
1838
c47a9403 1839 printf("hfscr = %.16lx dhdes = %.16lx rpr = %.16lx\n",
e0ddf7a2 1840 mfspr(SPRN_HFSCR), mfspr(SPRN_DHDES), mfspr(SPRN_RPR));
c47a9403 1841 printf("dawr = %.16lx dawrx = %.16lx ciabr = %.16lx\n",
e0ddf7a2
ME
1842 mfspr(SPRN_DAWR), mfspr(SPRN_DAWRX), mfspr(SPRN_CIABR));
1843#endif
1844}
1da177e4 1845
d1e1b351
BS
1846static void dump_300_sprs(void)
1847{
1848#ifdef CONFIG_PPC64
1849 bool hv = mfmsr() & MSR_HV;
1850
1851 if (!cpu_has_feature(CPU_FTR_ARCH_300))
1852 return;
1853
1854 printf("pidr = %.16lx tidr = %.16lx\n",
1855 mfspr(SPRN_PID), mfspr(SPRN_TIDR));
1856 printf("asdr = %.16lx psscr = %.16lx\n",
1857 mfspr(SPRN_ASDR), hv ? mfspr(SPRN_PSSCR)
1858 : mfspr(SPRN_PSSCR_PR));
1859
1860 if (!hv)
1861 return;
1862
1863 printf("ptcr = %.16lx\n",
1864 mfspr(SPRN_PTCR));
1865#endif
1866}
1867
31cdd0c3
PM
1868static void dump_one_spr(int spr, bool show_unimplemented)
1869{
1870 unsigned long val;
1871
1872 val = 0xdeadbeef;
1873 if (!read_spr(spr, &val)) {
1874 printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr);
1875 return;
1876 }
1877
1878 if (val == 0xdeadbeef) {
1879 /* Looks like read was a nop, confirm */
1880 val = 0x0badcafe;
1881 if (!read_spr(spr, &val)) {
1882 printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr);
1883 return;
1884 }
1885
1886 if (val == 0x0badcafe) {
1887 if (show_unimplemented)
1888 printf("SPR 0x%03x (%4d) Unimplemented\n", spr, spr);
1889 return;
1890 }
1891 }
1892
1893 printf("SPR 0x%03x (%4d) = 0x%lx\n", spr, spr, val);
1894}
1895
9f1067c2 1896static void super_regs(void)
1da177e4 1897{
13629dad 1898 static unsigned long regno;
1da177e4 1899 int cmd;
31cdd0c3 1900 int spr;
1da177e4
LT
1901
1902 cmd = skipbl();
31cdd0c3
PM
1903
1904 switch (cmd) {
1905 case '\n': {
e3bc8049 1906 unsigned long sp, toc;
1da177e4
LT
1907 asm("mr %0,1" : "=r" (sp) :);
1908 asm("mr %0,2" : "=r" (toc) :);
1909
56346ad8 1910 printf("msr = "REG" sprg0 = "REG"\n",
f78541dc 1911 mfmsr(), mfspr(SPRN_SPRG0));
56346ad8 1912 printf("pvr = "REG" sprg1 = "REG"\n",
e3bc8049 1913 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
56346ad8 1914 printf("dec = "REG" sprg2 = "REG"\n",
f78541dc 1915 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
56346ad8
ME
1916 printf("sp = "REG" sprg3 = "REG"\n", sp, mfspr(SPRN_SPRG3));
1917 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1918
1846193b 1919 dump_206_sprs();
e0ddf7a2 1920 dump_207_sprs();
d1e1b351 1921 dump_300_sprs();
1846193b 1922
1da177e4
LT
1923 return;
1924 }
31cdd0c3
PM
1925 case 'w': {
1926 unsigned long val;
1927 scanhex(&regno);
1928 val = 0;
1929 read_spr(regno, &val);
1da177e4
LT
1930 scanhex(&val);
1931 write_spr(regno, val);
31cdd0c3
PM
1932 dump_one_spr(regno, true);
1933 break;
1934 }
1da177e4 1935 case 'r':
31cdd0c3
PM
1936 scanhex(&regno);
1937 dump_one_spr(regno, true);
1938 break;
1939 case 'a':
1940 /* dump ALL SPRs */
1941 for (spr = 1; spr < 1024; ++spr)
1942 dump_one_spr(spr, false);
1da177e4 1943 break;
1da177e4 1944 }
31cdd0c3 1945
1da177e4
LT
1946 scannl();
1947}
1948
1949/*
1950 * Stuff for reading and writing memory safely
1951 */
9f1067c2 1952static int
1da177e4
LT
1953mread(unsigned long adrs, void *buf, int size)
1954{
1955 volatile int n;
1956 char *p, *q;
1957
1958 n = 0;
1959 if (setjmp(bus_error_jmp) == 0) {
1960 catch_memory_errors = 1;
1961 sync();
1962 p = (char *)adrs;
1963 q = (char *)buf;
1964 switch (size) {
1965 case 2:
f78541dc 1966 *(u16 *)q = *(u16 *)p;
1da177e4
LT
1967 break;
1968 case 4:
f78541dc 1969 *(u32 *)q = *(u32 *)p;
1da177e4
LT
1970 break;
1971 case 8:
f78541dc 1972 *(u64 *)q = *(u64 *)p;
1da177e4
LT
1973 break;
1974 default:
1975 for( ; n < size; ++n) {
1976 *q++ = *p++;
1977 sync();
1978 }
1979 }
1980 sync();
1981 /* wait a little while to see if we get a machine check */
1982 __delay(200);
1983 n = size;
1984 }
1985 catch_memory_errors = 0;
1986 return n;
1987}
1988
9f1067c2 1989static int
1da177e4
LT
1990mwrite(unsigned long adrs, void *buf, int size)
1991{
1992 volatile int n;
1993 char *p, *q;
1994
1995 n = 0;
1996 if (setjmp(bus_error_jmp) == 0) {
1997 catch_memory_errors = 1;
1998 sync();
1999 p = (char *) adrs;
2000 q = (char *) buf;
2001 switch (size) {
2002 case 2:
f78541dc 2003 *(u16 *)p = *(u16 *)q;
1da177e4
LT
2004 break;
2005 case 4:
f78541dc 2006 *(u32 *)p = *(u32 *)q;
1da177e4
LT
2007 break;
2008 case 8:
f78541dc 2009 *(u64 *)p = *(u64 *)q;
1da177e4
LT
2010 break;
2011 default:
2012 for ( ; n < size; ++n) {
2013 *p++ = *q++;
2014 sync();
2015 }
2016 }
2017 sync();
2018 /* wait a little while to see if we get a machine check */
2019 __delay(200);
2020 n = size;
2021 } else {
736256e4 2022 printf("*** Error writing address "REG"\n", adrs + n);
1da177e4
LT
2023 }
2024 catch_memory_errors = 0;
2025 return n;
2026}
2027
2028static int fault_type;
f78541dc 2029static int fault_except;
1da177e4
LT
2030static char *fault_chars[] = { "--", "**", "##" };
2031
f78541dc 2032static int handle_fault(struct pt_regs *regs)
1da177e4 2033{
f78541dc 2034 fault_except = TRAP(regs);
1da177e4
LT
2035 switch (TRAP(regs)) {
2036 case 0x200:
2037 fault_type = 0;
2038 break;
2039 case 0x300:
2040 case 0x380:
2041 fault_type = 1;
2042 break;
2043 default:
2044 fault_type = 2;
2045 }
2046
2047 longjmp(bus_error_jmp, 1);
2048
2049 return 0;
2050}
2051
2052#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
2053
9f1067c2 2054static void
1da177e4
LT
2055byterev(unsigned char *val, int size)
2056{
2057 int t;
2058
2059 switch (size) {
2060 case 2:
2061 SWAP(val[0], val[1], t);
2062 break;
2063 case 4:
2064 SWAP(val[0], val[3], t);
2065 SWAP(val[1], val[2], t);
2066 break;
2067 case 8: /* is there really any use for this? */
2068 SWAP(val[0], val[7], t);
2069 SWAP(val[1], val[6], t);
2070 SWAP(val[2], val[5], t);
2071 SWAP(val[3], val[4], t);
2072 break;
2073 }
2074}
2075
2076static int brev;
2077static int mnoread;
2078
e3bc8049 2079static char *memex_help_string =
1da177e4
LT
2080 "Memory examine command usage:\n"
2081 "m [addr] [flags] examine/change memory\n"
2082 " addr is optional. will start where left off.\n"
2083 " flags may include chars from this set:\n"
2084 " b modify by bytes (default)\n"
2085 " w modify by words (2 byte)\n"
2086 " l modify by longs (4 byte)\n"
2087 " d modify by doubleword (8 byte)\n"
2088 " r toggle reverse byte order mode\n"
2089 " n do not read memory (for i/o spaces)\n"
2090 " . ok to read (default)\n"
2091 "NOTE: flags are saved as defaults\n"
2092 "";
2093
e3bc8049 2094static char *memex_subcmd_help_string =
1da177e4
LT
2095 "Memory examine subcommands:\n"
2096 " hexval write this val to current location\n"
2097 " 'string' write chars from string to this location\n"
2098 " ' increment address\n"
2099 " ^ decrement address\n"
2100 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
2101 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
2102 " ` clear no-read flag\n"
2103 " ; stay at this addr\n"
2104 " v change to byte mode\n"
2105 " w change to word (2 byte) mode\n"
2106 " l change to long (4 byte) mode\n"
2107 " u change to doubleword (8 byte) mode\n"
2108 " m addr change current addr\n"
2109 " n toggle no-read flag\n"
2110 " r toggle byte reverse flag\n"
2111 " < count back up count bytes\n"
2112 " > count skip forward count bytes\n"
2113 " x exit this mode\n"
2114 "";
2115
9f1067c2 2116static void
1da177e4
LT
2117memex(void)
2118{
2119 int cmd, inc, i, nslash;
2120 unsigned long n;
2121 unsigned char val[16];
2122
2123 scanhex((void *)&adrs);
2124 cmd = skipbl();
2125 if (cmd == '?') {
2126 printf(memex_help_string);
2127 return;
2128 } else {
2129 termch = cmd;
2130 }
2131 last_cmd = "m\n";
2132 while ((cmd = skipbl()) != '\n') {
2133 switch( cmd ){
2134 case 'b': size = 1; break;
2135 case 'w': size = 2; break;
2136 case 'l': size = 4; break;
2137 case 'd': size = 8; break;
2138 case 'r': brev = !brev; break;
2139 case 'n': mnoread = 1; break;
2140 case '.': mnoread = 0; break;
2141 }
2142 }
2143 if( size <= 0 )
2144 size = 1;
2145 else if( size > 8 )
2146 size = 8;
2147 for(;;){
2148 if (!mnoread)
2149 n = mread(adrs, val, size);
e1449ed9 2150 printf(REG"%c", adrs, brev? 'r': ' ');
1da177e4
LT
2151 if (!mnoread) {
2152 if (brev)
2153 byterev(val, size);
2154 putchar(' ');
2155 for (i = 0; i < n; ++i)
2156 printf("%.2x", val[i]);
2157 for (; i < size; ++i)
2158 printf("%s", fault_chars[fault_type]);
2159 }
2160 putchar(' ');
2161 inc = size;
2162 nslash = 0;
2163 for(;;){
2164 if( scanhex(&n) ){
2165 for (i = 0; i < size; ++i)
2166 val[i] = n >> (i * 8);
2167 if (!brev)
2168 byterev(val, size);
2169 mwrite(adrs, val, size);
2170 inc = size;
2171 }
2172 cmd = skipbl();
2173 if (cmd == '\n')
2174 break;
2175 inc = 0;
2176 switch (cmd) {
2177 case '\'':
2178 for(;;){
2179 n = inchar();
2180 if( n == '\\' )
2181 n = bsesc();
2182 else if( n == '\'' )
2183 break;
2184 for (i = 0; i < size; ++i)
2185 val[i] = n >> (i * 8);
2186 if (!brev)
2187 byterev(val, size);
2188 mwrite(adrs, val, size);
2189 adrs += size;
2190 }
2191 adrs -= size;
2192 inc = size;
2193 break;
2194 case ',':
2195 adrs += size;
2196 break;
2197 case '.':
2198 mnoread = 0;
2199 break;
2200 case ';':
2201 break;
2202 case 'x':
2203 case EOF:
2204 scannl();
2205 return;
2206 case 'b':
2207 case 'v':
2208 size = 1;
2209 break;
2210 case 'w':
2211 size = 2;
2212 break;
2213 case 'l':
2214 size = 4;
2215 break;
2216 case 'u':
2217 size = 8;
2218 break;
2219 case '^':
2220 adrs -= size;
2221 break;
1da177e4
LT
2222 case '/':
2223 if (nslash > 0)
2224 adrs -= 1 << nslash;
2225 else
2226 nslash = 0;
2227 nslash += 4;
2228 adrs += 1 << nslash;
2229 break;
2230 case '\\':
2231 if (nslash < 0)
2232 adrs += 1 << -nslash;
2233 else
2234 nslash = 0;
2235 nslash -= 4;
2236 adrs -= 1 << -nslash;
2237 break;
2238 case 'm':
2239 scanhex((void *)&adrs);
2240 break;
2241 case 'n':
2242 mnoread = 1;
2243 break;
2244 case 'r':
2245 brev = !brev;
2246 break;
2247 case '<':
2248 n = size;
2249 scanhex(&n);
2250 adrs -= n;
2251 break;
2252 case '>':
2253 n = size;
2254 scanhex(&n);
2255 adrs += n;
2256 break;
2257 case '?':
2258 printf(memex_subcmd_help_string);
2259 break;
2260 }
2261 }
2262 adrs += inc;
2263 }
2264}
2265
9f1067c2 2266static int
1da177e4
LT
2267bsesc(void)
2268{
2269 int c;
2270
2271 c = inchar();
2272 switch( c ){
2273 case 'n': c = '\n'; break;
2274 case 'r': c = '\r'; break;
2275 case 'b': c = '\b'; break;
2276 case 't': c = '\t'; break;
2277 }
2278 return c;
2279}
2280
7e5b5938
OH
2281static void xmon_rawdump (unsigned long adrs, long ndump)
2282{
2283 long n, m, r, nr;
2284 unsigned char temp[16];
2285
2286 for (n = ndump; n > 0;) {
2287 r = n < 16? n: 16;
2288 nr = mread(adrs, temp, r);
2289 adrs += nr;
2290 for (m = 0; m < r; ++m) {
2291 if (m < nr)
2292 printf("%.2x", temp[m]);
2293 else
2294 printf("%s", fault_chars[fault_type]);
2295 }
2296 n -= r;
2297 if (nr < r)
2298 break;
2299 }
2300 printf("\n");
2301}
2302
4125d012
BL
2303static void dump_tracing(void)
2304{
2305 int c;
2306
2307 c = inchar();
2308 if (c == 'c')
2309 ftrace_dump(DUMP_ORIG);
2310 else
2311 ftrace_dump(DUMP_ALL);
4125d012
BL
2312}
2313
ddadb6b8
ME
2314#ifdef CONFIG_PPC64
2315static void dump_one_paca(int cpu)
2316{
2317 struct paca_struct *p;
4e003747 2318#ifdef CONFIG_PPC_BOOK3S_64
ad987fc8
ME
2319 int i = 0;
2320#endif
ddadb6b8
ME
2321
2322 if (setjmp(bus_error_jmp) != 0) {
2323 printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
2324 return;
2325 }
2326
2327 catch_memory_errors = 1;
2328 sync();
2329
d2e60075 2330 p = paca_ptrs[cpu];
ddadb6b8 2331
d8104182 2332 printf("paca for cpu 0x%x @ %px:\n", cpu, p);
ddadb6b8 2333
ad987fc8
ME
2334 printf(" %-*s = %s\n", 20, "possible", cpu_possible(cpu) ? "yes" : "no");
2335 printf(" %-*s = %s\n", 20, "present", cpu_present(cpu) ? "yes" : "no");
2336 printf(" %-*s = %s\n", 20, "online", cpu_online(cpu) ? "yes" : "no");
ddadb6b8
ME
2337
2338#define DUMP(paca, name, format) \
ad987fc8 2339 printf(" %-*s = %#-*"format"\t(0x%lx)\n", 20, #name, 18, paca->name, \
ddadb6b8
ME
2340 offsetof(struct paca_struct, name));
2341
2342 DUMP(p, lock_token, "x");
2343 DUMP(p, paca_index, "x");
2344 DUMP(p, kernel_toc, "lx");
2345 DUMP(p, kernelbase, "lx");
2346 DUMP(p, kernel_msr, "lx");
2248fade 2347 DUMP(p, emergency_sp, "px");
729b0f71 2348#ifdef CONFIG_PPC_BOOK3S_64
2248fade
ME
2349 DUMP(p, nmi_emergency_sp, "px");
2350 DUMP(p, mc_emergency_sp, "px");
c4f3b52c 2351 DUMP(p, in_nmi, "x");
729b0f71 2352 DUMP(p, in_mce, "x");
ad987fc8 2353 DUMP(p, hmi_event_available, "x");
729b0f71 2354#endif
ddadb6b8
ME
2355 DUMP(p, data_offset, "lx");
2356 DUMP(p, hw_cpu_id, "x");
2357 DUMP(p, cpu_start, "x");
2358 DUMP(p, kexec_state, "x");
4e003747 2359#ifdef CONFIG_PPC_BOOK3S_64
ad987fc8
ME
2360 for (i = 0; i < SLB_NUM_BOLTED; i++) {
2361 u64 esid, vsid;
2362
2363 if (!p->slb_shadow_ptr)
2364 continue;
2365
2366 esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid);
2367 vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid);
2368
2369 if (esid || vsid) {
2370 printf(" slb_shadow[%d]: = 0x%016lx 0x%016lx\n",
2371 i, esid, vsid);
2372 }
2373 }
2374 DUMP(p, vmalloc_sllp, "x");
2375 DUMP(p, slb_cache_ptr, "x");
2376 for (i = 0; i < SLB_CACHE_ENTRIES; i++)
2377 printf(" slb_cache[%d]: = 0x%016lx\n", i, p->slb_cache[i]);
274920a3
ME
2378
2379 DUMP(p, rfi_flush_fallback_area, "px");
ad987fc8
ME
2380#endif
2381 DUMP(p, dscr_default, "llx");
2382#ifdef CONFIG_PPC_BOOK3E
2248fade
ME
2383 DUMP(p, pgd, "px");
2384 DUMP(p, kernel_pgd, "px");
2385 DUMP(p, tcd_ptr, "px");
2386 DUMP(p, mc_kstack, "px");
2387 DUMP(p, crit_kstack, "px");
2388 DUMP(p, dbg_kstack, "px");
ad987fc8 2389#endif
2248fade 2390 DUMP(p, __current, "px");
ddadb6b8 2391 DUMP(p, kstack, "lx");
90d64737 2392 printf(" kstack_base = 0x%016lx\n", p->kstack & ~(THREAD_SIZE - 1));
ddadb6b8
ME
2393 DUMP(p, stab_rr, "lx");
2394 DUMP(p, saved_r1, "lx");
2395 DUMP(p, trap_save, "x");
4e26bc4a 2396 DUMP(p, irq_soft_mask, "x");
ddadb6b8
ME
2397 DUMP(p, irq_happened, "x");
2398 DUMP(p, io_sync, "x");
2399 DUMP(p, irq_work_pending, "x");
2400 DUMP(p, nap_state_lost, "x");
ad987fc8
ME
2401 DUMP(p, sprg_vdso, "llx");
2402
2403#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2404 DUMP(p, tm_scratch, "llx");
2405#endif
2406
2407#ifdef CONFIG_PPC_POWERNV
2248fade 2408 DUMP(p, core_idle_state_ptr, "px");
ad987fc8
ME
2409 DUMP(p, thread_idle_state, "x");
2410 DUMP(p, thread_mask, "x");
2411 DUMP(p, subcore_sibling_mask, "x");
2412#endif
ddadb6b8 2413
8c8b73c4
FW
2414 DUMP(p, accounting.utime, "llx");
2415 DUMP(p, accounting.stime, "llx");
2416 DUMP(p, accounting.utime_scaled, "llx");
c223c903
CL
2417 DUMP(p, accounting.starttime, "llx");
2418 DUMP(p, accounting.starttime_user, "llx");
2419 DUMP(p, accounting.startspurr, "llx");
2420 DUMP(p, accounting.utime_sspurr, "llx");
f828c3d0 2421 DUMP(p, accounting.steal_time, "llx");
ddadb6b8
ME
2422#undef DUMP
2423
2424 catch_memory_errors = 0;
2425 sync();
2426}
2427
2428static void dump_all_pacas(void)
2429{
2430 int cpu;
2431
2432 if (num_possible_cpus() == 0) {
2433 printf("No possible cpus, use 'dp #' to dump individual cpus\n");
2434 return;
2435 }
2436
2437 for_each_possible_cpu(cpu)
2438 dump_one_paca(cpu);
2439}
2440
2441static void dump_pacas(void)
2442{
2443 unsigned long num;
2444 int c;
2445
2446 c = inchar();
2447 if (c == 'a') {
2448 dump_all_pacas();
2449 return;
2450 }
2451
2452 termch = c; /* Put c back, it wasn't 'a' */
2453
2454 if (scanhex(&num))
2455 dump_one_paca(num);
2456 else
2457 dump_one_paca(xmon_owner);
2458}
2459#endif
2460
243e2511
BH
2461#ifdef CONFIG_PPC_POWERNV
2462static void dump_one_xive(int cpu)
2463{
2464 unsigned int hwid = get_hard_smp_processor_id(cpu);
2465
2466 opal_xive_dump(XIVE_DUMP_TM_HYP, hwid);
2467 opal_xive_dump(XIVE_DUMP_TM_POOL, hwid);
2468 opal_xive_dump(XIVE_DUMP_TM_OS, hwid);
2469 opal_xive_dump(XIVE_DUMP_TM_USER, hwid);
2470 opal_xive_dump(XIVE_DUMP_VP, hwid);
2471 opal_xive_dump(XIVE_DUMP_EMU_STATE, hwid);
2472
2473 if (setjmp(bus_error_jmp) != 0) {
2474 catch_memory_errors = 0;
2475 printf("*** Error dumping xive on cpu %d\n", cpu);
2476 return;
2477 }
2478
2479 catch_memory_errors = 1;
2480 sync();
2481 xmon_xive_do_dump(cpu);
2482 sync();
2483 __delay(200);
2484 catch_memory_errors = 0;
2485}
2486
2487static void dump_all_xives(void)
2488{
2489 int cpu;
2490
2491 if (num_possible_cpus() == 0) {
2492 printf("No possible cpus, use 'dx #' to dump individual cpus\n");
2493 return;
2494 }
2495
2496 for_each_possible_cpu(cpu)
2497 dump_one_xive(cpu);
2498}
2499
2500static void dump_one_xive_irq(u32 num)
2501{
2502 s64 rc;
2503 __be64 vp;
2504 u8 prio;
2505 __be32 lirq;
2506
2507 rc = opal_xive_get_irq_config(num, &vp, &prio, &lirq);
2508 xmon_printf("IRQ 0x%x config: vp=0x%llx prio=%d lirq=0x%x (rc=%lld)\n",
2509 num, be64_to_cpu(vp), prio, be32_to_cpu(lirq), rc);
2510}
2511
2512static void dump_xives(void)
2513{
2514 unsigned long num;
2515 int c;
2516
402e172a
BL
2517 if (!xive_enabled()) {
2518 printf("Xive disabled on this system\n");
2519 return;
2520 }
2521
243e2511
BH
2522 c = inchar();
2523 if (c == 'a') {
2524 dump_all_xives();
2525 return;
2526 } else if (c == 'i') {
2527 if (scanhex(&num))
2528 dump_one_xive_irq(num);
2529 return;
2530 }
2531
2532 termch = c; /* Put c back, it wasn't 'a' */
2533
2534 if (scanhex(&num))
2535 dump_one_xive(num);
2536 else
2537 dump_one_xive(xmon_owner);
2538}
2539#endif /* CONFIG_PPC_POWERNV */
2540
5e48dc0a
DM
2541static void dump_by_size(unsigned long addr, long count, int size)
2542{
2543 unsigned char temp[16];
2544 int i, j;
2545 u64 val;
2546
2547 count = ALIGN(count, 16);
2548
2549 for (i = 0; i < count; i += 16, addr += 16) {
2550 printf(REG, addr);
2551
2552 if (mread(addr, temp, 16) != 16) {
2553 printf("\nFaulted reading %d bytes from 0x"REG"\n", 16, addr);
2554 return;
2555 }
2556
2557 for (j = 0; j < 16; j += size) {
2558 putchar(' ');
2559 switch (size) {
2560 case 1: val = temp[j]; break;
2561 case 2: val = *(u16 *)&temp[j]; break;
2562 case 4: val = *(u32 *)&temp[j]; break;
2563 case 8: val = *(u64 *)&temp[j]; break;
2564 default: val = 0;
2565 }
2566
2567 printf("%0*lx", size * 2, val);
2568 }
2569 printf("\n");
2570 }
2571}
2572
9f1067c2 2573static void
1da177e4
LT
2574dump(void)
2575{
5e48dc0a 2576 static char last[] = { "d?\n" };
1da177e4
LT
2577 int c;
2578
2579 c = inchar();
ddadb6b8
ME
2580
2581#ifdef CONFIG_PPC64
2582 if (c == 'p') {
958b7c80 2583 xmon_start_pagination();
ddadb6b8 2584 dump_pacas();
958b7c80 2585 xmon_end_pagination();
ddadb6b8
ME
2586 return;
2587 }
2588#endif
243e2511
BH
2589#ifdef CONFIG_PPC_POWERNV
2590 if (c == 'x') {
2591 xmon_start_pagination();
2592 dump_xives();
2593 xmon_end_pagination();
2594 return;
2595 }
2596#endif
ddadb6b8 2597
4125d012
BL
2598 if (c == 't') {
2599 dump_tracing();
2600 return;
2601 }
2602
5e48dc0a 2603 if (c == '\n')
1da177e4 2604 termch = c;
5e48dc0a 2605
1da177e4
LT
2606 scanhex((void *)&adrs);
2607 if (termch != '\n')
2608 termch = 0;
2609 if (c == 'i') {
2610 scanhex(&nidump);
2611 if (nidump == 0)
2612 nidump = 16;
2613 else if (nidump > MAX_DUMP)
2614 nidump = MAX_DUMP;
2615 adrs += ppc_inst_dump(adrs, nidump, 1);
2616 last_cmd = "di\n";
f312deb4
VS
2617 } else if (c == 'l') {
2618 dump_log_buf();
fde93a0f
AD
2619 } else if (c == 'o') {
2620 dump_opal_msglog();
80eff6c4
BS
2621 } else if (c == 'v') {
2622 /* dump virtual to physical translation */
2623 show_pte(adrs);
7e5b5938
OH
2624 } else if (c == 'r') {
2625 scanhex(&ndump);
2626 if (ndump == 0)
2627 ndump = 64;
2628 xmon_rawdump(adrs, ndump);
2629 adrs += ndump;
2630 last_cmd = "dr\n";
1da177e4
LT
2631 } else {
2632 scanhex(&ndump);
2633 if (ndump == 0)
2634 ndump = 64;
2635 else if (ndump > MAX_DUMP)
2636 ndump = MAX_DUMP;
5e48dc0a
DM
2637
2638 switch (c) {
2639 case '8':
2640 case '4':
2641 case '2':
2642 case '1':
2643 ndump = ALIGN(ndump, 16);
2644 dump_by_size(adrs, ndump, c - '0');
2645 last[1] = c;
2646 last_cmd = last;
2647 break;
2648 default:
2649 prdump(adrs, ndump);
2650 last_cmd = "d\n";
2651 }
2652
1da177e4 2653 adrs += ndump;
1da177e4
LT
2654 }
2655}
2656
9f1067c2 2657static void
1da177e4
LT
2658prdump(unsigned long adrs, long ndump)
2659{
2660 long n, m, c, r, nr;
2661 unsigned char temp[16];
2662
2663 for (n = ndump; n > 0;) {
f78541dc 2664 printf(REG, adrs);
1da177e4
LT
2665 putchar(' ');
2666 r = n < 16? n: 16;
2667 nr = mread(adrs, temp, r);
2668 adrs += nr;
2669 for (m = 0; m < r; ++m) {
e3bc8049 2670 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
e1449ed9 2671 putchar(' ');
1da177e4
LT
2672 if (m < nr)
2673 printf("%.2x", temp[m]);
2674 else
2675 printf("%s", fault_chars[fault_type]);
2676 }
e1449ed9 2677 for (; m < 16; ++m) {
e3bc8049 2678 if ((m & (sizeof(long) - 1)) == 0)
e1449ed9 2679 putchar(' ');
1da177e4 2680 printf(" ");
e1449ed9 2681 }
1da177e4
LT
2682 printf(" |");
2683 for (m = 0; m < r; ++m) {
2684 if (m < nr) {
2685 c = temp[m];
2686 putchar(' ' <= c && c <= '~'? c: '.');
2687 } else
2688 putchar(' ');
2689 }
2690 n -= r;
2691 for (; m < 16; ++m)
2692 putchar(' ');
2693 printf("|\n");
2694 if (nr < r)
2695 break;
2696 }
2697}
2698
4c4c8723
ME
2699typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2700
9f1067c2 2701static int
4c4c8723
ME
2702generic_inst_dump(unsigned long adr, long count, int praddr,
2703 instruction_dump_func dump_func)
1da177e4
LT
2704{
2705 int nr, dotted;
2706 unsigned long first_adr;
2707 unsigned long inst, last_inst = 0;
2708 unsigned char val[4];
2709
2710 dotted = 0;
2711 for (first_adr = adr; count > 0; --count, adr += 4) {
2712 nr = mread(adr, val, 4);
2713 if (nr == 0) {
2714 if (praddr) {
2715 const char *x = fault_chars[fault_type];
f78541dc 2716 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
1da177e4
LT
2717 }
2718 break;
2719 }
2720 inst = GETWORD(val);
2721 if (adr > first_adr && inst == last_inst) {
2722 if (!dotted) {
2723 printf(" ...\n");
2724 dotted = 1;
2725 }
2726 continue;
2727 }
2728 dotted = 0;
2729 last_inst = inst;
2730 if (praddr)
f78541dc 2731 printf(REG" %.8x", adr, inst);
1da177e4 2732 printf("\t");
4c4c8723 2733 dump_func(inst, adr);
1da177e4
LT
2734 printf("\n");
2735 }
2736 return adr - first_adr;
2737}
2738
9f1067c2 2739static int
4c4c8723
ME
2740ppc_inst_dump(unsigned long adr, long count, int praddr)
2741{
2742 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2743}
2744
1da177e4
LT
2745void
2746print_address(unsigned long addr)
2747{
2748 xmon_print_symbol(addr, "\t# ", "");
2749}
2750
f312deb4
VS
2751void
2752dump_log_buf(void)
2753{
ca5dd395
ME
2754 struct kmsg_dumper dumper = { .active = 1 };
2755 unsigned char buf[128];
2756 size_t len;
f312deb4 2757
e3bc8049 2758 if (setjmp(bus_error_jmp) != 0) {
ca5dd395 2759 printf("Error dumping printk buffer!\n");
e3bc8049
ME
2760 return;
2761 }
f312deb4 2762
e3bc8049
ME
2763 catch_memory_errors = 1;
2764 sync();
f312deb4 2765
ca5dd395 2766 kmsg_dump_rewind_nolock(&dumper);
0c23a88c 2767 xmon_start_pagination();
ca5dd395
ME
2768 while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
2769 buf[len] = '\0';
2770 printf("%s", buf);
2771 }
0c23a88c 2772 xmon_end_pagination();
f312deb4 2773
e3bc8049
ME
2774 sync();
2775 /* wait a little while to see if we get a machine check */
2776 __delay(200);
2777 catch_memory_errors = 0;
f312deb4 2778}
1da177e4 2779
fde93a0f
AD
2780#ifdef CONFIG_PPC_POWERNV
2781static void dump_opal_msglog(void)
2782{
2783 unsigned char buf[128];
2784 ssize_t res;
2785 loff_t pos = 0;
2786
2787 if (!firmware_has_feature(FW_FEATURE_OPAL)) {
2788 printf("Machine is not running OPAL firmware.\n");
2789 return;
2790 }
2791
2792 if (setjmp(bus_error_jmp) != 0) {
2793 printf("Error dumping OPAL msglog!\n");
2794 return;
2795 }
2796
2797 catch_memory_errors = 1;
2798 sync();
2799
2800 xmon_start_pagination();
2801 while ((res = opal_msglog_copy(buf, pos, sizeof(buf) - 1))) {
2802 if (res < 0) {
2803 printf("Error dumping OPAL msglog! Error: %zd\n", res);
2804 break;
2805 }
2806 buf[res] = '\0';
2807 printf("%s", buf);
2808 pos += res;
2809 }
2810 xmon_end_pagination();
2811
2812 sync();
2813 /* wait a little while to see if we get a machine check */
2814 __delay(200);
2815 catch_memory_errors = 0;
2816}
2817#endif
2818
1da177e4
LT
2819/*
2820 * Memory operations - move, set, print differences
2821 */
2822static unsigned long mdest; /* destination address */
2823static unsigned long msrc; /* source address */
2824static unsigned long mval; /* byte value to set memory to */
2825static unsigned long mcount; /* # bytes to affect */
2826static unsigned long mdiffs; /* max # differences to print */
2827
9f1067c2 2828static void
1da177e4
LT
2829memops(int cmd)
2830{
2831 scanhex((void *)&mdest);
2832 if( termch != '\n' )
2833 termch = 0;
2834 scanhex((void *)(cmd == 's'? &mval: &msrc));
2835 if( termch != '\n' )
2836 termch = 0;
2837 scanhex((void *)&mcount);
2838 switch( cmd ){
2839 case 'm':
2840 memmove((void *)mdest, (void *)msrc, mcount);
2841 break;
2842 case 's':
2843 memset((void *)mdest, mval, mcount);
2844 break;
2845 case 'd':
2846 if( termch != '\n' )
2847 termch = 0;
2848 scanhex((void *)&mdiffs);
2849 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2850 break;
2851 }
2852}
2853
9f1067c2 2854static void
1da177e4
LT
2855memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2856{
2857 unsigned n, prt;
2858
2859 prt = 0;
2860 for( n = nb; n > 0; --n )
2861 if( *p1++ != *p2++ )
2862 if( ++prt <= maxpr )
2863 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2864 p1[-1], p2 - 1, p2[-1]);
2865 if( prt > maxpr )
2866 printf("Total of %d differences\n", prt);
2867}
2868
2869static unsigned mend;
2870static unsigned mask;
2871
9f1067c2 2872static void
1da177e4
LT
2873memlocate(void)
2874{
2875 unsigned a, n;
2876 unsigned char val[4];
2877
2878 last_cmd = "ml";
2879 scanhex((void *)&mdest);
2880 if (termch != '\n') {
2881 termch = 0;
2882 scanhex((void *)&mend);
2883 if (termch != '\n') {
2884 termch = 0;
2885 scanhex((void *)&mval);
2886 mask = ~0;
2887 if (termch != '\n') termch = 0;
2888 scanhex((void *)&mask);
2889 }
2890 }
2891 n = 0;
2892 for (a = mdest; a < mend; a += 4) {
2893 if (mread(a, val, 4) == 4
2894 && ((GETWORD(val) ^ mval) & mask) == 0) {
2895 printf("%.16x: %.16x\n", a, GETWORD(val));
2896 if (++n >= 10)
2897 break;
2898 }
2899 }
2900}
2901
2902static unsigned long mskip = 0x1000;
2903static unsigned long mlim = 0xffffffff;
2904
9f1067c2 2905static void
1da177e4
LT
2906memzcan(void)
2907{
2908 unsigned char v;
2909 unsigned a;
2910 int ok, ook;
2911
2912 scanhex(&mdest);
2913 if (termch != '\n') termch = 0;
2914 scanhex(&mskip);
2915 if (termch != '\n') termch = 0;
2916 scanhex(&mlim);
2917 ook = 0;
2918 for (a = mdest; a < mlim; a += mskip) {
2919 ok = mread(a, &v, 1);
2920 if (ok && !ook) {
2921 printf("%.8x .. ", a);
1da177e4
LT
2922 } else if (!ok && ook)
2923 printf("%.8x\n", a - mskip);
2924 ook = ok;
2925 if (a + mskip < a)
2926 break;
2927 }
2928 if (ook)
2929 printf("%.8x\n", a - mskip);
2930}
2931
6dfb5404
DM
2932static void show_task(struct task_struct *tsk)
2933{
2934 char state;
2935
2936 /*
2937 * Cloned from kdb_task_state_char(), which is not entirely
2938 * appropriate for calling from xmon. This could be moved
2939 * to a common, generic, routine used by both.
2940 */
2941 state = (tsk->state == 0) ? 'R' :
2942 (tsk->state < 0) ? 'U' :
2943 (tsk->state & TASK_UNINTERRUPTIBLE) ? 'D' :
2944 (tsk->state & TASK_STOPPED) ? 'T' :
2945 (tsk->state & TASK_TRACED) ? 'C' :
2946 (tsk->exit_state & EXIT_ZOMBIE) ? 'Z' :
2947 (tsk->exit_state & EXIT_DEAD) ? 'E' :
2948 (tsk->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
2949
d8104182 2950 printf("%px %016lx %6d %6d %c %2d %s\n", tsk,
6dfb5404
DM
2951 tsk->thread.ksp,
2952 tsk->pid, tsk->parent->pid,
2953 state, task_thread_info(tsk)->cpu,
2954 tsk->comm);
2955}
2956
80eff6c4
BS
2957#ifdef CONFIG_PPC_BOOK3S_64
2958void format_pte(void *ptep, unsigned long pte)
2959{
2960 printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte);
2961 printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK);
2962
2963 printf("Flags = %s%s%s%s%s\n",
2964 (pte & _PAGE_ACCESSED) ? "Accessed " : "",
2965 (pte & _PAGE_DIRTY) ? "Dirty " : "",
2966 (pte & _PAGE_READ) ? "Read " : "",
2967 (pte & _PAGE_WRITE) ? "Write " : "",
2968 (pte & _PAGE_EXEC) ? "Exec " : "");
2969}
2970
2971static void show_pte(unsigned long addr)
2972{
2973 unsigned long tskv = 0;
2974 struct task_struct *tsk = NULL;
2975 struct mm_struct *mm;
2976 pgd_t *pgdp, *pgdir;
2977 pud_t *pudp;
2978 pmd_t *pmdp;
2979 pte_t *ptep;
2980
2981 if (!scanhex(&tskv))
2982 mm = &init_mm;
2983 else
2984 tsk = (struct task_struct *)tskv;
2985
2986 if (tsk == NULL)
2987 mm = &init_mm;
2988 else
2989 mm = tsk->active_mm;
2990
2991 if (setjmp(bus_error_jmp) != 0) {
2992 catch_memory_errors = 0;
d8104182 2993 printf("*** Error dumping pte for task %px\n", tsk);
80eff6c4
BS
2994 return;
2995 }
2996
2997 catch_memory_errors = 1;
2998 sync();
2999
3000 if (mm == &init_mm) {
3001 pgdp = pgd_offset_k(addr);
3002 pgdir = pgd_offset_k(0);
3003 } else {
3004 pgdp = pgd_offset(mm, addr);
3005 pgdir = pgd_offset(mm, 0);
3006 }
3007
3008 if (pgd_none(*pgdp)) {
3009 printf("no linux page table for address\n");
3010 return;
3011 }
3012
3013 printf("pgd @ 0x%016lx\n", pgdir);
3014
3015 if (pgd_huge(*pgdp)) {
3016 format_pte(pgdp, pgd_val(*pgdp));
3017 return;
3018 }
3019 printf("pgdp @ 0x%016lx = 0x%016lx\n", pgdp, pgd_val(*pgdp));
3020
3021 pudp = pud_offset(pgdp, addr);
3022
3023 if (pud_none(*pudp)) {
3024 printf("No valid PUD\n");
3025 return;
3026 }
3027
3028 if (pud_huge(*pudp)) {
3029 format_pte(pudp, pud_val(*pudp));
3030 return;
3031 }
3032
3033 printf("pudp @ 0x%016lx = 0x%016lx\n", pudp, pud_val(*pudp));
3034
3035 pmdp = pmd_offset(pudp, addr);
3036
3037 if (pmd_none(*pmdp)) {
3038 printf("No valid PMD\n");
3039 return;
3040 }
3041
3042 if (pmd_huge(*pmdp)) {
3043 format_pte(pmdp, pmd_val(*pmdp));
3044 return;
3045 }
3046 printf("pmdp @ 0x%016lx = 0x%016lx\n", pmdp, pmd_val(*pmdp));
3047
3048 ptep = pte_offset_map(pmdp, addr);
3049 if (pte_none(*ptep)) {
3050 printf("no valid PTE\n");
3051 return;
3052 }
3053
3054 format_pte(ptep, pte_val(*ptep));
3055
3056 sync();
3057 __delay(200);
3058 catch_memory_errors = 0;
3059}
3060#else
3061static void show_pte(unsigned long addr)
3062{
3063 printf("show_pte not yet implemented\n");
3064}
3065#endif /* CONFIG_PPC_BOOK3S_64 */
3066
6dfb5404
DM
3067static void show_tasks(void)
3068{
3069 unsigned long tskv;
3070 struct task_struct *tsk = NULL;
3071
3072 printf(" task_struct ->thread.ksp PID PPID S P CMD\n");
3073
3074 if (scanhex(&tskv))
3075 tsk = (struct task_struct *)tskv;
3076
3077 if (setjmp(bus_error_jmp) != 0) {
3078 catch_memory_errors = 0;
d8104182 3079 printf("*** Error dumping task %px\n", tsk);
6dfb5404
DM
3080 return;
3081 }
3082
3083 catch_memory_errors = 1;
3084 sync();
3085
3086 if (tsk)
3087 show_task(tsk);
3088 else
3089 for_each_process(tsk)
3090 show_task(tsk);
3091
3092 sync();
3093 __delay(200);
3094 catch_memory_errors = 0;
3095}
3096
9f1067c2 3097static void proccall(void)
f78541dc
PM
3098{
3099 unsigned long args[8];
3100 unsigned long ret;
3101 int i;
3102 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
3103 unsigned long, unsigned long, unsigned long,
3104 unsigned long, unsigned long, unsigned long);
3105 callfunc_t func;
3106
3107 if (!scanhex(&adrs))
3108 return;
3109 if (termch != '\n')
3110 termch = 0;
3111 for (i = 0; i < 8; ++i)
3112 args[i] = 0;
3113 for (i = 0; i < 8; ++i) {
3114 if (!scanhex(&args[i]) || termch == '\n')
3115 break;
3116 termch = 0;
3117 }
3118 func = (callfunc_t) adrs;
3119 ret = 0;
3120 if (setjmp(bus_error_jmp) == 0) {
3121 catch_memory_errors = 1;
3122 sync();
3123 ret = func(args[0], args[1], args[2], args[3],
3124 args[4], args[5], args[6], args[7]);
3125 sync();
736256e4 3126 printf("return value is 0x%lx\n", ret);
f78541dc
PM
3127 } else {
3128 printf("*** %x exception occurred\n", fault_except);
3129 }
3130 catch_memory_errors = 0;
3131}
3132
1da177e4
LT
3133/* Input scanning routines */
3134int
3135skipbl(void)
3136{
3137 int c;
3138
3139 if( termch != 0 ){
3140 c = termch;
3141 termch = 0;
3142 } else
3143 c = inchar();
3144 while( c == ' ' || c == '\t' )
3145 c = inchar();
3146 return c;
3147}
3148
3149#define N_PTREGS 44
3150static char *regnames[N_PTREGS] = {
3151 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
3152 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
3153 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
3154 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
f78541dc
PM
3155 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
3156#ifdef CONFIG_PPC64
3157 "softe",
3158#else
3159 "mq",
3160#endif
1da177e4
LT
3161 "trap", "dar", "dsisr", "res"
3162};
3163
3164int
3165scanhex(unsigned long *vp)
3166{
3167 int c, d;
3168 unsigned long v;
3169
3170 c = skipbl();
3171 if (c == '%') {
3172 /* parse register name */
3173 char regname[8];
3174 int i;
3175
3176 for (i = 0; i < sizeof(regname) - 1; ++i) {
3177 c = inchar();
3178 if (!isalnum(c)) {
3179 termch = c;
3180 break;
3181 }
3182 regname[i] = c;
3183 }
3184 regname[i] = 0;
3185 for (i = 0; i < N_PTREGS; ++i) {
3186 if (strcmp(regnames[i], regname) == 0) {
3187 if (xmon_regs == NULL) {
3188 printf("regs not available\n");
3189 return 0;
3190 }
3191 *vp = ((unsigned long *)xmon_regs)[i];
3192 return 1;
3193 }
3194 }
3195 printf("invalid register name '%%%s'\n", regname);
3196 return 0;
3197 }
3198
3199 /* skip leading "0x" if any */
3200
3201 if (c == '0') {
3202 c = inchar();
3203 if (c == 'x') {
3204 c = inchar();
3205 } else {
3206 d = hexdigit(c);
3207 if (d == EOF) {
3208 termch = c;
3209 *vp = 0;
3210 return 1;
3211 }
3212 }
3213 } else if (c == '$') {
3214 int i;
3215 for (i=0; i<63; i++) {
3216 c = inchar();
05b981f4 3217 if (isspace(c) || c == '\0') {
1da177e4
LT
3218 termch = c;
3219 break;
3220 }
3221 tmpstr[i] = c;
3222 }
3223 tmpstr[i++] = 0;
6879dc13
BH
3224 *vp = 0;
3225 if (setjmp(bus_error_jmp) == 0) {
3226 catch_memory_errors = 1;
3227 sync();
3228 *vp = kallsyms_lookup_name(tmpstr);
3229 sync();
3230 }
3231 catch_memory_errors = 0;
1da177e4
LT
3232 if (!(*vp)) {
3233 printf("unknown symbol '%s'\n", tmpstr);
3234 return 0;
3235 }
3236 return 1;
3237 }
3238
3239 d = hexdigit(c);
3240 if (d == EOF) {
3241 termch = c;
3242 return 0;
3243 }
3244 v = 0;
3245 do {
3246 v = (v << 4) + d;
3247 c = inchar();
3248 d = hexdigit(c);
3249 } while (d != EOF);
3250 termch = c;
3251 *vp = v;
3252 return 1;
3253}
3254
9f1067c2 3255static void
1da177e4
LT
3256scannl(void)
3257{
3258 int c;
3259
3260 c = termch;
3261 termch = 0;
3262 while( c != '\n' )
3263 c = inchar();
3264}
3265
9f1067c2 3266static int hexdigit(int c)
1da177e4
LT
3267{
3268 if( '0' <= c && c <= '9' )
3269 return c - '0';
3270 if( 'A' <= c && c <= 'F' )
3271 return c - ('A' - 10);
3272 if( 'a' <= c && c <= 'f' )
3273 return c - ('a' - 10);
3274 return EOF;
3275}
3276
3277void
3278getstring(char *s, int size)
3279{
3280 int c;
3281
3282 c = skipbl();
3283 do {
3284 if( size > 1 ){
3285 *s++ = c;
3286 --size;
3287 }
3288 c = inchar();
3289 } while( c != ' ' && c != '\t' && c != '\n' );
3290 termch = c;
3291 *s = 0;
3292}
3293
3294static char line[256];
3295static char *lineptr;
3296
9f1067c2 3297static void
1da177e4
LT
3298flush_input(void)
3299{
3300 lineptr = NULL;
3301}
3302
9f1067c2 3303static int
1da177e4
LT
3304inchar(void)
3305{
3306 if (lineptr == NULL || *lineptr == 0) {
fca5dcd4 3307 if (xmon_gets(line, sizeof(line)) == NULL) {
1da177e4
LT
3308 lineptr = NULL;
3309 return EOF;
3310 }
3311 lineptr = line;
3312 }
3313 return *lineptr++;
3314}
3315
9f1067c2 3316static void
1da177e4
LT
3317take_input(char *str)
3318{
3319 lineptr = str;
3320}
3321
3322
3323static void
3324symbol_lookup(void)
3325{
3326 int type = inchar();
3327 unsigned long addr;
3328 static char tmp[64];
3329
3330 switch (type) {
3331 case 'a':
3332 if (scanhex(&addr))
3333 xmon_print_symbol(addr, ": ", "\n");
3334 termch = 0;
3335 break;
3336 case 's':
3337 getstring(tmp, 64);
3338 if (setjmp(bus_error_jmp) == 0) {
3339 catch_memory_errors = 1;
3340 sync();
3341 addr = kallsyms_lookup_name(tmp);
3342 if (addr)
3343 printf("%s: %lx\n", tmp, addr);
3344 else
3345 printf("Symbol '%s' not found.\n", tmp);
3346 sync();
3347 }
3348 catch_memory_errors = 0;
3349 termch = 0;
3350 break;
3351 }
3352}
3353
3354
3355/* Print an address in numeric and symbolic form (if possible) */
3356static void xmon_print_symbol(unsigned long address, const char *mid,
3357 const char *after)
3358{
3359 char *modname;
3360 const char *name = NULL;
3361 unsigned long offset, size;
3362
f78541dc 3363 printf(REG, address);
1da177e4
LT
3364 if (setjmp(bus_error_jmp) == 0) {
3365 catch_memory_errors = 1;
3366 sync();
3367 name = kallsyms_lookup(address, &size, &offset, &modname,
3368 tmpstr);
3369 sync();
3370 /* wait a little while to see if we get a machine check */
3371 __delay(200);
3372 }
3373
3374 catch_memory_errors = 0;
3375
3376 if (name) {
3377 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
3378 if (modname)
3379 printf(" [%s]", modname);
3380 }
3381 printf("%s", after);
3382}
3383
4e003747 3384#ifdef CONFIG_PPC_BOOK3S_64
13b3d13b 3385void dump_segments(void)
1da177e4
LT
3386{
3387 int i;
8218a303 3388 unsigned long esid,vsid;
b3b9595f 3389 unsigned long llp;
1da177e4 3390
736256e4 3391 printf("SLB contents of cpu 0x%x\n", smp_processor_id());
1da177e4 3392
584f8b71 3393 for (i = 0; i < mmu_slb_size; i++) {
b3b9595f 3394 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
3395 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
85673646
ME
3396
3397 if (!esid && !vsid)
3398 continue;
3399
3400 printf("%02d %016lx %016lx", i, esid, vsid);
3401
3402 if (!(esid & SLB_ESID_V)) {
3403 printf("\n");
3404 continue;
3405 }
3406
3407 llp = vsid & SLB_VSID_LLP;
3408 if (vsid & SLB_VSID_B_1T) {
3409 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
3410 GET_ESID_1T(esid),
3411 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
3412 llp);
3413 } else {
3414 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
3415 GET_ESID(esid),
3416 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
3417 llp);
b3b9595f 3418 }
1da177e4
LT
3419 }
3420}
f78541dc
PM
3421#endif
3422
3423#ifdef CONFIG_PPC_STD_MMU_32
3424void dump_segments(void)
3425{
3426 int i;
3427
3428 printf("sr0-15 =");
3429 for (i = 0; i < 16; ++i)
3430 printf(" %x", mfsrin(i));
3431 printf("\n");
3432}
3433#endif
3434
5a8a1a28
BH
3435#ifdef CONFIG_44x
3436static void dump_tlb_44x(void)
3437{
3438 int i;
3439
3440 for (i = 0; i < PPC44x_TLB_SIZE; i++) {
3441 unsigned long w0,w1,w2;
3442 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
3443 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
3444 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
3445 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
3446 if (w0 & PPC44x_TLB_VALID) {
3447 printf("V %08x -> %01x%08x %c%c%c%c%c",
3448 w0 & PPC44x_TLB_EPN_MASK,
3449 w1 & PPC44x_TLB_ERPN_MASK,
3450 w1 & PPC44x_TLB_RPN_MASK,
3451 (w2 & PPC44x_TLB_W) ? 'W' : 'w',
3452 (w2 & PPC44x_TLB_I) ? 'I' : 'i',
3453 (w2 & PPC44x_TLB_M) ? 'M' : 'm',
3454 (w2 & PPC44x_TLB_G) ? 'G' : 'g',
3455 (w2 & PPC44x_TLB_E) ? 'E' : 'e');
3456 }
3457 printf("\n");
3458 }
3459}
3460#endif /* CONFIG_44x */
9f1067c2 3461
03247157
BH
3462#ifdef CONFIG_PPC_BOOK3E
3463static void dump_tlb_book3e(void)
3464{
3465 u32 mmucfg, pidmask, lpidmask;
3466 u64 ramask;
3467 int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
3468 int mmu_version;
3469 static const char *pgsz_names[] = {
3470 " 1K",
3471 " 2K",
3472 " 4K",
3473 " 8K",
3474 " 16K",
3475 " 32K",
3476 " 64K",
3477 "128K",
3478 "256K",
3479 "512K",
3480 " 1M",
3481 " 2M",
3482 " 4M",
3483 " 8M",
3484 " 16M",
3485 " 32M",
3486 " 64M",
3487 "128M",
3488 "256M",
3489 "512M",
3490 " 1G",
3491 " 2G",
3492 " 4G",
3493 " 8G",
3494 " 16G",
3495 " 32G",
3496 " 64G",
3497 "128G",
3498 "256G",
3499 "512G",
3500 " 1T",
3501 " 2T",
3502 };
3503
3504 /* Gather some infos about the MMU */
3505 mmucfg = mfspr(SPRN_MMUCFG);
3506 mmu_version = (mmucfg & 3) + 1;
3507 ntlbs = ((mmucfg >> 2) & 3) + 1;
3508 pidsz = ((mmucfg >> 6) & 0x1f) + 1;
3509 lpidsz = (mmucfg >> 24) & 0xf;
3510 rasz = (mmucfg >> 16) & 0x7f;
3511 if ((mmu_version > 1) && (mmucfg & 0x10000))
3512 lrat = 1;
3513 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
3514 mmu_version, ntlbs, pidsz, lpidsz, rasz);
3515 pidmask = (1ul << pidsz) - 1;
3516 lpidmask = (1ul << lpidsz) - 1;
3517 ramask = (1ull << rasz) - 1;
3518
3519 for (tlb = 0; tlb < ntlbs; tlb++) {
3520 u32 tlbcfg;
3521 int nent, assoc, new_cc = 1;
3522 printf("TLB %d:\n------\n", tlb);
3523 switch(tlb) {
3524 case 0:
3525 tlbcfg = mfspr(SPRN_TLB0CFG);
3526 break;
3527 case 1:
3528 tlbcfg = mfspr(SPRN_TLB1CFG);
3529 break;
3530 case 2:
3531 tlbcfg = mfspr(SPRN_TLB2CFG);
3532 break;
3533 case 3:
3534 tlbcfg = mfspr(SPRN_TLB3CFG);
3535 break;
3536 default:
3537 printf("Unsupported TLB number !\n");
3538 continue;
3539 }
3540 nent = tlbcfg & 0xfff;
3541 assoc = (tlbcfg >> 24) & 0xff;
3542 for (i = 0; i < nent; i++) {
3543 u32 mas0 = MAS0_TLBSEL(tlb);
3544 u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
3545 u64 mas2 = 0;
3546 u64 mas7_mas3;
3547 int esel = i, cc = i;
3548
3549 if (assoc != 0) {
3550 cc = i / assoc;
3551 esel = i % assoc;
3552 mas2 = cc * 0x1000;
3553 }
3554
3555 mas0 |= MAS0_ESEL(esel);
3556 mtspr(SPRN_MAS0, mas0);
3557 mtspr(SPRN_MAS1, mas1);
3558 mtspr(SPRN_MAS2, mas2);
3559 asm volatile("tlbre 0,0,0" : : : "memory");
3560 mas1 = mfspr(SPRN_MAS1);
3561 mas2 = mfspr(SPRN_MAS2);
3562 mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
3563 if (assoc && (i % assoc) == 0)
3564 new_cc = 1;
3565 if (!(mas1 & MAS1_VALID))
3566 continue;
3567 if (assoc == 0)
3568 printf("%04x- ", i);
3569 else if (new_cc)
3570 printf("%04x-%c", cc, 'A' + esel);
3571 else
3572 printf(" |%c", 'A' + esel);
3573 new_cc = 0;
3574 printf(" %016llx %04x %s %c%c AS%c",
3575 mas2 & ~0x3ffull,
3576 (mas1 >> 16) & 0x3fff,
3577 pgsz_names[(mas1 >> 7) & 0x1f],
3578 mas1 & MAS1_IND ? 'I' : ' ',
3579 mas1 & MAS1_IPROT ? 'P' : ' ',
3580 mas1 & MAS1_TS ? '1' : '0');
3581 printf(" %c%c%c%c%c%c%c",
3582 mas2 & MAS2_X0 ? 'a' : ' ',
3583 mas2 & MAS2_X1 ? 'v' : ' ',
3584 mas2 & MAS2_W ? 'w' : ' ',
3585 mas2 & MAS2_I ? 'i' : ' ',
3586 mas2 & MAS2_M ? 'm' : ' ',
3587 mas2 & MAS2_G ? 'g' : ' ',
3588 mas2 & MAS2_E ? 'e' : ' ');
3589 printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
3590 if (mas1 & MAS1_IND)
3591 printf(" %s\n",
3592 pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
3593 else
3594 printf(" U%c%c%c S%c%c%c\n",
3595 mas7_mas3 & MAS3_UX ? 'x' : ' ',
3596 mas7_mas3 & MAS3_UW ? 'w' : ' ',
3597 mas7_mas3 & MAS3_UR ? 'r' : ' ',
3598 mas7_mas3 & MAS3_SX ? 'x' : ' ',
3599 mas7_mas3 & MAS3_SW ? 'w' : ' ',
3600 mas7_mas3 & MAS3_SR ? 'r' : ' ');
3601 }
3602 }
3603}
3604#endif /* CONFIG_PPC_BOOK3E */
3605
9f1067c2 3606static void xmon_init(int enable)
b13cfd17
OH
3607{
3608 if (enable) {
3609 __debugger = xmon;
3610 __debugger_ipi = xmon_ipi;
3611 __debugger_bpt = xmon_bpt;
3612 __debugger_sstep = xmon_sstep;
3613 __debugger_iabr_match = xmon_iabr_match;
9422de3e 3614 __debugger_break_match = xmon_break_match;
b13cfd17
OH
3615 __debugger_fault_handler = xmon_fault_handler;
3616 } else {
3617 __debugger = NULL;
3618 __debugger_ipi = NULL;
3619 __debugger_bpt = NULL;
3620 __debugger_sstep = NULL;
3621 __debugger_iabr_match = NULL;
9422de3e 3622 __debugger_break_match = NULL;
b13cfd17
OH
3623 __debugger_fault_handler = NULL;
3624 }
1da177e4 3625}
fca5dcd4
PM
3626
3627#ifdef CONFIG_MAGIC_SYSRQ
1495cc9d 3628static void sysrq_handle_xmon(int key)
fca5dcd4
PM
3629{
3630 /* ensure xmon is enabled */
3631 xmon_init(1);
7d12e780 3632 debugger(get_irq_regs());
3b5bf42b
PX
3633 if (!xmon_on)
3634 xmon_init(0);
fca5dcd4
PM
3635}
3636
1495cc9d 3637static struct sysrq_key_op sysrq_xmon_op = {
fca5dcd4 3638 .handler = sysrq_handle_xmon,
90a102e5 3639 .help_msg = "xmon(x)",
fca5dcd4
PM
3640 .action_msg = "Entering xmon",
3641};
3642
3643static int __init setup_xmon_sysrq(void)
3644{
3645 register_sysrq_key('x', &sysrq_xmon_op);
3646 return 0;
3647}
b561783c 3648device_initcall(setup_xmon_sysrq);
fca5dcd4 3649#endif /* CONFIG_MAGIC_SYSRQ */
47679283 3650
de78ae6c
GP
3651#ifdef CONFIG_DEBUG_FS
3652static int xmon_dbgfs_set(void *data, u64 val)
3653{
3654 xmon_on = !!val;
3655 xmon_init(xmon_on);
3656
3657 return 0;
3658}
3659
3660static int xmon_dbgfs_get(void *data, u64 *val)
3661{
3662 *val = xmon_on;
3663 return 0;
3664}
3665
3666DEFINE_SIMPLE_ATTRIBUTE(xmon_dbgfs_ops, xmon_dbgfs_get,
3667 xmon_dbgfs_set, "%llu\n");
3668
3669static int __init setup_xmon_dbgfs(void)
3670{
3671 debugfs_create_file("xmon", 0600, powerpc_debugfs_root, NULL,
3672 &xmon_dbgfs_ops);
3673 return 0;
3674}
3675device_initcall(setup_xmon_dbgfs);
3676#endif /* CONFIG_DEBUG_FS */
3677
b561783c 3678static int xmon_early __initdata;
47679283
ME
3679
3680static int __init early_parse_xmon(char *p)
3681{
3682 if (!p || strncmp(p, "early", 5) == 0) {
3683 /* just "xmon" is equivalent to "xmon=early" */
3684 xmon_init(1);
3685 xmon_early = 1;
3b5bf42b
PX
3686 xmon_on = 1;
3687 } else if (strncmp(p, "on", 2) == 0) {
47679283 3688 xmon_init(1);
3b5bf42b
PX
3689 xmon_on = 1;
3690 } else if (strncmp(p, "off", 3) == 0)
3691 xmon_on = 0;
47679283
ME
3692 else
3693 return 1;
3694
3695 return 0;
3696}
3697early_param("xmon", early_parse_xmon);
3698
3699void __init xmon_setup(void)
3700{
3b5bf42b 3701 if (xmon_on)
47679283 3702 xmon_init(1);
47679283
ME
3703 if (xmon_early)
3704 debugger(NULL);
3705}
ff8a8f25 3706
e055595d 3707#ifdef CONFIG_SPU_BASE
ff8a8f25
ME
3708
3709struct spu_info {
3710 struct spu *spu;
3711 u64 saved_mfc_sr1_RW;
3712 u32 saved_spu_runcntl_RW;
24a24c85 3713 unsigned long dump_addr;
ff8a8f25
ME
3714 u8 stopped_ok;
3715};
3716
3717#define XMON_NUM_SPUS 16 /* Enough for current hardware */
3718
3719static struct spu_info spu_info[XMON_NUM_SPUS];
3720
3721void xmon_register_spus(struct list_head *list)
3722{
3723 struct spu *spu;
3724
3725 list_for_each_entry(spu, list, full_list) {
3726 if (spu->number >= XMON_NUM_SPUS) {
3727 WARN_ON(1);
3728 continue;
3729 }
3730
3731 spu_info[spu->number].spu = spu;
3732 spu_info[spu->number].stopped_ok = 0;
24a24c85
ME
3733 spu_info[spu->number].dump_addr = (unsigned long)
3734 spu_info[spu->number].spu->local_store;
ff8a8f25
ME
3735 }
3736}
3737
3738static void stop_spus(void)
3739{
3740 struct spu *spu;
3741 int i;
3742 u64 tmp;
3743
3744 for (i = 0; i < XMON_NUM_SPUS; i++) {
3745 if (!spu_info[i].spu)
3746 continue;
3747
3748 if (setjmp(bus_error_jmp) == 0) {
3749 catch_memory_errors = 1;
3750 sync();
3751
3752 spu = spu_info[i].spu;
3753
3754 spu_info[i].saved_spu_runcntl_RW =
3755 in_be32(&spu->problem->spu_runcntl_RW);
3756
3757 tmp = spu_mfc_sr1_get(spu);
3758 spu_info[i].saved_mfc_sr1_RW = tmp;
3759
3760 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
3761 spu_mfc_sr1_set(spu, tmp);
3762
3763 sync();
3764 __delay(200);
3765
3766 spu_info[i].stopped_ok = 1;
2a14442b
ME
3767
3768 printf("Stopped spu %.2d (was %s)\n", i,
3769 spu_info[i].saved_spu_runcntl_RW ?
3770 "running" : "stopped");
ff8a8f25
ME
3771 } else {
3772 catch_memory_errors = 0;
3773 printf("*** Error stopping spu %.2d\n", i);
3774 }
3775 catch_memory_errors = 0;
3776 }
3777}
3778
3779static void restart_spus(void)
3780{
3781 struct spu *spu;
3782 int i;
3783
3784 for (i = 0; i < XMON_NUM_SPUS; i++) {
3785 if (!spu_info[i].spu)
3786 continue;
3787
3788 if (!spu_info[i].stopped_ok) {
3789 printf("*** Error, spu %d was not successfully stopped"
3790 ", not restarting\n", i);
3791 continue;
3792 }
3793
3794 if (setjmp(bus_error_jmp) == 0) {
3795 catch_memory_errors = 1;
3796 sync();
3797
3798 spu = spu_info[i].spu;
3799 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3800 out_be32(&spu->problem->spu_runcntl_RW,
3801 spu_info[i].saved_spu_runcntl_RW);
3802
3803 sync();
3804 __delay(200);
3805
3806 printf("Restarted spu %.2d\n", i);
3807 } else {
3808 catch_memory_errors = 0;
3809 printf("*** Error restarting spu %.2d\n", i);
3810 }
3811 catch_memory_errors = 0;
3812 }
3813}
3814
a8984970 3815#define DUMP_WIDTH 23
437a0706 3816#define DUMP_VALUE(format, field, value) \
a8984970
ME
3817do { \
3818 if (setjmp(bus_error_jmp) == 0) { \
3819 catch_memory_errors = 1; \
3820 sync(); \
3821 printf(" %-*s = "format"\n", DUMP_WIDTH, \
437a0706 3822 #field, value); \
a8984970
ME
3823 sync(); \
3824 __delay(200); \
3825 } else { \
3826 catch_memory_errors = 0; \
3827 printf(" %-*s = *** Error reading field.\n", \
3828 DUMP_WIDTH, #field); \
3829 } \
3830 catch_memory_errors = 0; \
3831} while (0)
3832
437a0706
ME
3833#define DUMP_FIELD(obj, format, field) \
3834 DUMP_VALUE(format, field, obj->field)
3835
a8984970
ME
3836static void dump_spu_fields(struct spu *spu)
3837{
3838 printf("Dumping spu fields at address %p:\n", spu);
3839
3840 DUMP_FIELD(spu, "0x%x", number);
3841 DUMP_FIELD(spu, "%s", name);
a8984970
ME
3842 DUMP_FIELD(spu, "0x%lx", local_store_phys);
3843 DUMP_FIELD(spu, "0x%p", local_store);
3844 DUMP_FIELD(spu, "0x%lx", ls_size);
3845 DUMP_FIELD(spu, "0x%x", node);
3846 DUMP_FIELD(spu, "0x%lx", flags);
a8984970 3847 DUMP_FIELD(spu, "%d", class_0_pending);
f3d69e05 3848 DUMP_FIELD(spu, "0x%lx", class_0_dar);
f3d69e05
LB
3849 DUMP_FIELD(spu, "0x%lx", class_1_dar);
3850 DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
a8984970
ME
3851 DUMP_FIELD(spu, "0x%lx", irqs[0]);
3852 DUMP_FIELD(spu, "0x%lx", irqs[1]);
3853 DUMP_FIELD(spu, "0x%lx", irqs[2]);
3854 DUMP_FIELD(spu, "0x%x", slb_replace);
3855 DUMP_FIELD(spu, "%d", pid);
a8984970
ME
3856 DUMP_FIELD(spu, "0x%p", mm);
3857 DUMP_FIELD(spu, "0x%p", ctx);
3858 DUMP_FIELD(spu, "0x%p", rq);
3859 DUMP_FIELD(spu, "0x%p", timestamp);
3860 DUMP_FIELD(spu, "0x%lx", problem_phys);
3861 DUMP_FIELD(spu, "0x%p", problem);
437a0706
ME
3862 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3863 in_be32(&spu->problem->spu_runcntl_RW));
3864 DUMP_VALUE("0x%x", problem->spu_status_R,
3865 in_be32(&spu->problem->spu_status_R));
3866 DUMP_VALUE("0x%x", problem->spu_npc_RW,
3867 in_be32(&spu->problem->spu_npc_RW));
a8984970 3868 DUMP_FIELD(spu, "0x%p", priv2);
a985239b 3869 DUMP_FIELD(spu, "0x%p", pdata);
a8984970
ME
3870}
3871
af89fb80
ME
3872int
3873spu_inst_dump(unsigned long adr, long count, int praddr)
3874{
3875 return generic_inst_dump(adr, count, praddr, print_insn_spu);
3876}
3877
3878static void dump_spu_ls(unsigned long num, int subcmd)
24a24c85
ME
3879{
3880 unsigned long offset, addr, ls_addr;
3881
3882 if (setjmp(bus_error_jmp) == 0) {
3883 catch_memory_errors = 1;
3884 sync();
3885 ls_addr = (unsigned long)spu_info[num].spu->local_store;
3886 sync();
3887 __delay(200);
3888 } else {
3889 catch_memory_errors = 0;
3890 printf("*** Error: accessing spu info for spu %d\n", num);
3891 return;
3892 }
3893 catch_memory_errors = 0;
3894
3895 if (scanhex(&offset))
3896 addr = ls_addr + offset;
3897 else
3898 addr = spu_info[num].dump_addr;
3899
3900 if (addr >= ls_addr + LS_SIZE) {
3901 printf("*** Error: address outside of local store\n");
3902 return;
3903 }
3904
af89fb80
ME
3905 switch (subcmd) {
3906 case 'i':
3907 addr += spu_inst_dump(addr, 16, 1);
3908 last_cmd = "sdi\n";
3909 break;
3910 default:
3911 prdump(addr, 64);
3912 addr += 64;
3913 last_cmd = "sd\n";
3914 break;
3915 }
24a24c85
ME
3916
3917 spu_info[num].dump_addr = addr;
3918}
3919
ff8a8f25
ME
3920static int do_spu_cmd(void)
3921{
24a24c85 3922 static unsigned long num = 0;
af89fb80 3923 int cmd, subcmd = 0;
ff8a8f25
ME
3924
3925 cmd = inchar();
3926 switch (cmd) {
3927 case 's':
3928 stop_spus();
3929 break;
3930 case 'r':
3931 restart_spus();
3932 break;
24a24c85 3933 case 'd':
af89fb80
ME
3934 subcmd = inchar();
3935 if (isxdigit(subcmd) || subcmd == '\n')
3936 termch = subcmd;
3937 case 'f':
24a24c85
ME
3938 scanhex(&num);
3939 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
a8984970 3940 printf("*** Error: invalid spu number\n");
24a24c85
ME
3941 return 0;
3942 }
3943
3944 switch (cmd) {
3945 case 'f':
3946 dump_spu_fields(spu_info[num].spu);
3947 break;
3948 default:
af89fb80 3949 dump_spu_ls(num, subcmd);
24a24c85
ME
3950 break;
3951 }
3952
a8984970 3953 break;
ff8a8f25
ME
3954 default:
3955 return -1;
3956 }
3957
3958 return 0;
3959}
e055595d 3960#else /* ! CONFIG_SPU_BASE */
ff8a8f25
ME
3961static int do_spu_cmd(void)
3962{
3963 return -1;
3964}
3965#endif