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