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