File: /usr/src/linux/arch/ppc/xmon/xmon.c

1     /*
2      * BK Id: SCCS/s.xmon.c 1.14 06/28/01 15:50:17 paulus
3      */
4     /*
5      * Routines providing a simple monitor for use on the PowerMac.
6      *
7      * Copyright (C) 1996 Paul Mackerras.
8      */
9     #include <linux/config.h>
10     #include <linux/errno.h>
11     #include <linux/sched.h>
12     #include <linux/smp.h>
13     #include <asm/ptrace.h>
14     #include <asm/string.h>
15     #include <asm/prom.h>
16     #include <asm/bitops.h>
17     #include "nonstdio.h"
18     #include "privinst.h"
19     
20     #define scanhex	xmon_scanhex
21     #define skipbl	xmon_skipbl
22     
23     #ifdef CONFIG_SMP
24     static unsigned long cpus_in_xmon = 0;
25     static unsigned long got_xmon = 0;
26     static volatile int take_xmon = -1;
27     #endif /* CONFIG_SMP */
28     
29     static unsigned adrs;
30     static int size = 1;
31     static unsigned ndump = 64;
32     static unsigned nidump = 16;
33     static unsigned ncsum = 4096;
34     static int termch;
35     
36     static u_int bus_error_jmp[100];
37     #define setjmp xmon_setjmp
38     #define longjmp xmon_longjmp
39     
40     /* Breakpoint stuff */
41     struct bpt {
42     	unsigned address;
43     	unsigned instr;
44     	unsigned count;
45     	unsigned char enabled;
46     };
47     
48     #define NBPTS	16
49     static struct bpt bpts[NBPTS];
50     static struct bpt dabr;
51     static struct bpt iabr;
52     static unsigned bpinstr = 0x7fe00008;	/* trap */
53     
54     /* Prototypes */
55     extern void (*debugger_fault_handler)(struct pt_regs *);
56     static int cmds(struct pt_regs *);
57     static int mread(unsigned, void *, int);
58     static int mwrite(unsigned, void *, int);
59     static void handle_fault(struct pt_regs *);
60     static void byterev(unsigned char *, int);
61     static void memex(void);
62     static int bsesc(void);
63     static void dump(void);
64     static void prdump(unsigned, int);
65     #ifdef __MWERKS__
66     static void prndump(unsigned, int);
67     static int nvreadb(unsigned);
68     #endif
69     static int ppc_inst_dump(unsigned, int);
70     void print_address(unsigned);
71     static int getsp(void);
72     static void dump_hash_table(void);
73     static void backtrace(struct pt_regs *);
74     static void excprint(struct pt_regs *);
75     static void prregs(struct pt_regs *);
76     static void memops(int);
77     static void memlocate(void);
78     static void memzcan(void);
79     static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
80     int skipbl(void);
81     int scanhex(unsigned *valp);
82     static void scannl(void);
83     static int hexdigit(int);
84     void getstring(char *, int);
85     static void flush_input(void);
86     static int inchar(void);
87     static void take_input(char *);
88     /* static void openforth(void); */
89     static unsigned read_spr(int);
90     static void write_spr(int, unsigned);
91     static void super_regs(void);
92     static void print_sysmap(void);
93     static void remove_bpts(void);
94     static void insert_bpts(void);
95     static struct bpt *at_breakpoint(unsigned pc);
96     static void bpt_cmds(void);
97     static void cacheflush(void);
98     #ifdef CONFIG_SMP
99     static void cpu_cmd(void);
100     #endif /* CONFIG_SMP */
101     #if 0 /* Makes compile with -Wall */
102     static char *pretty_print_addr(unsigned long addr);
103     static char *lookup_name(unsigned long addr);
104     #endif
105     static void csum(void);
106     
107     extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
108     extern void printf(const char *fmt, ...);
109     extern int putchar(int ch);
110     extern int setjmp(u_int *);
111     extern void longjmp(u_int *, int);
112     
113     extern void xmon_enter(void);
114     extern void xmon_leave(void);
115     
116     #define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
117     
118     #define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
119     			 || ('a' <= (c) && (c) <= 'f') \
120     			 || ('A' <= (c) && (c) <= 'F'))
121     #define isalnum(c)	(('0' <= (c) && (c) <= '9') \
122     			 || ('a' <= (c) && (c) <= 'z') \
123     			 || ('A' <= (c) && (c) <= 'Z'))
124     
125     static char *help_string = "\
126     Commands:\n\
127       d	dump bytes\n\
128       di	dump instructions\n\
129       df	dump float values\n\
130       dd	dump double values\n\
131       e	print exception information\n\
132       h	dump hash table\n\
133       m	examine/change memory\n\
134       mm	move a block of memory\n\
135       ms	set a block of memory\n\
136       md	compare two blocks of memory\n\
137       M	print System.map\n\
138       r	print registers\n\
139       S	print special registers\n\
140       t	print backtrace\n\
141       x	exit monitor\n\
142     ";
143     
144     static int xmon_trace[NR_CPUS];
145     #define SSTEP	1		/* stepping because of 's' command */
146     #define BRSTEP	2		/* stepping over breakpoint */
147     
148     static struct pt_regs *xmon_regs[NR_CPUS];
149     
150     void
151     xmon(struct pt_regs *excp)
152     {
153     	struct pt_regs regs;
154     	int msr, cmd;
155     
156     	if (excp == NULL) {
157     		asm volatile ("stw	0,0(%0)\n\
158     			lwz	0,0(1)\n\
159     			stw	0,4(%0)\n\
160     			stmw	2,8(%0)" : : "b" (&regs));
161     		regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
162     		regs.msr = get_msr();
163     		regs.ctr = get_ctr();
164     		regs.xer = get_xer();
165     		regs.ccr = get_cr();
166     		regs.trap = 0;
167     		excp = &regs;
168     	}
169     
170     	msr = get_msr();
171     	set_msr(msr & ~0x8000);	/* disable interrupts */
172     	xmon_regs[smp_processor_id()] = excp;
173     	xmon_enter();
174     	excprint(excp);
175     #ifdef CONFIG_SMP
176     	if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
177     		for (;;)
178     			;
179     	while (test_and_set_bit(0, &got_xmon)) {
180     		if (take_xmon == smp_processor_id()) {
181     			take_xmon = -1;
182     			break;
183     		}
184     	}
185     	/*
186     	 * XXX: breakpoints are removed while any cpu is in xmon
187     	 */
188     #endif /* CONFIG_SMP */
189     	remove_bpts();
190     	cmd = cmds(excp);
191     	if (cmd == 's') {
192     		xmon_trace[smp_processor_id()] = SSTEP;
193     		excp->msr |= 0x400;
194     	} else if (at_breakpoint(excp->nip)) {
195     		xmon_trace[smp_processor_id()] = BRSTEP;
196     		excp->msr |= 0x400;
197     	} else {
198     		xmon_trace[smp_processor_id()] = 0;
199     		insert_bpts();
200     	}
201     	xmon_leave();
202     	xmon_regs[smp_processor_id()] = 0;
203     #ifdef CONFIG_SMP
204     	clear_bit(0, &got_xmon);
205     	clear_bit(smp_processor_id(), &cpus_in_xmon);
206     #endif /* CONFIG_SMP */
207     	set_msr(msr);		/* restore interrupt enable */
208     }
209     
210     void
211     xmon_irq(int irq, void *d, struct pt_regs *regs)
212     {
213     	unsigned long flags;
214     	__save_flags(flags);
215     	__cli();
216     	printf("Keyboard interrupt\n");
217     	xmon(regs);
218     	__restore_flags(flags);
219     }
220     
221     int
222     xmon_bpt(struct pt_regs *regs)
223     {
224     	struct bpt *bp;
225     
226     	bp = at_breakpoint(regs->nip);
227     	if (!bp)
228     		return 0;
229     	if (bp->count) {
230     		--bp->count;
231     		remove_bpts();
232     		excprint(regs);
233     		xmon_trace[smp_processor_id()] = BRSTEP;
234     		regs->msr |= 0x400;
235     	} else {
236     		xmon(regs);
237     	}
238     	return 1;
239     }
240     
241     int
242     xmon_sstep(struct pt_regs *regs)
243     {
244     	if (!xmon_trace[smp_processor_id()])
245     		return 0;
246     	if (xmon_trace[smp_processor_id()] == BRSTEP) {
247     		xmon_trace[smp_processor_id()] = 0;
248     		insert_bpts();
249     	} else {
250     		xmon(regs);
251     	}
252     	return 1;
253     }
254     
255     int
256     xmon_dabr_match(struct pt_regs *regs)
257     {
258     	if (dabr.enabled && dabr.count) {
259     		--dabr.count;
260     		remove_bpts();
261     		excprint(regs);
262     		xmon_trace[smp_processor_id()] = BRSTEP;
263     		regs->msr |= 0x400;
264     	} else {
265     		dabr.instr = regs->nip;
266     		xmon(regs);
267     	}
268     	return 1;
269     }
270     
271     int
272     xmon_iabr_match(struct pt_regs *regs)
273     {
274     	if (iabr.enabled && iabr.count) {
275     		--iabr.count;
276     		remove_bpts();
277     		excprint(regs);
278     		xmon_trace[smp_processor_id()] = BRSTEP;
279     		regs->msr |= 0x400;
280     	} else {
281     		xmon(regs);
282     	}
283     	return 1;
284     }
285     
286     static struct bpt *
287     at_breakpoint(unsigned pc)
288     {
289     	int i;
290     	struct bpt *bp;
291     
292     	if (dabr.enabled && pc == dabr.instr)
293     		return &dabr;
294     	if (iabr.enabled && pc == iabr.address)
295     		return &iabr;
296     	bp = bpts;
297     	for (i = 0; i < NBPTS; ++i, ++bp)
298     		if (bp->enabled && pc == bp->address)
299     			return bp;
300     	return 0;
301     }
302     
303     static void
304     insert_bpts()
305     {
306     	int i;
307     	struct bpt *bp;
308     
309     	bp = bpts;
310     	for (i = 0; i < NBPTS; ++i, ++bp) {
311     		if (!bp->enabled)
312     			continue;
313     		if (mread(bp->address, &bp->instr, 4) != 4
314     		    || mwrite(bp->address, &bpinstr, 4) != 4) {
315     			printf("Couldn't insert breakpoint at %x, disabling\n",
316     			       bp->address);
317     			bp->enabled = 0;
318     		}
319     		store_inst((void *) bp->address);
320     	}
321     #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
322     	if (dabr.enabled)
323     		set_dabr(dabr.address);
324     	if (iabr.enabled)
325     		set_iabr(iabr.address);
326     #endif
327     }
328     
329     static void
330     remove_bpts()
331     {
332     	int i;
333     	struct bpt *bp;
334     	unsigned instr;
335     
336     #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
337     	set_dabr(0);
338     	set_iabr(0);
339     #endif
340     	bp = bpts;
341     	for (i = 0; i < NBPTS; ++i, ++bp) {
342     		if (!bp->enabled)
343     			continue;
344     		if (mread(bp->address, &instr, 4) == 4
345     		    && instr == bpinstr
346     		    && mwrite(bp->address, &bp->instr, 4) != 4)
347     			printf("Couldn't remove breakpoint at %x\n",
348     			       bp->address);
349     		store_inst((void *) bp->address);
350     	}
351     }
352     
353     static char *last_cmd;
354     
355     /* Command interpreting routine */
356     static int
357     cmds(struct pt_regs *excp)
358     {
359     	int cmd;
360     
361     	last_cmd = NULL;
362     	for(;;) {
363     #ifdef CONFIG_SMP
364     		printf("%d:", smp_processor_id());
365     #endif /* CONFIG_SMP */
366     		printf("mon> ");
367     		fflush(stdout);
368     		flush_input();
369     		termch = 0;
370     		cmd = skipbl();
371     		if( cmd == '\n' ) {
372     			if (last_cmd == NULL)
373     				continue;
374     			take_input(last_cmd);
375     			last_cmd = NULL;
376     			cmd = inchar();
377     		}
378     		switch (cmd) {
379     		case 'm':
380     			cmd = inchar();
381     			switch (cmd) {
382     			case 'm':
383     			case 's':
384     			case 'd':
385     				memops(cmd);
386     				break;
387     			case 'l':
388     				memlocate();
389     				break;
390     			case 'z':
391     				memzcan();
392     				break;
393     			default:
394     				termch = cmd;
395     				memex();
396     			}
397     			break;
398     		case 'd':
399     			dump();
400     			break;
401     		case 'r':
402     			if (excp != NULL)
403     				prregs(excp);	/* print regs */
404     			break;
405     		case 'e':
406     			if (excp == NULL)
407     				printf("No exception information\n");
408     			else
409     				excprint(excp);
410     			break;
411     		case 'M':
412     			print_sysmap();
413     			break;
414     		case 'S':
415     			super_regs();
416     			break;
417     		case 't':
418     			backtrace(excp);
419     			break;
420     		case 'f':
421     			cacheflush();
422     			break;
423     		case 'h':
424     			dump_hash_table();
425     			break;
426     		case 's':
427     		case 'x':
428     		case EOF:
429     			return cmd;
430     		case '?':
431     			printf(help_string);
432     			break;
433     		default:
434     			printf("Unrecognized command: ");
435     			if( ' ' < cmd && cmd <= '~' )
436     				putchar(cmd);
437     			else
438     				printf("\\x%x", cmd);
439     			printf(" (type ? for help)\n");
440     			break;
441     		case 'b':
442     			bpt_cmds();
443     			break;
444     		case 'C':
445     			csum();
446     			break;
447     #ifdef CONFIG_SMP
448     		case 'c':
449     			cpu_cmd();
450     			break;
451     #endif /* CONFIG_SMP */
452     		}
453     	}
454     }
455     
456     #ifdef CONFIG_SMP
457     static void cpu_cmd(void)
458     {
459     	unsigned cpu;
460     	int timeout;
461     	int cmd;
462     
463     	cmd = inchar();
464     	if (cmd == 'i') {
465     		/* interrupt other cpu(s) */
466     		cpu = MSG_ALL_BUT_SELF;
467     		scanhex(&cpu);
468     		smp_send_xmon_break(cpu);
469     		return;
470     	}
471     	termch = cmd;
472     	if (!scanhex(&cpu)) {
473     		/* print cpus waiting or in xmon */
474     		printf("cpus stopped:");
475     		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
476     			if (test_bit(cpu, &cpus_in_xmon)) {
477     				printf(" %d", cpu);
478     				if (cpu == smp_processor_id())
479     					printf("*", cpu);
480     			}
481     		}
482     		printf("\n");
483     		return;
484     	}
485     	/* try to switch to cpu specified */
486     	take_xmon = cpu;
487     	timeout = 10000000;
488     	while (take_xmon >= 0) {
489     		if (--timeout == 0) {
490     			/* yes there's a race here */
491     			take_xmon = -1;
492     			printf("cpu %u didn't take control\n", cpu);
493     			return;
494     		}
495     	}
496     	/* now have to wait to be given control back */
497     	while (test_and_set_bit(0, &got_xmon)) {
498     		if (take_xmon == smp_processor_id()) {
499     			take_xmon = -1;
500     			break;
501     		}
502     	}
503     }
504     #endif /* CONFIG_SMP */
505     
506     static unsigned short fcstab[256] = {
507     	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
508     	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
509     	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
510     	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
511     	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
512     	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
513     	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
514     	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
515     	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
516     	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
517     	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
518     	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
519     	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
520     	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
521     	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
522     	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
523     	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
524     	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
525     	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
526     	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
527     	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
528     	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
529     	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
530     	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
531     	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
532     	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
533     	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
534     	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
535     	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
536     	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
537     	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
538     	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
539     };
540     
541     #define FCS(fcs, c)	(((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
542     
543     static void
544     csum(void)
545     {
546     	unsigned int i;
547     	unsigned short fcs;
548     	unsigned char v;
549     
550     	scanhex(&adrs);
551     	scanhex(&ncsum);
552     	fcs = 0xffff;
553     	for (i = 0; i < ncsum; ++i) {
554     		if (mread(adrs+i, &v, 1) == 0) {
555     			printf("csum stopped at %x\n", adrs+i);
556     			break;
557     		}
558     		fcs = FCS(fcs, v);
559     	}
560     	printf("%x\n", fcs);
561     }
562     
563     static void
564     bpt_cmds(void)
565     {
566     	int cmd;
567     	unsigned a;
568     	int mode, i;
569     	struct bpt *bp;
570     
571     	cmd = inchar();
572     	switch (cmd) {
573     #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
574     	case 'd':
575     		mode = 7;
576     		cmd = inchar();
577     		if (cmd == 'r')
578     			mode = 5;
579     		else if (cmd == 'w')
580     			mode = 6;
581     		else
582     			termch = cmd;
583     		dabr.address = 0;
584     		dabr.count = 0;
585     		dabr.enabled = scanhex(&dabr.address);
586     		scanhex(&dabr.count);
587     		if (dabr.enabled)
588     			dabr.address = (dabr.address & ~7) | mode;
589     		break;
590     	case 'i':
591     		iabr.address = 0;
592     		iabr.count = 0;
593     		iabr.enabled = scanhex(&iabr.address);
594     		if (iabr.enabled)
595     			iabr.address |= 3;
596     		scanhex(&iabr.count);
597     		break;
598     #endif
599     	case 'c':
600     		if (!scanhex(&a)) {
601     			/* clear all breakpoints */
602     			for (i = 0; i < NBPTS; ++i)
603     				bpts[i].enabled = 0;
604     			iabr.enabled = 0;
605     			dabr.enabled = 0;
606     			printf("All breakpoints cleared\n");
607     		} else {
608     			bp = at_breakpoint(a);
609     			if (bp == 0) {
610     				printf("No breakpoint at %x\n", a);
611     			} else {
612     				bp->enabled = 0;
613     			}
614     		}
615     		break;
616     	default:
617     		termch = cmd;
618     		if (!scanhex(&a)) {
619     			/* print all breakpoints */
620     			printf("type  address   count\n");
621     			if (dabr.enabled) {
622     				printf("data %.8x %8x [", dabr.address & ~7,
623     				       dabr.count);
624     				if (dabr.address & 1)
625     					printf("r");
626     				if (dabr.address & 2)
627     					printf("w");
628     				printf("]\n");
629     			}
630     			if (iabr.enabled)
631     				printf("inst %.8x %8x\n", iabr.address & ~3,
632     				       iabr.count);
633     			for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
634     				if (bp->enabled)
635     					printf("trap %.8x %8x\n", bp->address,
636     					       bp->count);
637     			break;
638     		}
639     		bp = at_breakpoint(a);
640     		if (bp == 0) {
641     			for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
642     				if (!bp->enabled)
643     					break;
644     			if (bp >= &bpts[NBPTS]) {
645     				printf("Sorry, no free breakpoints\n");
646     				break;
647     			}
648     		}
649     		bp->enabled = 1;
650     		bp->address = a;
651     		bp->count = 0;
652     		scanhex(&bp->count);
653     		break;
654     	}
655     }
656     
657     static void
658     backtrace(struct pt_regs *excp)
659     {
660     	unsigned sp;
661     	unsigned stack[2];
662     	struct pt_regs regs;
663     	extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2;
664     	extern char do_signal_ret, ret_from_except;
665     
666     	printf("backtrace:\n");
667     	
668     	if (excp != NULL)
669     		sp = excp->gpr[1];
670     	else
671     		sp = getsp();
672     	scanhex(&sp);
673     	scannl();
674     	for (; sp != 0; sp = stack[0]) {
675     		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
676     			break;
677     		printf("%x ", stack[1]);
678     		if (stack[1] == (unsigned) &ret_from_intercept
679     		    || stack[1] == (unsigned) &ret_from_except
680     		    || stack[1] == (unsigned) &ret_from_syscall_1
681     		    || stack[1] == (unsigned) &ret_from_syscall_2
682     		    || stack[1] == (unsigned) &do_signal_ret) {
683     			if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
684     				break;
685     			printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
686     			       regs.nip);
687     			sp = regs.gpr[1];
688     			if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
689     				break;
690     		}
691     	}
692     	printf("\n");
693     }
694     
695     int
696     getsp()
697     {
698         int x;
699     
700         asm("mr %0,1" : "=r" (x) :);
701         return x;
702     }
703     
704     void
705     excprint(struct pt_regs *fp)
706     {
707     #ifdef CONFIG_SMP
708     	printf("cpu %d: ", smp_processor_id());
709     #endif /* CONFIG_SMP */
710     	printf("vector: %x at pc = %x",
711     	       fp->trap, fp->nip);
712     	printf(", lr = %x, msr = %x, sp = %x [%x]\n",
713     	       fp->link, fp->msr, fp->gpr[1], fp);
714     	if (fp->trap == 0x300 || fp->trap == 0x600)
715     		printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
716     	if (current)
717     		printf("current = %x, pid = %d, comm = %s\n",
718     		       current, current->pid, current->comm);
719     }
720     
721     void
722     prregs(struct pt_regs *fp)
723     {
724     	int n;
725     	unsigned base;
726     
727     	if (scanhex(&base))
728     		fp = (struct pt_regs *) base;
729     	for (n = 0; n < 32; ++n)
730     		printf("R%.2d = %.8x%s", n, fp->gpr[n],
731     		       (n & 3) == 3? "\n": "   ");
732     	printf("pc  = %.8x   msr = %.8x   lr  = %.8x   cr  = %.8x\n",
733     	       fp->nip, fp->msr, fp->link, fp->ccr);
734     	printf("ctr = %.8x   xer = %.8x   trap = %4x\n",
735     	       fp->ctr, fp->xer, fp->trap);
736     }
737     
738     void
739     cacheflush(void)
740     {
741     	int cmd;
742     	unsigned nflush;
743     
744     	cmd = inchar();
745     	if (cmd != 'i')
746     		termch = cmd;
747     	scanhex(&adrs);
748     	if (termch != '\n')
749     		termch = 0;
750     	nflush = 1;
751     	scanhex(&nflush);
752     	nflush = (nflush + 31) / 32;
753     	if (cmd != 'i') {
754     		for (; nflush > 0; --nflush, adrs += 0x20)
755     			cflush((void *) adrs);
756     	} else {
757     		for (; nflush > 0; --nflush, adrs += 0x20)
758     			cinval((void *) adrs);
759     	}
760     }
761     
762     unsigned int
763     read_spr(int n)
764     {
765         unsigned int instrs[2];
766         int (*code)(void);
767     
768         instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
769         instrs[1] = 0x4e800020;
770         store_inst(instrs);
771         store_inst(instrs+1);
772         code = (int (*)(void)) instrs;
773         return code();
774     }
775     
776     void
777     write_spr(int n, unsigned int val)
778     {
779         unsigned int instrs[2];
780         int (*code)(unsigned int);
781     
782         instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
783         instrs[1] = 0x4e800020;
784         store_inst(instrs);
785         store_inst(instrs+1);
786         code = (int (*)(unsigned int)) instrs;
787         code(val);
788     }
789     
790     static unsigned int regno;
791     extern char exc_prolog;
792     extern char dec_exc;
793     
794     void
795     print_sysmap(void)
796     {
797     	extern char *sysmap;
798     	if ( sysmap )
799     		printf("System.map: \n%s", sysmap);
800     	else
801     		printf("No System.map\n");
802     }
803     
804     void
805     super_regs()
806     {
807     	int i, cmd;
808     	unsigned val;
809     
810     	cmd = skipbl();
811     	if (cmd == '\n') {
812     		printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
813     		printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
814     		       get_sprg2(), get_sprg3());
815     		printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
816     		printf("sr0-15 =");
817     		for (i = 0; i < 16; ++i)
818     			printf(" %x", get_sr(i));
819     		printf("\n");
820     		asm("mr %0,1" : "=r" (i) :);
821     		printf("sp = %x ", i);
822     		asm("mr %0,2" : "=r" (i) :);
823     		printf("toc = %x\n", i);
824     		return;
825     	}
826     
827     	scanhex(&regno);
828     	switch (cmd) {
829     	case 'w':
830     		val = read_spr(regno);
831     		scanhex(&val);
832     		write_spr(regno, val);
833     		/* fall through */
834     	case 'r':
835     		printf("spr %x = %x\n", regno, read_spr(regno));
836     		break;
837     	case 's':
838     		val = get_sr(regno);
839     		scanhex(&val);
840     		set_sr(regno, val);
841     		break;
842     	case 'm':
843     		val = get_msr();
844     		scanhex(&val);
845     		set_msr(val);
846     		break;
847     	}
848     	scannl();
849     }
850     
851     #if 0
852     static void
853     openforth()
854     {
855         int c;
856         char *p;
857         char cmd[1024];
858         int args[5];
859         extern int (*prom_entry)(int *);
860     
861         p = cmd;
862         c = skipbl();
863         while (c != '\n') {
864     	*p++ = c;
865     	c = inchar();
866         }
867         *p = 0;
868         args[0] = (int) "interpret";
869         args[1] = 1;
870         args[2] = 1;
871         args[3] = (int) cmd;
872         (*prom_entry)(args);
873         printf("\n");
874         if (args[4] != 0)
875     	printf("error %x\n", args[4]);
876     }
877     #endif
878     
879     #ifndef CONFIG_PPC64BRIDGE
880     static void
881     dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
882     {
883     	extern void *Hash;
884     	extern unsigned long Hash_size;
885     	unsigned *htab = Hash;
886     	unsigned hsize = Hash_size;
887     	unsigned v, hmask, va, last_va;
888     	int found, last_found, i;
889     	unsigned *hg, w1, last_w2, last_va0;
890     
891     	last_found = 0;
892     	hmask = hsize / 64 - 1;
893     	va = start;
894     	start = (start >> 12) & 0xffff;
895     	end = (end >> 12) & 0xffff;
896     	for (v = start; v < end; ++v) {
897     		found = 0;
898     		hg = htab + (((v ^ seg) & hmask) * 16);
899     		w1 = 0x80000000 | (seg << 7) | (v >> 10);
900     		for (i = 0; i < 8; ++i, hg += 2) {
901     			if (*hg == w1) {
902     				found = 1;
903     				break;
904     			}
905     		}
906     		if (!found) {
907     			w1 ^= 0x40;
908     			hg = htab + ((~(v ^ seg) & hmask) * 16);
909     			for (i = 0; i < 8; ++i, hg += 2) {
910     				if (*hg == w1) {
911     					found = 1;
912     					break;
913     				}
914     			}
915     		}
916     		if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
917     			if (last_found) {
918     				if (last_va != last_va0)
919     					printf(" ... %x", last_va);
920     				printf("\n");
921     			}
922     			if (found) {
923     				printf("%x to %x", va, hg[1]);
924     				last_va0 = va;
925     			}
926     			last_found = found;
927     		}
928     		if (found) {
929     			last_w2 = hg[1] & ~0x180;
930     			last_va = va;
931     		}
932     		va += 4096;
933     	}
934     	if (last_found)
935     		printf(" ... %x\n", last_va);
936     }
937     
938     #else /* CONFIG_PPC64BRIDGE */
939     static void
940     dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
941     {
942     	extern void *Hash;
943     	extern unsigned long Hash_size;
944     	unsigned *htab = Hash;
945     	unsigned hsize = Hash_size;
946     	unsigned v, hmask, va, last_va;
947     	int found, last_found, i;
948     	unsigned *hg, w1, last_w2, last_va0;
949     
950     	last_found = 0;
951     	hmask = hsize / 128 - 1;
952     	va = start;
953     	start = (start >> 12) & 0xffff;
954     	end = (end >> 12) & 0xffff;
955     	for (v = start; v < end; ++v) {
956     		found = 0;
957     		hg = htab + (((v ^ seg) & hmask) * 32);
958     		w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
959     		for (i = 0; i < 8; ++i, hg += 4) {
960     			if (hg[1] == w1) {
961     				found = 1;
962     				break;
963     			}
964     		}
965     		if (!found) {
966     			w1 ^= 2;
967     			hg = htab + ((~(v ^ seg) & hmask) * 32);
968     			for (i = 0; i < 8; ++i, hg += 4) {
969     				if (hg[1] == w1) {
970     					found = 1;
971     					break;
972     				}
973     			}
974     		}
975     		if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
976     			if (last_found) {
977     				if (last_va != last_va0)
978     					printf(" ... %x", last_va);
979     				printf("\n");
980     			}
981     			if (found) {
982     				printf("%x to %x", va, hg[3]);
983     				last_va0 = va;
984     			}
985     			last_found = found;
986     		}
987     		if (found) {
988     			last_w2 = hg[3] & ~0x180;
989     			last_va = va;
990     		}
991     		va += 4096;
992     	}
993     	if (last_found)
994     		printf(" ... %x\n", last_va);
995     }
996     #endif /* CONFIG_PPC64BRIDGE */
997     
998     static unsigned hash_ctx;
999     static unsigned hash_start;
1000     static unsigned hash_end;
1001     
1002     static void
1003     dump_hash_table()
1004     {
1005     	int seg;
1006     	unsigned seg_start, seg_end;
1007     
1008     	hash_ctx = 0;
1009     	hash_start = 0;
1010     	hash_end = 0xfffff000;
1011     	scanhex(&hash_ctx);
1012     	scanhex(&hash_start);
1013     	scanhex(&hash_end);
1014     	printf("Mappings for context %x\n", hash_ctx);
1015     	seg_start = hash_start;
1016     	for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1017     		seg_end = (seg << 28) | 0x0ffff000;
1018     		if (seg_end > hash_end)
1019     			seg_end = hash_end;
1020     		dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1021     				    seg_start, seg_end);
1022     		seg_start = seg_end + 0x1000;
1023     	}
1024     }
1025     
1026     /*
1027      * Stuff for reading and writing memory safely
1028      */
1029     extern inline void sync(void)
1030     {
1031     	asm volatile("sync; isync");
1032     }
1033     
1034     extern inline void __delay(unsigned int loops)
1035     {
1036     	if (loops != 0)
1037     		__asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
1038     				     "r" (loops) : "ctr");
1039     }
1040     
1041     int
1042     mread(unsigned adrs, void *buf, int size)
1043     {
1044     	volatile int n;
1045     	char *p, *q;
1046     
1047     	n = 0;
1048     	if( setjmp(bus_error_jmp) == 0 ){
1049     		debugger_fault_handler = handle_fault;
1050     		sync();
1051     		p = (char *) adrs;
1052     		q = (char *) buf;
1053     		switch (size) {
1054     		case 2: *(short *)q = *(short *)p;	break;
1055     		case 4: *(int *)q = *(int *)p;		break;
1056     		default:
1057     			for( ; n < size; ++n ) {
1058     				*q++ = *p++;
1059     				sync();
1060     			}
1061     		}
1062     		sync();
1063     		/* wait a little while to see if we get a machine check */
1064     		__delay(200);
1065     		n = size;
1066     	}
1067     	debugger_fault_handler = 0;
1068     	return n;
1069     }
1070     
1071     int
1072     mwrite(unsigned adrs, void *buf, int size)
1073     {
1074     	volatile int n;
1075     	char *p, *q;
1076     
1077     	n = 0;
1078     	if( setjmp(bus_error_jmp) == 0 ){
1079     		debugger_fault_handler = handle_fault;
1080     		sync();
1081     		p = (char *) adrs;
1082     		q = (char *) buf;
1083     		switch (size) {
1084     		case 2: *(short *)p = *(short *)q;	break;
1085     		case 4: *(int *)p = *(int *)q;		break;
1086     		default:
1087     			for( ; n < size; ++n ) {
1088     				*p++ = *q++;
1089     				sync();
1090     			}
1091     		}
1092     		sync();
1093     		n = size;
1094     	} else {
1095     		printf("*** Error writing address %x\n", adrs + n);
1096     	}
1097     	debugger_fault_handler = 0;
1098     	return n;
1099     }
1100     
1101     static int fault_type;
1102     static char *fault_chars[] = { "--", "**", "##" };
1103     
1104     static void
1105     handle_fault(struct pt_regs *regs)
1106     {
1107     	fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
1108     	longjmp(bus_error_jmp, 1);
1109     }
1110     
1111     #define SWAP(a, b, t)	((t) = (a), (a) = (b), (b) = (t))
1112     
1113     void
1114     byterev(unsigned char *val, int size)
1115     {
1116     	int t;
1117     	
1118     	switch (size) {
1119     	case 2:
1120     		SWAP(val[0], val[1], t);
1121     		break;
1122     	case 4:
1123     		SWAP(val[0], val[3], t);
1124     		SWAP(val[1], val[2], t);
1125     		break;
1126     	}
1127     }
1128     
1129     static int brev;
1130     static int mnoread;
1131     
1132     void
1133     memex()
1134     {
1135         int cmd, inc, i, nslash;
1136         unsigned n;
1137         unsigned char val[4];
1138     
1139         last_cmd = "m\n";
1140         scanhex(&adrs);
1141         while ((cmd = skipbl()) != '\n') {
1142     	switch( cmd ){
1143     	case 'b':	size = 1;	break;
1144     	case 'w':	size = 2;	break;
1145     	case 'l':	size = 4;	break;
1146     	case 'r': 	brev = !brev;	break;
1147     	case 'n':	mnoread = 1;	break;
1148     	case '.':	mnoread = 0;	break;
1149     	}
1150         }
1151         if( size <= 0 )
1152     	size = 1;
1153         else if( size > 4 )
1154     	size = 4;
1155         for(;;){
1156     	if (!mnoread)
1157     	    n = mread(adrs, val, size);
1158     	printf("%.8x%c", adrs, brev? 'r': ' ');
1159     	if (!mnoread) {
1160     	    if (brev)
1161     		byterev(val, size);
1162     	    putchar(' ');
1163     	    for (i = 0; i < n; ++i)
1164     		printf("%.2x", val[i]);
1165     	    for (; i < size; ++i)
1166     		printf("%s", fault_chars[fault_type]);
1167     	}
1168     	putchar(' ');
1169     	inc = size;
1170     	nslash = 0;
1171     	for(;;){
1172     	    if( scanhex(&n) ){
1173     		for (i = 0; i < size; ++i)
1174     		    val[i] = n >> (i * 8);
1175     		if (!brev)
1176     		    byterev(val, size);
1177     		mwrite(adrs, val, size);
1178     		inc = size;
1179     	    }
1180     	    cmd = skipbl();
1181     	    if (cmd == '\n')
1182     		break;
1183     	    inc = 0;
1184     	    switch (cmd) {
1185     	    case '\'':
1186     		for(;;){
1187     		    n = inchar();
1188     		    if( n == '\\' )
1189     			n = bsesc();
1190     		    else if( n == '\'' )
1191     			break;
1192     		    for (i = 0; i < size; ++i)
1193     			val[i] = n >> (i * 8);
1194     		    if (!brev)
1195     			byterev(val, size);
1196     		    mwrite(adrs, val, size);
1197     		    adrs += size;
1198     		}
1199     		adrs -= size;
1200     		inc = size;
1201     		break;
1202     	    case ',':
1203     		adrs += size;
1204     		break;
1205     	    case '.':
1206     		mnoread = 0;
1207     		break;
1208     	    case ';':
1209     		break;
1210     	    case 'x':
1211     	    case EOF:
1212     		scannl();
1213     		return;
1214     	    case 'b':
1215     	    case 'v':
1216     		size = 1;
1217     		break;
1218     	    case 'w':
1219     		size = 2;
1220     		break;
1221     	    case 'l':
1222     		size = 4;
1223     		break;
1224     	    case '^':
1225     		adrs -= size;
1226     		break;
1227     		break;
1228     	    case '/':
1229     		if (nslash > 0)
1230     		    adrs -= 1 << nslash;
1231     		else
1232     		    nslash = 0;
1233     		nslash += 4;
1234     		adrs += 1 << nslash;
1235     		break;
1236     	    case '\\':
1237     		if (nslash < 0)
1238     		    adrs += 1 << -nslash;
1239     		else
1240     		    nslash = 0;
1241     		nslash -= 4;
1242     		adrs -= 1 << -nslash;
1243     		break;
1244     	    case 'm':
1245     		scanhex(&adrs);
1246     		break;
1247     	    case 'n':
1248     		mnoread = 1;
1249     		break;
1250     	    case 'r':
1251     		brev = !brev;
1252     		break;
1253     	    case '<':
1254     		n = size;
1255     		scanhex(&n);
1256     		adrs -= n;
1257     		break;
1258     	    case '>':
1259     		n = size;
1260     		scanhex(&n);
1261     		adrs += n;
1262     		break;
1263     	    }
1264     	}
1265     	adrs += inc;
1266         }
1267     }
1268     
1269     int
1270     bsesc()
1271     {
1272     	int c;
1273     
1274     	c = inchar();
1275     	switch( c ){
1276     	case 'n':	c = '\n';	break;
1277     	case 'r':	c = '\r';	break;
1278     	case 'b':	c = '\b';	break;
1279     	case 't':	c = '\t';	break;
1280     	}
1281     	return c;
1282     }
1283     
1284     void
1285     dump()
1286     {
1287     	int c;
1288     
1289     	c = inchar();
1290     	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1291     		termch = c;
1292     	scanhex(&adrs);
1293     	if( termch != '\n')
1294     		termch = 0;
1295     	if( c == 'i' ){
1296     		scanhex(&nidump);
1297     		if( nidump == 0 )
1298     			nidump = 16;
1299     		adrs += ppc_inst_dump(adrs, nidump);
1300     		last_cmd = "di\n";
1301     	} else {
1302     		scanhex(&ndump);
1303     		if( ndump == 0 )
1304     			ndump = 64;
1305     		prdump(adrs, ndump);
1306     		adrs += ndump;
1307     		last_cmd = "d\n";
1308     	}
1309     }
1310     
1311     void
1312     prdump(unsigned adrs, int ndump)
1313     {
1314     	register int n, m, c, r, nr;
1315     	unsigned char temp[16];
1316     
1317     	for( n = ndump; n > 0; ){
1318     		printf("%.8x", adrs);
1319     		putchar(' ');
1320     		r = n < 16? n: 16;
1321     		nr = mread(adrs, temp, r);
1322     		adrs += nr;
1323     		for( m = 0; m < r; ++m ){
1324     			putchar((m & 3) == 0 && m > 0? '.': ' ');
1325     			if( m < nr )
1326     				printf("%.2x", temp[m]);
1327     			else
1328     				printf("%s", fault_chars[fault_type]);
1329     		}
1330     		for(; m < 16; ++m )
1331     			printf("   ");
1332     		printf("  |");
1333     		for( m = 0; m < r; ++m ){
1334     			if( m < nr ){
1335     				c = temp[m];
1336     				putchar(' ' <= c && c <= '~'? c: '.');
1337     			} else
1338     				putchar(' ');
1339     		}
1340     		n -= r;
1341     		for(; m < 16; ++m )
1342     			putchar(' ');
1343     		printf("|\n");
1344     		if( nr < r )
1345     			break;
1346     	}
1347     }
1348     
1349     int
1350     ppc_inst_dump(unsigned adr, int count)
1351     {
1352     	int nr, dotted;
1353     	unsigned first_adr;
1354     	unsigned long inst, last_inst;
1355     	unsigned char val[4];
1356     
1357     	dotted = 0;
1358     	for (first_adr = adr; count > 0; --count, adr += 4){
1359     		nr = mread(adr, val, 4);
1360     		if( nr == 0 ){
1361     			const char *x = fault_chars[fault_type];
1362     			printf("%.8x  %s%s%s%s\n", adr, x, x, x, x);
1363     			break;
1364     		}
1365     		inst = GETWORD(val);
1366     		if (adr > first_adr && inst == last_inst) {
1367     			if (!dotted) {
1368     				printf(" ...\n");
1369     				dotted = 1;
1370     			}
1371     			continue;
1372     		}
1373     		dotted = 0;
1374     		last_inst = inst;
1375     		printf("%.8x  ", adr);
1376     		printf("%.8x\t", inst);
1377     		print_insn_big_powerpc(stdout, inst, adr);	/* always returns 4 */
1378     		printf("\n");
1379     	}
1380     	return adr - first_adr;
1381     }
1382     
1383     void
1384     print_address(addr)
1385     unsigned addr;
1386     {
1387     	printf("0x%x", addr);
1388     }
1389     
1390     /*
1391      * Memory operations - move, set, print differences
1392      */
1393     static unsigned mdest;		/* destination address */
1394     static unsigned msrc;		/* source address */
1395     static unsigned mval;		/* byte value to set memory to */
1396     static unsigned mcount;		/* # bytes to affect */
1397     static unsigned mdiffs;		/* max # differences to print */
1398     
1399     void
1400     memops(int cmd)
1401     {
1402     	scanhex(&mdest);
1403     	if( termch != '\n' )
1404     		termch = 0;
1405     	scanhex(cmd == 's'? &mval: &msrc);
1406     	if( termch != '\n' )
1407     		termch = 0;
1408     	scanhex(&mcount);
1409     	switch( cmd ){
1410     	case 'm':
1411     		memmove((void *)mdest, (void *)msrc, mcount);
1412     		break;
1413     	case 's':
1414     		memset((void *)mdest, mval, mcount);
1415     		break;
1416     	case 'd':
1417     		if( termch != '\n' )
1418     			termch = 0;
1419     		scanhex(&mdiffs);
1420     		memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1421     		break;
1422     	}
1423     }
1424     
1425     void
1426     memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1427     {
1428     	unsigned n, prt;
1429     
1430     	prt = 0;
1431     	for( n = nb; n > 0; --n )
1432     		if( *p1++ != *p2++ )
1433     			if( ++prt <= maxpr )
1434     				printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1435     					p1[-1], (unsigned)p2 - 1, p2[-1]);
1436     	if( prt > maxpr )
1437     		printf("Total of %d differences\n", prt);
1438     }
1439     
1440     static unsigned mend;
1441     static unsigned mask;
1442     
1443     void
1444     memlocate()
1445     {
1446     	unsigned a, n;
1447     	unsigned char val[4];
1448     
1449     	last_cmd = "ml";
1450     	scanhex(&mdest);
1451     	if (termch != '\n') {
1452     		termch = 0;
1453     		scanhex(&mend);
1454     		if (termch != '\n') {
1455     			termch = 0;
1456     			scanhex(&mval);
1457     			mask = ~0;
1458     			if (termch != '\n') termch = 0;
1459     			scanhex(&mask);
1460     		}
1461     	}
1462     	n = 0;
1463     	for (a = mdest; a < mend; a += 4) {
1464     		if (mread(a, val, 4) == 4
1465     			&& ((GETWORD(val) ^ mval) & mask) == 0) {
1466     			printf("%.8x:  %.8x\n", a, GETWORD(val));
1467     			if (++n >= 10)
1468     				break;
1469     		}
1470     	}
1471     }
1472     
1473     static unsigned mskip = 0x1000;
1474     static unsigned mlim = 0xffffffff;
1475     
1476     void
1477     memzcan()
1478     {
1479     	unsigned char v;
1480     	unsigned a;
1481     	int ok, ook;
1482     
1483     	scanhex(&mdest);
1484     	if (termch != '\n') termch = 0;
1485     	scanhex(&mskip);
1486     	if (termch != '\n') termch = 0;
1487     	scanhex(&mlim);
1488     	ook = 0;
1489     	for (a = mdest; a < mlim; a += mskip) {
1490     		ok = mread(a, &v, 1);
1491     		if (ok && !ook) {
1492     			printf("%.8x .. ", a);
1493     			fflush(stdout);
1494     		} else if (!ok && ook)
1495     			printf("%.8x\n", a - mskip);
1496     		ook = ok;
1497     		if (a + mskip < a)
1498     			break;
1499     	}
1500     	if (ook)
1501     		printf("%.8x\n", a - mskip);
1502     }
1503     
1504     /* Input scanning routines */
1505     int
1506     skipbl()
1507     {
1508     	int c;
1509     
1510     	if( termch != 0 ){
1511     		c = termch;
1512     		termch = 0;
1513     	} else
1514     		c = inchar();
1515     	while( c == ' ' || c == '\t' )
1516     		c = inchar();
1517     	return c;
1518     }
1519     
1520     #define N_PTREGS	44
1521     static char *regnames[N_PTREGS] = {
1522     	"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1523     	"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1524     	"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1525     	"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1526     	"pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1527     	"trap", "dar", "dsisr", "res"
1528     };
1529     
1530     int
1531     scanhex(vp)
1532     unsigned *vp;
1533     {
1534     	int c, d;
1535     	unsigned v;
1536     
1537     	c = skipbl();
1538     	if (c == '%') {
1539     		/* parse register name */
1540     		char regname[8];
1541     		int i;
1542     
1543     		for (i = 0; i < sizeof(regname) - 1; ++i) {
1544     			c = inchar();
1545     			if (!isalnum(c)) {
1546     				termch = c;
1547     				break;
1548     			}
1549     			regname[i] = c;
1550     		}
1551     		regname[i] = 0;
1552     		for (i = 0; i < N_PTREGS; ++i) {
1553     			if (strcmp(regnames[i], regname) == 0) {
1554     				unsigned *rp = (unsigned *)
1555     					xmon_regs[smp_processor_id()];
1556     				if (rp == NULL) {
1557     					printf("regs not available\n");
1558     					return 0;
1559     				}
1560     				*vp = rp[i];
1561     				return 1;
1562     			}
1563     		}
1564     		printf("invalid register name '%%%s'\n", regname);
1565     		return 0;
1566     	}
1567     
1568     	d = hexdigit(c);
1569     	if( d == EOF ){
1570     		termch = c;
1571     		return 0;
1572     	}
1573     	v = 0;
1574     	do {
1575     		v = (v << 4) + d;
1576     		c = inchar();
1577     		d = hexdigit(c);
1578     	} while( d != EOF );
1579     	termch = c;
1580     	*vp = v;
1581     	return 1;
1582     }
1583     
1584     void
1585     scannl()
1586     {
1587     	int c;
1588     
1589     	c = termch;
1590     	termch = 0;
1591     	while( c != '\n' )
1592     		c = inchar();
1593     }
1594     
1595     int
1596     hexdigit(c)
1597     {
1598     	if( '0' <= c && c <= '9' )
1599     		return c - '0';
1600     	if( 'A' <= c && c <= 'F' )
1601     		return c - ('A' - 10);
1602     	if( 'a' <= c && c <= 'f' )
1603     		return c - ('a' - 10);
1604     	return EOF;
1605     }
1606     
1607     void
1608     getstring(char *s, int size)
1609     {
1610     	int c;
1611     
1612     	c = skipbl();
1613     	do {
1614     		if( size > 1 ){
1615     			*s++ = c;
1616     			--size;
1617     		}
1618     		c = inchar();
1619     	} while( c != ' ' && c != '\t' && c != '\n' );
1620     	termch = c;
1621     	*s = 0;
1622     }
1623     
1624     static char line[256];
1625     static char *lineptr;
1626     
1627     void
1628     flush_input()
1629     {
1630     	lineptr = NULL;
1631     }
1632     
1633     int
1634     inchar()
1635     {
1636     	if (lineptr == NULL || *lineptr == 0) {
1637     		if (fgets(line, sizeof(line), stdin) == NULL) {
1638     			lineptr = NULL;
1639     			return EOF;
1640     		}
1641     		lineptr = line;
1642     	}
1643     	return *lineptr++;
1644     }
1645     
1646     void
1647     take_input(str)
1648     char *str;
1649     {
1650     	lineptr = str;
1651     }
1652     
1653     #if 0 /* Makes compile with -Wall */
1654     static char *pretty_print_addr(unsigned long addr)
1655     {
1656     	printf("%08x", addr);
1657     	if ( lookup_name(addr) )
1658     		printf(" %s", lookup_name(addr) );
1659     	return NULL;
1660     }
1661     #endif
1662     
1663     #if 0 /* Makes compile with -Wall */
1664     static char *lookup_name(unsigned long addr)
1665     {
1666     	extern char *sysmap;
1667     	extern unsigned long sysmap_size;
1668     	char *c = sysmap;
1669     	unsigned long cmp;
1670     	if ( !sysmap || !sysmap_size )
1671     		return NULL;
1672     return NULL;	
1673     #if 0
1674     	cmp = simple_strtoul(c, &c, 8);
1675     	/* XXX crap, we don't want the whole of the rest of the map - paulus */
1676     	strcpy( last, strsep( &c, "\n"));
1677     	while ( c < (sysmap+sysmap_size) )
1678     	{
1679     		cmp = simple_strtoul(c, &c, 8);
1680     		if ( cmp < addr )
1681     			break;
1682     		strcpy( last, strsep( &c, "\n"));
1683     	}
1684     	return last;
1685     #endif	
1686     }
1687     #endif
1688