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