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

source code of linux/arch/powerpc/xmon/xmon.c