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