1/*
2 * Routines providing a simple monitor for use on the PowerMac.
3 *
4 * Copyright (C) 1996 Paul Mackerras.
5 *
6 *      This program is free software; you can redistribute it and/or
7 *      modify it under the terms of the GNU General Public License
8 *      as published by the Free Software Foundation; either version
9 *      2 of the License, or (at your option) any later version.
10 */
11#include <linux/config.h>
12#include <linux/errno.h>
13#include <linux/sched.h>
14#include <linux/smp.h>
15#include <linux/mm.h>
16#include <linux/reboot.h>
17#include <asm/ptrace.h>
18#include <asm/string.h>
19#include <asm/prom.h>
20#include <asm/machdep.h>
21#include <asm/processor.h>
22#include <asm/pgtable.h>
23#include <asm/mmu.h>
24#include <asm/mmu_context.h>
25#include <asm/naca.h>
26#include <asm/paca.h>
27#include <asm/ppcdebug.h>
28#include "nonstdio.h"
29#include "privinst.h"
30
31#define scanhex	xmon_scanhex
32#define skipbl	xmon_skipbl
33
34#ifdef CONFIG_SMP
35static unsigned long cpus_in_xmon = 0;
36static unsigned long got_xmon = 0;
37static volatile int take_xmon = -1;
38#endif /* CONFIG_SMP */
39
40static unsigned long adrs;
41static int size = 1;
42static unsigned long ndump = 64;
43static unsigned long nidump = 16;
44static unsigned long ncsum = 4096;
45static int termch;
46
47static u_int bus_error_jmp[100];
48#define setjmp xmon_setjmp
49#define longjmp xmon_longjmp
50
51#define memlist_entry list_entry
52#define memlist_next(x) ((x)->next)
53#define memlist_prev(x) ((x)->prev)
54
55
56/* Max number of stack frames we are willing to produce on a backtrace. */
57#define MAXFRAMECOUNT 50
58
59/* Breakpoint stuff */
60struct bpt {
61	unsigned long address;
62	unsigned instr;
63	unsigned long count;
64	unsigned char enabled;
65	char funcname[64];	/* function name for humans */
66};
67
68#define NBPTS	16
69static struct bpt bpts[NBPTS];
70static struct bpt dabr;
71static struct bpt iabr;
72static unsigned bpinstr = 0x7fe00008;	/* trap */
73
74/* Prototypes */
75extern void (*debugger_fault_handler)(struct pt_regs *);
76static int cmds(struct pt_regs *);
77static int mread(unsigned long, void *, int);
78static int mwrite(unsigned long, void *, int);
79static void handle_fault(struct pt_regs *);
80static void byterev(unsigned char *, int);
81static void memex(void);
82static int bsesc(void);
83static void dump(void);
84static void prdump(unsigned long, long);
85#ifdef __MWERKS__
86static void prndump(unsigned, int);
87static int nvreadb(unsigned);
88#endif
89static int ppc_inst_dump(unsigned long, long);
90void print_address(unsigned long);
91static int getsp(void);
92static void dump_hash_table(void);
93static void backtrace(struct pt_regs *);
94static void excprint(struct pt_regs *);
95static void prregs(struct pt_regs *);
96static void memops(int);
97static void memlocate(void);
98static void memzcan(void);
99static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
100int skipbl(void);
101int scanhex(unsigned long *valp);
102static void scannl(void);
103static int hexdigit(int);
104void getstring(char *, int);
105static void flush_input(void);
106static int inchar(void);
107static void take_input(char *);
108/* static void openforth(void); */
109static unsigned long read_spr(int);
110static void write_spr(int, unsigned long);
111static void super_regs(void);
112static void print_sysmap(void);
113static void remove_bpts(void);
114static void insert_bpts(void);
115static struct bpt *at_breakpoint(unsigned long pc);
116static void bpt_cmds(void);
117static void cacheflush(void);
118#ifdef CONFIG_SMP
119static void cpu_cmd(void);
120#endif /* CONFIG_SMP */
121static void csum(void);
122static void mem_translate(void);
123static void mem_check(void);
124static void mem_find_real(void);
125static void mem_find_vsid(void);
126static void mem_check_pagetable_vsids (void);
127
128static void mem_map_check_slab(void);
129static void mem_map_lock_pages(void);
130static void mem_check_dup_rpn (void);
131static void debug_trace(void);
132
133extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long);
134extern void printf(const char *fmt, ...);
135extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
136extern int xmon_putc(int c, void *f);
137extern int putchar(int ch);
138extern int xmon_read_poll(void);
139extern int setjmp(u_int *);
140extern void longjmp(u_int *, int);
141extern unsigned long _ASR;
142
143pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va);	/* from htab.c */
144
145#define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
146
147static char *help_string = "\
148Commands:\n\
149  b	show breakpoints\n\
150  bd	set data breakpoint\n\
151  bi	set instruction breakpoint\n\
152  bc	clear breakpoint\n\
153  d	dump bytes\n\
154  di	dump instructions\n\
155  df	dump float values\n\
156  dd	dump double values\n\
157  e	print exception information\n\
158  f	flush cache\n\
159  h	dump hash table\n\
160  m	examine/change memory\n\
161  mm	move a block of memory\n\
162  ms	set a block of memory\n\
163  md	compare two blocks of memory\n\
164  ml	locate a block of memory\n\
165  mz	zero a block of memory\n\
166  mx	translation information for an effective address\n\
167  mi	show information about memory allocation\n\
168  M	print System.map\n\
169  p 	show the task list\n\
170  r	print registers\n\
171  s	single step\n\
172  S	print special registers\n\
173  t	print backtrace\n\
174  T	Enable/Disable PPCDBG flags\n\
175  x	exit monitor\n\
176  z	reboot\n\
177  Z	halt\n\
178";
179
180static int xmon_trace[NR_CPUS];
181#define SSTEP	1		/* stepping because of 's' command */
182#define BRSTEP	2		/* stepping over breakpoint */
183
184/*
185 * Stuff for reading and writing memory safely
186 */
187extern inline void sync(void)
188{
189	asm volatile("sync; isync");
190}
191
192/* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs).
193 A PPC stack frame looks like this:
194
195 High Address
196    Back Chain
197    FP reg save area
198    GP reg save area
199    Local var space
200    Parameter save area		(SP+48)
201    TOC save area		(SP+40)
202    link editor doubleword	(SP+32)
203    compiler doubleword		(SP+24)
204    LR save			(SP+16)
205    CR save			(SP+8)
206    Back Chain			(SP+0)
207
208 Note that the LR (ret addr) may not be saved in the current frame if
209 no functions have been called from the current function.
210 */
211
212/*
213 A traceback table typically follows each function.
214 The find_tb_table() func will fill in this struct.  Note that the struct
215 is not an exact match with the encoded table defined by the ABI.  It is
216 defined here more for programming convenience.
217 */
218struct tbtable {
219	unsigned long	flags;		/* flags: */
220#define TBTAB_FLAGSGLOBALLINK	(1L<<47)
221#define TBTAB_FLAGSISEPROL	(1L<<46)
222#define TBTAB_FLAGSHASTBOFF	(1L<<45)
223#define TBTAB_FLAGSINTPROC	(1L<<44)
224#define TBTAB_FLAGSHASCTL	(1L<<43)
225#define TBTAB_FLAGSTOCLESS	(1L<<42)
226#define TBTAB_FLAGSFPPRESENT	(1L<<41)
227#define TBTAB_FLAGSNAMEPRESENT	(1L<<38)
228#define TBTAB_FLAGSUSESALLOCA	(1L<<37)
229#define TBTAB_FLAGSSAVESCR	(1L<<33)
230#define TBTAB_FLAGSSAVESLR	(1L<<32)
231#define TBTAB_FLAGSSTORESBC	(1L<<31)
232#define TBTAB_FLAGSFIXUP	(1L<<30)
233#define TBTAB_FLAGSPARMSONSTK	(1L<<0)
234	unsigned char	fp_saved;	/* num fp regs saved f(32-n)..f31 */
235	unsigned char	gpr_saved;	/* num gpr's saved */
236	unsigned char	fixedparms;	/* num fixed point parms */
237	unsigned char	floatparms;	/* num float parms */
238	unsigned char	parminfo[32];	/* types of args.  null terminated */
239#define TBTAB_PARMFIXED 1
240#define TBTAB_PARMSFLOAT 2
241#define TBTAB_PARMDFLOAT 3
242	unsigned int	tb_offset;	/* offset from start of func */
243	unsigned long	funcstart;	/* addr of start of function */
244	char		name[64];	/* name of function (null terminated)*/
245};
246static int find_tb_table(unsigned long codeaddr, struct tbtable *tab);
247
248void
249xmon(struct pt_regs *excp)
250{
251	struct pt_regs regs;
252	int cmd;
253	unsigned long msr;
254
255	if (excp == NULL) {
256		/* Ok, grab regs as they are now.
257		 This won't do a particularily good job because the
258		 prologue has already been executed.
259		 ToDo: We could reach back into the callers save
260		 area to do a better job of representing the
261		 caller's state.
262		 */
263		asm volatile ("std	0,0(%0)\n\
264			std	1,8(%0)\n\
265			std	2,16(%0)\n\
266			std	3,24(%0)\n\
267			std	4,32(%0)\n\
268			std	5,40(%0)\n\
269			std	6,48(%0)\n\
270			std	7,56(%0)\n\
271			std	8,64(%0)\n\
272			std	9,72(%0)\n\
273			std	10,80(%0)\n\
274			std	11,88(%0)\n\
275			std	12,96(%0)\n\
276			std	13,104(%0)\n\
277			std	14,112(%0)\n\
278			std	15,120(%0)\n\
279			std	16,128(%0)\n\
280			std	17,136(%0)\n\
281			std	18,144(%0)\n\
282			std	19,152(%0)\n\
283			std	20,160(%0)\n\
284			std	21,168(%0)\n\
285			std	22,176(%0)\n\
286			std	23,184(%0)\n\
287			std	24,192(%0)\n\
288			std	25,200(%0)\n\
289			std	26,208(%0)\n\
290			std	27,216(%0)\n\
291			std	28,224(%0)\n\
292			std	29,232(%0)\n\
293			std	30,240(%0)\n\
294			std	31,248(%0)" : : "b" (&regs));
295		printf("xmon called\n");
296		/* Fetch the link reg for this stack frame.
297		 NOTE: the prev printf fills in the lr. */
298		regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
299		regs.msr = get_msr();
300		regs.ctr = get_ctr();
301		regs.xer = get_xer();
302		regs.ccr = get_cr();
303		regs.trap = 0;
304		excp = &regs;
305	}
306
307	msr = get_msr();
308	set_msrd(msr & ~MSR_EE);	/* disable interrupts */
309	excprint(excp);
310#ifdef CONFIG_SMP
311	if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
312		for (;;)
313			;
314	while (test_and_set_bit(0, &got_xmon)) {
315		if (take_xmon == smp_processor_id()) {
316			take_xmon = -1;
317			break;
318		}
319	}
320#endif /* CONFIG_SMP */
321	remove_bpts();
322	cmd = cmds(excp);
323	if (cmd == 's') {
324		xmon_trace[smp_processor_id()] = SSTEP;
325		excp->msr |= 0x400;
326	} else if (at_breakpoint(excp->nip)) {
327		xmon_trace[smp_processor_id()] = BRSTEP;
328		excp->msr |= 0x400;
329	} else {
330		xmon_trace[smp_processor_id()] = 0;
331		insert_bpts();
332	}
333#ifdef CONFIG_SMP
334	clear_bit(0, &got_xmon);
335	clear_bit(smp_processor_id(), &cpus_in_xmon);
336#endif /* CONFIG_SMP */
337	set_msrd(msr);		/* restore interrupt enable */
338}
339
340/* Code can call this to get a backtrace and continue. */
341void
342xmon_backtrace(const char *fmt, ...)
343{
344	va_list ap;
345	struct pt_regs regs;
346
347
348	/* Ok, grab regs as they are now.
349	 This won't do a particularily good job because the
350	 prologue has already been executed.
351	 ToDo: We could reach back into the callers save
352	 area to do a better job of representing the
353	 caller's state.
354	 */
355	asm volatile ("std	0,0(%0)\n\
356	    std	1,8(%0)\n\
357	    std	2,16(%0)\n\
358	    std	3,24(%0)\n\
359	    std	4,32(%0)\n\
360	    std	5,40(%0)\n\
361	    std	6,48(%0)\n\
362	    std	7,56(%0)\n\
363	    std	8,64(%0)\n\
364	    std	9,72(%0)\n\
365	    std	10,80(%0)\n\
366	    std	11,88(%0)\n\
367	    std	12,96(%0)\n\
368	    std	13,104(%0)\n\
369	    std	14,112(%0)\n\
370	    std	15,120(%0)\n\
371	    std	16,128(%0)\n\
372	    std	17,136(%0)\n\
373	    std	18,144(%0)\n\
374	    std	19,152(%0)\n\
375	    std	20,160(%0)\n\
376	    std	21,168(%0)\n\
377	    std	22,176(%0)\n\
378	    std	23,184(%0)\n\
379	    std	24,192(%0)\n\
380	    std	25,200(%0)\n\
381	    std	26,208(%0)\n\
382	    std	27,216(%0)\n\
383	    std	28,224(%0)\n\
384	    std	29,232(%0)\n\
385	    std	30,240(%0)\n\
386	    std	31,248(%0)" : : "b" (&regs));
387	/* Fetch the link reg for this stack frame.
388	 NOTE: the prev printf fills in the lr. */
389	regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
390	regs.msr = get_msr();
391	regs.ctr = get_ctr();
392	regs.xer = get_xer();
393	regs.ccr = get_cr();
394	regs.trap = 0;
395
396	va_start(ap, fmt);
397	xmon_vfprintf(stdout, fmt, ap);
398	xmon_putc('\n', stdout);
399	va_end(ap);
400	take_input("\n");
401	backtrace(&regs);
402}
403
404/* Call this to poll for ^C during busy operations.
405 * Returns true if the user has hit ^C.
406 */
407int
408xmon_interrupted(void)
409{
410	int ret = xmon_read_poll();
411	if (ret == 3) {
412		printf("\n^C interrupted.\n");
413		return 1;
414	}
415	return 0;
416}
417
418
419void
420xmon_irq(int irq, void *d, struct pt_regs *regs)
421{
422	unsigned long flags;
423	__save_flags(flags);
424	__cli();
425	printf("Keyboard interrupt\n");
426	xmon(regs);
427	__restore_flags(flags);
428}
429
430int
431xmon_bpt(struct pt_regs *regs)
432{
433	struct bpt *bp;
434
435	bp = at_breakpoint(regs->nip);
436	if (!bp)
437		return 0;
438	if (bp->count) {
439		--bp->count;
440		remove_bpts();
441		excprint(regs);
442		xmon_trace[smp_processor_id()] = BRSTEP;
443		regs->msr |= 0x400;
444	} else {
445		printf("Stopped at breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname);
446		xmon(regs);
447	}
448	return 1;
449}
450
451int
452xmon_sstep(struct pt_regs *regs)
453{
454	if (!xmon_trace[smp_processor_id()])
455		return 0;
456	if (xmon_trace[smp_processor_id()] == BRSTEP) {
457		xmon_trace[smp_processor_id()] = 0;
458		insert_bpts();
459	} else {
460		xmon(regs);
461	}
462	return 1;
463}
464
465int
466xmon_dabr_match(struct pt_regs *regs)
467{
468	if (dabr.enabled && dabr.count) {
469		--dabr.count;
470		remove_bpts();
471		excprint(regs);
472		xmon_trace[smp_processor_id()] = BRSTEP;
473		regs->msr |= 0x400;
474	} else {
475		dabr.instr = regs->nip;
476		xmon(regs);
477	}
478	return 1;
479}
480
481int
482xmon_iabr_match(struct pt_regs *regs)
483{
484	if (iabr.enabled && iabr.count) {
485		--iabr.count;
486		remove_bpts();
487		excprint(regs);
488		xmon_trace[smp_processor_id()] = BRSTEP;
489		regs->msr |= 0x400;
490	} else {
491		xmon(regs);
492	}
493	return 1;
494}
495
496static struct bpt *
497at_breakpoint(unsigned long pc)
498{
499	int i;
500	struct bpt *bp;
501
502	if (dabr.enabled && pc == dabr.instr)
503		return &dabr;
504	if (iabr.enabled && pc == iabr.address)
505		return &iabr;
506	bp = bpts;
507	for (i = 0; i < NBPTS; ++i, ++bp)
508		if (bp->enabled && pc == bp->address)
509			return bp;
510	return 0;
511}
512
513static void
514insert_bpts()
515{
516	int i;
517	struct bpt *bp;
518
519	if (naca->platform != PLATFORM_PSERIES)
520		return;
521	bp = bpts;
522	for (i = 0; i < NBPTS; ++i, ++bp) {
523		if (!bp->enabled)
524			continue;
525		if (mread(bp->address, &bp->instr, 4) != 4
526		    || mwrite(bp->address, &bpinstr, 4) != 4) {
527			printf("Couldn't insert breakpoint at %x, disabling\n",
528			       bp->address);
529			bp->enabled = 0;
530		} else {
531			store_inst((void *)bp->address);
532		}
533	}
534
535	if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) {
536		if (dabr.enabled)
537			set_dabr(dabr.address);
538		if (iabr.enabled)
539			set_iabr(iabr.address);
540	}
541}
542
543static void
544remove_bpts()
545{
546	int i;
547	struct bpt *bp;
548	unsigned instr;
549
550	if (naca->platform != PLATFORM_PSERIES)
551		return;
552	if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) {
553		set_dabr(0);
554		set_iabr(0);
555	}
556
557	bp = bpts;
558	for (i = 0; i < NBPTS; ++i, ++bp) {
559		if (!bp->enabled)
560			continue;
561		if (mread(bp->address, &instr, 4) == 4
562		    && instr == bpinstr
563		    && mwrite(bp->address, &bp->instr, 4) != 4)
564			printf("Couldn't remove breakpoint at %x\n",
565			       bp->address);
566		else
567			store_inst((void *)bp->address);
568	}
569}
570
571static char *last_cmd;
572
573/* Command interpreting routine */
574static int
575cmds(struct pt_regs *excp)
576{
577	int cmd;
578
579	last_cmd = NULL;
580	for(;;) {
581#ifdef CONFIG_SMP
582		printf("%d:", smp_processor_id());
583#endif /* CONFIG_SMP */
584		printf("mon> ");
585		fflush(stdout);
586		flush_input();
587		termch = 0;
588		cmd = skipbl();
589		if( cmd == '\n' ) {
590			if (last_cmd == NULL)
591				continue;
592			take_input(last_cmd);
593			last_cmd = NULL;
594			cmd = inchar();
595		}
596		switch (cmd) {
597		case 'z':
598			printf("Rebooting machine now...");
599			machine_restart(NULL);
600			break;
601		case 'Z':
602			printf("Halting machine now...");
603			machine_halt();
604			break;
605		case 'm':
606			cmd = inchar();
607			switch (cmd) {
608			case 'm':
609			case 's':
610			case 'd':
611				memops(cmd);
612				break;
613			case 'l':
614				memlocate();
615				break;
616			case 'z':
617				memzcan();
618				break;
619			case 'x':
620				mem_translate();
621				break;
622			case 'c':
623				mem_check();
624				break;
625			case 'j':
626				mem_map_check_slab();
627				break;
628			case 'f':
629				mem_find_real();
630				break;
631			case 'e':
632				mem_find_vsid();
633				break;
634			case 'r':
635				mem_check_dup_rpn();
636				break;
637			case 'i':
638				show_mem();
639				break;
640			case 'o':
641				mem_check_pagetable_vsids ();
642				break;
643			case 'q':
644				mem_map_lock_pages() ;
645				break;
646			default:
647				termch = cmd;
648				memex();
649			}
650			break;
651		case 'd':
652			dump();
653			break;
654		case 'r':
655			if (excp != NULL)
656				prregs(excp);	/* print regs */
657			break;
658		case 'e':
659			if (excp == NULL)
660				printf("No exception information\n");
661			else
662				excprint(excp);
663			break;
664		case 'M':
665			print_sysmap();
666			break;
667		case 'S':
668			super_regs();
669			break;
670		case 't':
671			backtrace(excp);
672			break;
673		case 'f':
674			cacheflush();
675			break;
676		case 'h':
677			dump_hash_table();
678			break;
679		case 's':
680		case 'x':
681		case EOF:
682			return cmd;
683		case '?':
684			printf(help_string);
685			break;
686		case 'p':
687			show_state();
688			break;
689		case 'b':
690			bpt_cmds();
691			break;
692		case 'C':
693			csum();
694			break;
695#ifdef CONFIG_SMP
696		case 'c':
697			cpu_cmd();
698			break;
699#endif /* CONFIG_SMP */
700		case 'T':
701			debug_trace();
702			break;
703		default:
704			printf("Unrecognized command: ");
705		        do {
706				if( ' ' < cmd && cmd <= '~' )
707					putchar(cmd);
708				else
709					printf("\\x%x", cmd);
710				cmd = inchar();
711		        } while (cmd != '\n');
712			printf(" (type ? for help)\n");
713			break;
714		}
715	}
716}
717
718#ifdef CONFIG_SMP
719static void cpu_cmd(void)
720{
721	unsigned long cpu;
722	int timeout;
723	int cmd;
724
725	cmd = inchar();
726	if (cmd == 'i') {
727		printf("stopping all cpus\n");
728		/* interrupt other cpu(s) */
729		cpu = MSG_ALL_BUT_SELF;
730		smp_send_xmon_break(cpu);
731		return;
732	}
733	termch = cmd;
734	if (!scanhex(&cpu)) {
735		/* print cpus waiting or in xmon */
736		printf("cpus stopped:");
737		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
738			if (test_bit(cpu, &cpus_in_xmon)) {
739				printf(" %d", cpu);
740				if (cpu == smp_processor_id())
741					printf("*", cpu);
742			}
743		}
744		printf("\n");
745		return;
746	}
747	/* try to switch to cpu specified */
748	take_xmon = cpu;
749	timeout = 10000000;
750	while (take_xmon >= 0) {
751		if (--timeout == 0) {
752			/* yes there's a race here */
753			take_xmon = -1;
754			printf("cpu %u didn't take control\n", cpu);
755			return;
756		}
757	}
758	/* now have to wait to be given control back */
759	while (test_and_set_bit(0, &got_xmon)) {
760		if (take_xmon == smp_processor_id()) {
761			take_xmon = -1;
762			break;
763		}
764	}
765}
766#endif /* CONFIG_SMP */
767
768static unsigned short fcstab[256] = {
769	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
770	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
771	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
772	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
773	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
774	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
775	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
776	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
777	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
778	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
779	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
780	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
781	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
782	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
783	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
784	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
785	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
786	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
787	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
788	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
789	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
790	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
791	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
792	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
793	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
794	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
795	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
796	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
797	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
798	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
799	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
800	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
801};
802
803#define FCS(fcs, c)	(((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
804
805static void
806csum(void)
807{
808	unsigned int i;
809	unsigned short fcs;
810	unsigned char v;
811
812	if (!scanhex(&adrs))
813		return;
814	if (!scanhex(&ncsum))
815		return;
816	fcs = 0xffff;
817	for (i = 0; i < ncsum; ++i) {
818		if (mread(adrs+i, &v, 1) == 0) {
819			printf("csum stopped at %x\n", adrs+i);
820			break;
821		}
822		fcs = FCS(fcs, v);
823	}
824	printf("%x\n", fcs);
825}
826
827static char *breakpoint_help_string =
828    "Breakpoint command usage:\n"
829    "b                show breakpoints\n"
830    "b <addr> [cnt]   set breakpoint at given instr addr\n"
831    "bc               clear all breakpoints\n"
832    "bc <n/addr>      clear breakpoint number n or at addr\n"
833    "bi <addr> [cnt]  set hardware instr breakpoint (broken?)\n"
834    "bd <addr> [cnt]  set hardware data breakpoint (broken?)\n"
835    "";
836
837static void
838bpt_cmds(void)
839{
840	int cmd;
841	unsigned long a;
842	int mode, i;
843	struct bpt *bp;
844	struct tbtable tab;
845
846	cmd = inchar();
847	switch (cmd) {
848	case 'd':	/* bd - hardware data breakpoint */
849		if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) {
850			printf("Not implemented on POWER4\n");
851			break;
852		}
853		mode = 7;
854		cmd = inchar();
855		if (cmd == 'r')
856			mode = 5;
857		else if (cmd == 'w')
858			mode = 6;
859		else
860			termch = cmd;
861		dabr.address = 0;
862		dabr.count = 0;
863		dabr.enabled = scanhex(&dabr.address);
864		scanhex(&dabr.count);
865		if (dabr.enabled)
866			dabr.address = (dabr.address & ~7) | mode;
867		break;
868	case 'i':	/* bi - hardware instr breakpoint */
869		if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) {
870			break;
871		}
872		iabr.address = 0;
873		iabr.count = 0;
874		iabr.enabled = scanhex(&iabr.address);
875		if (iabr.enabled)
876			iabr.address |= 3;
877		scanhex(&iabr.count);
878		break;
879	case 'c':
880		if (!scanhex(&a)) {
881			/* clear all breakpoints */
882			for (i = 0; i < NBPTS; ++i)
883				bpts[i].enabled = 0;
884			iabr.enabled = 0;
885			dabr.enabled = 0;
886			printf("All breakpoints cleared\n");
887		} else {
888			if (a <= NBPTS && a >= 1) {
889				/* assume a breakpoint number */
890				--a;	/* bp nums are 1 based */
891				bp = &bpts[a];
892			} else {
893				/* assume a breakpoint address */
894				bp = at_breakpoint(a);
895			}
896			if (bp == 0) {
897				printf("No breakpoint at %x\n", a);
898			} else {
899				printf("Cleared breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname);
900				bp->enabled = 0;
901			}
902		}
903		break;
904	case '?':
905	        printf(breakpoint_help_string);
906	        break;
907	default:
908		termch = cmd;
909	        cmd = skipbl();
910		if (cmd == '?') {
911			printf(breakpoint_help_string);
912			break;
913		}
914		termch = cmd;
915		if (!scanhex(&a)) {
916			/* print all breakpoints */
917			int bpnum;
918
919			printf("   type            address    count\n");
920			if (dabr.enabled) {
921				printf("   data   %.16lx %8x [", dabr.address & ~7,
922				       dabr.count);
923				if (dabr.address & 1)
924					printf("r");
925				if (dabr.address & 2)
926					printf("w");
927				printf("]\n");
928			}
929			if (iabr.enabled)
930				printf("   inst   %.16lx %8x\n", iabr.address & ~3,
931				       iabr.count);
932			for (bp = bpts, bpnum = 1; bp < &bpts[NBPTS]; ++bp, ++bpnum)
933				if (bp->enabled)
934					printf("%2x trap   %.16lx %8x  %s\n", bpnum, bp->address, bp->count, bp->funcname);
935			break;
936		}
937		bp = at_breakpoint(a);
938		if (bp == 0) {
939			for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
940				if (!bp->enabled)
941					break;
942			if (bp >= &bpts[NBPTS]) {
943				printf("Sorry, no free breakpoints.  Please clear one first.\n");
944				break;
945			}
946		}
947		bp->enabled = 1;
948		bp->address = a;
949		bp->count = 0;
950		scanhex(&bp->count);
951		/* Find the function name just once. */
952		bp->funcname[0] = '\0';
953		if (find_tb_table(bp->address, &tab) && tab.name[0]) {
954			/* Got a nice name for it. */
955			int delta = bp->address - tab.funcstart;
956			sprintf(bp->funcname, "%s+0x%x", tab.name, delta);
957		}
958		printf("Set breakpoint %2x trap   %.16lx %8x  %s\n", (bp-bpts)+1, bp->address, bp->count, bp->funcname);
959		break;
960	}
961}
962
963/* Very cheap human name for vector lookup. */
964static
965const char *getvecname(unsigned long vec)
966{
967	char *ret;
968	switch (vec) {
969	case 0x100:	ret = "(System Reset)"; break;
970	case 0x200:	ret = "(Machine Check)"; break;
971	case 0x300:	ret = "(Data Access)"; break;
972	case 0x400:	ret = "(Instruction Access)"; break;
973	case 0x500:	ret = "(Hardware Interrupt)"; break;
974	case 0x600:	ret = "(Alignment)"; break;
975	case 0x700:	ret = "(Program Check)"; break;
976	case 0x800:	ret = "(FPU Unavailable)"; break;
977	case 0x900:	ret = "(Decrementer)"; break;
978	case 0xc00:	ret = "(System Call)"; break;
979	case 0xd00:	ret = "(Single Step)"; break;
980	case 0xf00:	ret = "(Performance Monitor)"; break;
981	default: ret = "";
982	}
983	return ret;
984}
985
986static void
987backtrace(struct pt_regs *excp)
988{
989	unsigned long sp;
990	unsigned long lr;
991	unsigned long stack[3];
992	struct pt_regs regs;
993	struct tbtable tab;
994	int framecount;
995	char *funcname;
996	/* declare these as raw ptrs so we don't get func descriptors */
997	extern void *ret_from_except, *ret_from_syscall_1;
998
999	if (excp != NULL) {
1000	        lr = excp->link;
1001		sp = excp->gpr[1];
1002	} else {
1003	        /* Use care not to call any function before this point
1004		 so the saved lr has a chance of being good. */
1005	        asm volatile ("mflr %0" : "=r" (lr) :);
1006		sp = getsp();
1007	}
1008	scanhex(&sp);
1009	scannl();
1010	for (framecount = 0;
1011	     sp != 0 && framecount < MAXFRAMECOUNT;
1012	     sp = stack[0], framecount++) {
1013		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
1014			break;
1015		printf("%.16lx  %.16lx", sp, stack[2]);
1016		/* TAI -- for now only the ones cast to unsigned long will match.
1017		 * Need to test the rest...
1018		 */
1019		if ((stack[2] == (unsigned long)ret_from_except &&
1020		            (funcname = "ret_from_except"))
1021		    || (stack[2] == (unsigned long)ret_from_syscall_1 &&
1022		            (funcname = "ret_from_syscall_1"))
1023		    ) {
1024			printf("  %s\n", funcname);
1025			if (mread(sp+112, &regs, sizeof(regs)) != sizeof(regs))
1026				break;
1027			printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112);
1028			printf("                  %.16lx", regs.nip);
1029			if ((regs.nip & 0xffffffff00000000UL) &&
1030			    find_tb_table(regs.nip, &tab)) {
1031				int delta = regs.nip-tab.funcstart;
1032				if (delta < 0)
1033					printf("  <unknown code>");
1034				else
1035					printf("  %s+0x%x", tab.name, delta);
1036			}
1037			printf("\n");
1038                        if (regs.gpr[1] < sp) {
1039                            printf("<Stack drops into 32-bit userspace %.16lx>\n", regs.gpr[1]);
1040                            break;
1041			}
1042
1043			sp = regs.gpr[1];
1044			if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
1045				break;
1046		} else {
1047			if (stack[2] && find_tb_table(stack[2], &tab)) {
1048				int delta = stack[2]-tab.funcstart;
1049				if (delta < 0)
1050					printf("  <unknown code>");
1051				else
1052					printf("  %s+0x%x", tab.name, delta);
1053			}
1054			printf("\n");
1055		}
1056		if (stack[0] && stack[0] <= sp) {
1057			if ((stack[0] & 0xffffffff00000000UL) == 0)
1058				printf("<Stack drops into 32-bit userspace %.16lx>\n", stack[0]);
1059			else
1060				printf("<Corrupt stack.  Next backchain is %.16lx>\n", stack[0]);
1061			break;
1062		}
1063	}
1064	if (framecount >= MAXFRAMECOUNT)
1065		printf("<Punt. Too many stack frames>\n");
1066}
1067
1068int
1069getsp()
1070{
1071	int x;
1072
1073	asm("mr %0,1" : "=r" (x) :);
1074	return x;
1075}
1076
1077spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED;
1078
1079void
1080excprint(struct pt_regs *fp)
1081{
1082	struct task_struct *c;
1083	struct tbtable tab;
1084	unsigned long flags;
1085
1086	spin_lock_irqsave(&exception_print_lock, flags);
1087
1088#ifdef CONFIG_SMP
1089	printf("cpu %d: ", smp_processor_id());
1090#endif /* CONFIG_SMP */
1091
1092	printf("Vector: %lx %s at  [%lx]\n", fp->trap, getvecname(fp->trap), fp);
1093	printf("    pc: %lx", fp->nip);
1094	if (find_tb_table(fp->nip, &tab) && tab.name[0]) {
1095		/* Got a nice name for it */
1096		int delta = fp->nip - tab.funcstart;
1097		printf(" (%s+0x%x)", tab.name, delta);
1098	}
1099	printf("\n");
1100	printf("    lr: %lx", fp->link);
1101	if (find_tb_table(fp->link, &tab) && tab.name[0]) {
1102		/* Got a nice name for it */
1103		int delta = fp->link - tab.funcstart;
1104		printf(" (%s+0x%x)", tab.name, delta);
1105	}
1106	printf("\n");
1107	printf("    sp: %lx\n", fp->gpr[1]);
1108	printf("   msr: %lx\n", fp->msr);
1109
1110	if (fp->trap == 0x300 || fp->trap == 0x600) {
1111		printf("   dar: %lx\n", fp->dar);
1112		printf(" dsisr: %lx\n", fp->dsisr);
1113	}
1114
1115	c = current;
1116	printf("  current = 0x%lx\n", c);
1117	printf("  paca    = 0x%lx\n", get_paca());
1118	if (c) {
1119		printf("  current = %lx, pid = %ld, comm = %s\n",
1120		       c, c->pid, c->comm);
1121	}
1122
1123	spin_unlock_irqrestore(&exception_print_lock, flags);
1124}
1125
1126void
1127prregs(struct pt_regs *fp)
1128{
1129	int n;
1130	unsigned long base;
1131
1132	if (scanhex((void *)&base))
1133		fp = (struct pt_regs *) base;
1134	for (n = 0; n < 16; ++n)
1135		printf("R%.2ld = %.16lx   R%.2ld = %.16lx\n", n, fp->gpr[n],
1136		       n+16, fp->gpr[n+16]);
1137	printf("pc  = %.16lx   msr = %.16lx\nlr  = %.16lx   cr  = %.16lx\n",
1138	       fp->nip, fp->msr, fp->link, fp->ccr);
1139	printf("ctr = %.16lx   xer = %.16lx   trap = %8lx\n",
1140	       fp->ctr, fp->xer, fp->trap);
1141}
1142
1143void
1144cacheflush(void)
1145{
1146	int cmd;
1147	unsigned long nflush;
1148
1149	cmd = inchar();
1150	if (cmd != 'i')
1151		termch = cmd;
1152	scanhex((void *)&adrs);
1153	if (termch != '\n')
1154		termch = 0;
1155	nflush = 1;
1156	scanhex(&nflush);
1157	nflush = (nflush + 31) / 32;
1158	if (cmd != 'i') {
1159		for (; nflush > 0; --nflush, adrs += 0x20)
1160			cflush((void *) adrs);
1161	} else {
1162		for (; nflush > 0; --nflush, adrs += 0x20)
1163			cinval((void *) adrs);
1164	}
1165}
1166
1167unsigned long
1168read_spr(int n)
1169{
1170	unsigned int instrs[2];
1171	unsigned long (*code)(void);
1172	unsigned long opd[3];
1173
1174	instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1175	instrs[1] = 0x4e800020;
1176	opd[0] = (unsigned long)instrs;
1177	opd[1] = 0;
1178	opd[2] = 0;
1179	store_inst(instrs);
1180	store_inst(instrs+1);
1181	code = (unsigned long (*)(void)) opd;
1182
1183	return code();
1184}
1185
1186void
1187write_spr(int n, unsigned long val)
1188{
1189	unsigned int instrs[2];
1190	unsigned long (*code)(unsigned long);
1191	unsigned long opd[3];
1192
1193	instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1194	instrs[1] = 0x4e800020;
1195	opd[0] = (unsigned long)instrs;
1196	opd[1] = 0;
1197	opd[2] = 0;
1198	store_inst(instrs);
1199	store_inst(instrs+1);
1200	code = (unsigned long (*)(unsigned long)) opd;
1201
1202	code(val);
1203}
1204
1205static unsigned long regno;
1206extern char exc_prolog;
1207extern char dec_exc;
1208
1209void
1210print_sysmap(void)
1211{
1212	extern char *sysmap;
1213	if ( sysmap )
1214		printf("System.map: \n%s", sysmap);
1215}
1216
1217void
1218super_regs()
1219{
1220	int i, cmd;
1221	unsigned long val;
1222	struct paca_struct*  ptrPaca = NULL;
1223	struct ItLpPaca*  ptrLpPaca = NULL;
1224	struct ItLpRegSave*  ptrLpRegSave = NULL;
1225
1226	cmd = skipbl();
1227	if (cmd == '\n') {
1228	        unsigned long sp, toc;
1229		asm("mr %0,1" : "=r" (sp) :);
1230		asm("mr %0,2" : "=r" (toc) :);
1231
1232		printf("msr  = %.16lx  sprg0= %.16lx\n", get_msr(), get_sprg0());
1233		printf("pvr  = %.16lx  sprg1= %.16lx\n", get_pvr(), get_sprg1());
1234		printf("dec  = %.16lx  sprg2= %.16lx\n", get_dec(), get_sprg2());
1235		printf("sp   = %.16lx  sprg3= %.16lx\n", sp, get_sprg3());
1236		printf("toc  = %.16lx  dar  = %.16lx\n", toc, get_dar());
1237		printf("srr0 = %.16lx  srr1 = %.16lx\n", get_srr0(), get_srr1());
1238		printf("asr  = %.16lx\n", mfasr());
1239		for (i = 0; i < 8; ++i)
1240			printf("sr%.2ld = %.16lx  sr%.2ld = %.16lx\n", i, get_sr(i), i+8, get_sr(i+8));
1241
1242		// Dump out relevant Paca data areas.
1243		printf("Paca: \n");
1244		ptrPaca = get_paca();
1245
1246		printf("  Local Processor Control Area (LpPaca): \n");
1247		ptrLpPaca = ptrPaca->xLpPacaPtr;
1248		printf("    Saved Srr0=%.16lx  Saved Srr1=%.16lx \n", ptrLpPaca->xSavedSrr0, ptrLpPaca->xSavedSrr1);
1249		printf("    Saved Gpr3=%.16lx  Saved Gpr4=%.16lx \n", ptrLpPaca->xSavedGpr3, ptrLpPaca->xSavedGpr4);
1250		printf("    Saved Gpr5=%.16lx \n", ptrLpPaca->xSavedGpr5);
1251
1252		printf("  Local Processor Register Save Area (LpRegSave): \n");
1253		ptrLpRegSave = ptrPaca->xLpRegSavePtr;
1254		printf("    Saved Sprg0=%.16lx  Saved Sprg1=%.16lx \n", ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1255		printf("    Saved Sprg2=%.16lx  Saved Sprg3=%.16lx \n", ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1256		printf("    Saved Msr  =%.16lx  Saved Nia  =%.16lx \n", ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1257
1258		return;
1259	}
1260
1261	scanhex(&regno);
1262	switch (cmd) {
1263	case 'w':
1264		val = read_spr(regno);
1265		scanhex(&val);
1266		write_spr(regno, val);
1267		/* fall through */
1268	case 'r':
1269		printf("spr %lx = %lx\n", regno, read_spr(regno));
1270		break;
1271	case 's':
1272		val = get_sr(regno);
1273		scanhex(&val);
1274		set_sr(regno, val);
1275		break;
1276	case 'm':
1277		val = get_msr();
1278		scanhex(&val);
1279		set_msrd(val);
1280		break;
1281	}
1282	scannl();
1283}
1284
1285
1286#ifndef CONFIG_PPC64BRIDGE
1287static void
1288dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1289{
1290	extern void *Hash;
1291	extern unsigned long Hash_size;
1292	unsigned *htab = Hash;
1293	unsigned hsize = Hash_size;
1294	unsigned v, hmask, va, last_va;
1295	int found, last_found, i;
1296	unsigned *hg, w1, last_w2, last_va0;
1297
1298	last_found = 0;
1299	hmask = hsize / 64 - 1;
1300	va = start;
1301	start = (start >> 12) & 0xffff;
1302	end = (end >> 12) & 0xffff;
1303	for (v = start; v < end; ++v) {
1304		found = 0;
1305		hg = htab + (((v ^ seg) & hmask) * 16);
1306		w1 = 0x80000000 | (seg << 7) | (v >> 10);
1307		for (i = 0; i < 8; ++i, hg += 2) {
1308			if (*hg == w1) {
1309				found = 1;
1310				break;
1311			}
1312		}
1313		if (!found) {
1314			w1 ^= 0x40;
1315			hg = htab + ((~(v ^ seg) & hmask) * 16);
1316			for (i = 0; i < 8; ++i, hg += 2) {
1317				if (*hg == w1) {
1318					found = 1;
1319					break;
1320				}
1321			}
1322		}
1323		if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1324			if (last_found) {
1325				if (last_va != last_va0)
1326					printf(" ... %x", last_va);
1327				printf("\n");
1328			}
1329			if (found) {
1330				printf("%x to %x", va, hg[1]);
1331				last_va0 = va;
1332			}
1333			last_found = found;
1334		}
1335		if (found) {
1336			last_w2 = hg[1] & ~0x180;
1337			last_va = va;
1338		}
1339		va += 4096;
1340	}
1341	if (last_found)
1342		printf(" ... %x\n", last_va);
1343}
1344
1345#else /* CONFIG_PPC64BRIDGE */
1346static void
1347dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1348{
1349	extern void *Hash;
1350	extern unsigned long Hash_size;
1351	unsigned *htab = Hash;
1352	unsigned hsize = Hash_size;
1353	unsigned v, hmask, va, last_va;
1354	int found, last_found, i;
1355	unsigned *hg, w1, last_w2, last_va0;
1356
1357	last_found = 0;
1358	hmask = hsize / 128 - 1;
1359	va = start;
1360	start = (start >> 12) & 0xffff;
1361	end = (end >> 12) & 0xffff;
1362	for (v = start; v < end; ++v) {
1363		found = 0;
1364		hg = htab + (((v ^ seg) & hmask) * 32);
1365		w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
1366		for (i = 0; i < 8; ++i, hg += 4) {
1367			if (hg[1] == w1) {
1368				found = 1;
1369				break;
1370			}
1371		}
1372		if (!found) {
1373			w1 ^= 2;
1374			hg = htab + ((~(v ^ seg) & hmask) * 32);
1375			for (i = 0; i < 8; ++i, hg += 4) {
1376				if (hg[1] == w1) {
1377					found = 1;
1378					break;
1379				}
1380			}
1381		}
1382		if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
1383			if (last_found) {
1384				if (last_va != last_va0)
1385					printf(" ... %x", last_va);
1386				printf("\n");
1387			}
1388			if (found) {
1389				printf("%x to %x", va, hg[3]);
1390				last_va0 = va;
1391			}
1392			last_found = found;
1393		}
1394		if (found) {
1395			last_w2 = hg[3] & ~0x180;
1396			last_va = va;
1397		}
1398		va += 4096;
1399	}
1400	if (last_found)
1401		printf(" ... %x\n", last_va);
1402}
1403#endif /* CONFIG_PPC64BRIDGE */
1404
1405static unsigned long hash_ctx;
1406static unsigned long hash_start;
1407static unsigned long hash_end;
1408
1409static void
1410dump_hash_table()
1411{
1412	int seg;
1413	unsigned seg_start, seg_end;
1414
1415	hash_ctx = 0;
1416	hash_start = 0;
1417	hash_end = 0xfffff000;
1418	scanhex(&hash_ctx);
1419	scanhex(&hash_start);
1420	scanhex(&hash_end);
1421	printf("Mappings for context %x\n", hash_ctx);
1422	seg_start = hash_start;
1423	for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1424		seg_end = (seg << 28) | 0x0ffff000;
1425		if (seg_end > hash_end)
1426			seg_end = hash_end;
1427		dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end);
1428		seg_start = seg_end + 0x1000;
1429	}
1430}
1431
1432int
1433mread(unsigned long adrs, void *buf, int size)
1434{
1435	volatile int n;
1436	char *p, *q;
1437
1438	n = 0;
1439	if( setjmp(bus_error_jmp) == 0 ){
1440		debugger_fault_handler = handle_fault;
1441		sync();
1442		p = (char *) adrs;
1443		q = (char *) buf;
1444		switch (size) {
1445		case 2: *(short *)q = *(short *)p;	break;
1446		case 4: *(int *)q = *(int *)p;		break;
1447		default:
1448			for( ; n < size; ++n ) {
1449				*q++ = *p++;
1450				sync();
1451			}
1452		}
1453		sync();
1454		/* wait a little while to see if we get a machine check */
1455		__delay(200);
1456		n = size;
1457	}
1458	debugger_fault_handler = 0;
1459	return n;
1460}
1461
1462int
1463mwrite(unsigned long adrs, void *buf, int size)
1464{
1465	volatile int n;
1466	char *p, *q;
1467
1468	n = 0;
1469	if( setjmp(bus_error_jmp) == 0 ){
1470		debugger_fault_handler = handle_fault;
1471		sync();
1472		p = (char *) adrs;
1473		q = (char *) buf;
1474		switch (size) {
1475		case 2: *(short *)p = *(short *)q;	break;
1476		case 4: *(int *)p = *(int *)q;		break;
1477		default:
1478			for( ; n < size; ++n ) {
1479				*p++ = *q++;
1480				sync();
1481			}
1482		}
1483		sync();
1484		/* wait a little while to see if we get a machine check */
1485		__delay(200);
1486		n = size;
1487	} else {
1488		printf("*** Error writing address %x\n", adrs + n);
1489	}
1490	debugger_fault_handler = 0;
1491	return n;
1492}
1493
1494static int fault_type;
1495static char *fault_chars[] = { "--", "**", "##" };
1496
1497static void
1498handle_fault(struct pt_regs *regs)
1499{
1500	fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
1501	longjmp(bus_error_jmp, 1);
1502}
1503
1504#define SWAP(a, b, t)	((t) = (a), (a) = (b), (b) = (t))
1505
1506void
1507byterev(unsigned char *val, int size)
1508{
1509	int t;
1510
1511	switch (size) {
1512	case 2:
1513		SWAP(val[0], val[1], t);
1514		break;
1515	case 4:
1516		SWAP(val[0], val[3], t);
1517		SWAP(val[1], val[2], t);
1518		break;
1519	case 8: /* is there really any use for this? */
1520		SWAP(val[0], val[7], t);
1521		SWAP(val[1], val[6], t);
1522		SWAP(val[2], val[5], t);
1523		SWAP(val[3], val[4], t);
1524		break;
1525	}
1526}
1527
1528static int brev;
1529static int mnoread;
1530
1531static char *memex_help_string =
1532    "Memory examine command usage:\n"
1533    "m [addr] [flags] examine/change memory\n"
1534    "  addr is optional.  will start where left off.\n"
1535    "  flags may include chars from this set:\n"
1536    "    b   modify by bytes (default)\n"
1537    "    w   modify by words (2 byte)\n"
1538    "    l   modify by longs (4 byte)\n"
1539    "    d   modify by doubleword (8 byte)\n"
1540    "    r   toggle reverse byte order mode\n"
1541    "    n   do not read memory (for i/o spaces)\n"
1542    "    .   ok to read (default)\n"
1543    "NOTE: flags are saved as defaults\n"
1544    "";
1545
1546static char *memex_subcmd_help_string =
1547    "Memory examine subcommands:\n"
1548    "  hexval   write this val to current location\n"
1549    "  'string' write chars from string to this location\n"
1550    "  '        increment address\n"
1551    "  ^        decrement address\n"
1552    "  /        increment addr by 0x10.  //=0x100, ///=0x1000, etc\n"
1553    "  \\        decrement addr by 0x10.  \\\\=0x100, \\\\\\=0x1000, etc\n"
1554    "  `        clear no-read flag\n"
1555    "  ;        stay at this addr\n"
1556    "  v        change to byte mode\n"
1557    "  w        change to word (2 byte) mode\n"
1558    "  l        change to long (4 byte) mode\n"
1559    "  u        change to doubleword (8 byte) mode\n"
1560    "  m addr   change current addr\n"
1561    "  n        toggle no-read flag\n"
1562    "  r        toggle byte reverse flag\n"
1563    "  < count  back up count bytes\n"
1564    "  > count  skip forward count bytes\n"
1565    "  x        exit this mode\n"
1566    "";
1567
1568void
1569memex()
1570{
1571	int cmd, inc, i, nslash;
1572	unsigned long n;
1573	unsigned char val[16];
1574
1575	scanhex((void *)&adrs);
1576	cmd = skipbl();
1577	if (cmd == '?') {
1578		printf(memex_help_string);
1579		return;
1580	} else {
1581		termch = cmd;
1582	}
1583	last_cmd = "m\n";
1584	while ((cmd = skipbl()) != '\n') {
1585		switch( cmd ){
1586		case 'b':	size = 1;	break;
1587		case 'w':	size = 2;	break;
1588		case 'l':	size = 4;	break;
1589		case 'd':	size = 8;	break;
1590		case 'r': 	brev = !brev;	break;
1591		case 'n':	mnoread = 1;	break;
1592		case '.':	mnoread = 0;	break;
1593		}
1594	}
1595	if( size <= 0 )
1596		size = 1;
1597	else if( size > 8 )
1598		size = 8;
1599	for(;;){
1600		if (!mnoread)
1601			n = mread(adrs, val, size);
1602		printf("%.16x%c", adrs, brev? 'r': ' ');
1603		if (!mnoread) {
1604			if (brev)
1605				byterev(val, size);
1606			putchar(' ');
1607			for (i = 0; i < n; ++i)
1608				printf("%.2x", val[i]);
1609			for (; i < size; ++i)
1610				printf("%s", fault_chars[fault_type]);
1611		}
1612		putchar(' ');
1613		inc = size;
1614		nslash = 0;
1615		for(;;){
1616			if( scanhex(&n) ){
1617				for (i = 0; i < size; ++i)
1618					val[i] = n >> (i * 8);
1619				if (!brev)
1620					byterev(val, size);
1621				mwrite(adrs, val, size);
1622				inc = size;
1623			}
1624			cmd = skipbl();
1625			if (cmd == '\n')
1626				break;
1627			inc = 0;
1628			switch (cmd) {
1629			case '\'':
1630				for(;;){
1631					n = inchar();
1632					if( n == '\\' )
1633						n = bsesc();
1634					else if( n == '\'' )
1635						break;
1636					for (i = 0; i < size; ++i)
1637						val[i] = n >> (i * 8);
1638					if (!brev)
1639						byterev(val, size);
1640					mwrite(adrs, val, size);
1641					adrs += size;
1642				}
1643				adrs -= size;
1644				inc = size;
1645				break;
1646			case ',':
1647				adrs += size;
1648				break;
1649			case '.':
1650				mnoread = 0;
1651				break;
1652			case ';':
1653				break;
1654			case 'x':
1655			case EOF:
1656				scannl();
1657				return;
1658			case 'b':
1659			case 'v':
1660				size = 1;
1661				break;
1662			case 'w':
1663				size = 2;
1664				break;
1665			case 'l':
1666				size = 4;
1667				break;
1668			case 'u':
1669				size = 8;
1670				break;
1671			case '^':
1672				adrs -= size;
1673				break;
1674				break;
1675			case '/':
1676				if (nslash > 0)
1677					adrs -= 1 << nslash;
1678				else
1679					nslash = 0;
1680				nslash += 4;
1681				adrs += 1 << nslash;
1682				break;
1683			case '\\':
1684				if (nslash < 0)
1685					adrs += 1 << -nslash;
1686				else
1687					nslash = 0;
1688				nslash -= 4;
1689				adrs -= 1 << -nslash;
1690				break;
1691			case 'm':
1692				scanhex((void *)&adrs);
1693				break;
1694			case 'n':
1695				mnoread = 1;
1696				break;
1697			case 'r':
1698				brev = !brev;
1699				break;
1700			case '<':
1701				n = size;
1702				scanhex(&n);
1703				adrs -= n;
1704				break;
1705			case '>':
1706				n = size;
1707				scanhex(&n);
1708				adrs += n;
1709				break;
1710			case '?':
1711				printf(memex_subcmd_help_string);
1712				break;
1713			}
1714		}
1715		adrs += inc;
1716	}
1717}
1718
1719int
1720bsesc()
1721{
1722	int c;
1723
1724	c = inchar();
1725	switch( c ){
1726	case 'n':	c = '\n';	break;
1727	case 'r':	c = '\r';	break;
1728	case 'b':	c = '\b';	break;
1729	case 't':	c = '\t';	break;
1730	}
1731	return c;
1732}
1733
1734#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
1735			 || ('a' <= (c) && (c) <= 'f') \
1736			 || ('A' <= (c) && (c) <= 'F'))
1737void
1738dump()
1739{
1740	int c;
1741
1742	c = inchar();
1743	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1744		termch = c;
1745	scanhex((void *)&adrs);
1746	if( termch != '\n')
1747		termch = 0;
1748	if( c == 'i' ){
1749		scanhex(&nidump);
1750		if( nidump == 0 )
1751			nidump = 16;
1752		adrs += ppc_inst_dump(adrs, nidump);
1753		last_cmd = "di\n";
1754	} else {
1755		scanhex(&ndump);
1756		if( ndump == 0 )
1757			ndump = 64;
1758		prdump(adrs, ndump);
1759		adrs += ndump;
1760		last_cmd = "d\n";
1761	}
1762}
1763
1764void
1765prdump(unsigned long adrs, long ndump)
1766{
1767	long n, m, c, r, nr;
1768	unsigned char temp[16];
1769
1770	for( n = ndump; n > 0; ){
1771		printf("%.16lx", adrs);
1772		putchar(' ');
1773		r = n < 16? n: 16;
1774		nr = mread(adrs, temp, r);
1775		adrs += nr;
1776		for( m = 0; m < r; ++m ){
1777		        if ((m & 7) == 0 && m > 0)
1778			    putchar(' ');
1779			if( m < nr )
1780				printf("%.2x", temp[m]);
1781			else
1782				printf("%s", fault_chars[fault_type]);
1783		}
1784		for(; m < 16; ++m )
1785			printf("   ");
1786		printf("  |");
1787		for( m = 0; m < r; ++m ){
1788			if( m < nr ){
1789				c = temp[m];
1790				putchar(' ' <= c && c <= '~'? c: '.');
1791			} else
1792				putchar(' ');
1793		}
1794		n -= r;
1795		for(; m < 16; ++m )
1796			putchar(' ');
1797		printf("|\n");
1798		if( nr < r )
1799			break;
1800	}
1801}
1802
1803int
1804ppc_inst_dump(unsigned long adr, long count)
1805{
1806	int nr, dotted;
1807	unsigned long first_adr;
1808	unsigned long inst, last_inst;
1809	unsigned char val[4];
1810
1811	dotted = 0;
1812	for (first_adr = adr; count > 0; --count, adr += 4){
1813		nr = mread(adr, val, 4);
1814		if( nr == 0 ){
1815			const char *x = fault_chars[fault_type];
1816			printf("%.16lx  %s%s%s%s\n", adr, x, x, x, x);
1817			break;
1818		}
1819		inst = GETWORD(val);
1820		if (adr > first_adr && inst == last_inst) {
1821			if (!dotted) {
1822				printf(" ...\n");
1823				dotted = 1;
1824			}
1825			continue;
1826		}
1827		dotted = 0;
1828		last_inst = inst;
1829		printf("%.16lx  ", adr);
1830		printf("%.8x\t", inst);
1831		print_insn_big_powerpc(stdout, inst, adr);	/* always returns 4 */
1832		printf("\n");
1833	}
1834	return adr - first_adr;
1835}
1836
1837void
1838print_address(unsigned long addr)
1839{
1840	printf("0x%lx", addr);
1841}
1842
1843/*
1844 * Memory operations - move, set, print differences
1845 */
1846static unsigned long mdest;		/* destination address */
1847static unsigned long msrc;		/* source address */
1848static unsigned long mval;		/* byte value to set memory to */
1849static unsigned long mcount;		/* # bytes to affect */
1850static unsigned long mdiffs;		/* max # differences to print */
1851
1852void
1853memops(int cmd)
1854{
1855	scanhex((void *)&mdest);
1856	if( termch != '\n' )
1857		termch = 0;
1858	scanhex((void *)(cmd == 's'? &mval: &msrc));
1859	if( termch != '\n' )
1860		termch = 0;
1861	scanhex((void *)&mcount);
1862	switch( cmd ){
1863	case 'm':
1864		memmove((void *)mdest, (void *)msrc, mcount);
1865		break;
1866	case 's':
1867		memset((void *)mdest, mval, mcount);
1868		break;
1869	case 'd':
1870		if( termch != '\n' )
1871			termch = 0;
1872		scanhex((void *)&mdiffs);
1873		memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1874		break;
1875	}
1876}
1877
1878void
1879memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1880{
1881	unsigned n, prt;
1882
1883	prt = 0;
1884	for( n = nb; n > 0; --n )
1885		if( *p1++ != *p2++ )
1886			if( ++prt <= maxpr )
1887				printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
1888					p1[-1], p2 - 1, p2[-1]);
1889	if( prt > maxpr )
1890		printf("Total of %d differences\n", prt);
1891}
1892
1893static unsigned mend;
1894static unsigned mask;
1895
1896void
1897memlocate()
1898{
1899	unsigned a, n;
1900	unsigned char val[4];
1901
1902	last_cmd = "ml";
1903	scanhex((void *)&mdest);
1904	if (termch != '\n') {
1905		termch = 0;
1906		scanhex((void *)&mend);
1907		if (termch != '\n') {
1908			termch = 0;
1909			scanhex((void *)&mval);
1910			mask = ~0;
1911			if (termch != '\n') termch = 0;
1912			scanhex((void *)&mask);
1913		}
1914	}
1915	n = 0;
1916	for (a = mdest; a < mend; a += 4) {
1917		if (mread(a, val, 4) == 4
1918			&& ((GETWORD(val) ^ mval) & mask) == 0) {
1919			printf("%.16x:  %.16x\n", a, GETWORD(val));
1920			if (++n >= 10)
1921				break;
1922		}
1923	}
1924}
1925
1926static unsigned long mskip = 0x1000;
1927static unsigned long mlim = 0xffffffff;
1928
1929void
1930memzcan()
1931{
1932	unsigned char v;
1933	unsigned a;
1934	int ok, ook;
1935
1936	scanhex(&mdest);
1937	if (termch != '\n') termch = 0;
1938	scanhex(&mskip);
1939	if (termch != '\n') termch = 0;
1940	scanhex(&mlim);
1941	ook = 0;
1942	for (a = mdest; a < mlim; a += mskip) {
1943		ok = mread(a, &v, 1);
1944		if (ok && !ook) {
1945			printf("%.8x .. ", a);
1946			fflush(stdout);
1947		} else if (!ok && ook)
1948			printf("%.8x\n", a - mskip);
1949		ook = ok;
1950		if (a + mskip < a)
1951			break;
1952	}
1953	if (ook)
1954		printf("%.8x\n", a - mskip);
1955}
1956
1957/* Input scanning routines */
1958int
1959skipbl()
1960{
1961	int c;
1962
1963	if( termch != 0 ){
1964		c = termch;
1965		termch = 0;
1966	} else
1967		c = inchar();
1968	while( c == ' ' || c == '\t' )
1969		c = inchar();
1970	return c;
1971}
1972
1973int
1974scanhex(vp)
1975unsigned long *vp;
1976{
1977	int c, d;
1978	unsigned long v;
1979
1980	c = skipbl();
1981	d = hexdigit(c);
1982	if( d == EOF ){
1983		termch = c;
1984		return 0;
1985	}
1986	v = 0;
1987	do {
1988		v = (v << 4) + d;
1989		c = inchar();
1990		d = hexdigit(c);
1991	} while( d != EOF );
1992	termch = c;
1993	*vp = v;
1994	return 1;
1995}
1996
1997void
1998scannl()
1999{
2000	int c;
2001
2002	c = termch;
2003	termch = 0;
2004	while( c != '\n' )
2005		c = inchar();
2006}
2007
2008int
2009hexdigit(int c)
2010{
2011	if( '0' <= c && c <= '9' )
2012		return c - '0';
2013	if( 'A' <= c && c <= 'F' )
2014		return c - ('A' - 10);
2015	if( 'a' <= c && c <= 'f' )
2016		return c - ('a' - 10);
2017	return EOF;
2018}
2019
2020void
2021getstring(char *s, int size)
2022{
2023	int c;
2024
2025	c = skipbl();
2026	do {
2027		if( size > 1 ){
2028			*s++ = c;
2029			--size;
2030		}
2031		c = inchar();
2032	} while( c != ' ' && c != '\t' && c != '\n' );
2033	termch = c;
2034	*s = 0;
2035}
2036
2037static char line[256];
2038static char *lineptr;
2039
2040void
2041flush_input()
2042{
2043	lineptr = NULL;
2044}
2045
2046int
2047inchar()
2048{
2049	if (lineptr == NULL || *lineptr == 0) {
2050		if (fgets(line, sizeof(line), stdin) == NULL) {
2051			lineptr = NULL;
2052			return EOF;
2053		}
2054		lineptr = line;
2055	}
2056	return *lineptr++;
2057}
2058
2059void
2060take_input(str)
2061char *str;
2062{
2063	lineptr = str;
2064}
2065
2066
2067/* Starting at codeaddr scan forward for a tbtable and fill in the
2068 given table.  Return non-zero if successful at doing something.
2069 */
2070static int
2071find_tb_table(unsigned long codeaddr, struct tbtable *tab)
2072{
2073	unsigned long codeaddr_max;
2074	unsigned long tbtab_start;
2075	int nr;
2076	int instr;
2077	int num_parms;
2078
2079	if (tab == NULL)
2080		return 0;
2081	memset(tab, 0, sizeof(tab));
2082
2083	/* Scan instructions starting at codeaddr for 128k max */
2084	for (codeaddr_max = codeaddr + 128*1024*4;
2085	     codeaddr < codeaddr_max;
2086	     codeaddr += 4) {
2087		nr = mread(codeaddr, &instr, 4);
2088		if (nr != 4)
2089			return 0;	/* Bad read.  Give up promptly. */
2090		if (instr == 0) {
2091			/* table should follow. */
2092			int version;
2093			unsigned long flags;
2094			tbtab_start = codeaddr;	/* save it to compute func start addr */
2095			codeaddr += 4;
2096			nr = mread(codeaddr, &flags, 8);
2097			if (nr != 8)
2098				return 0;	/* Bad read or no tb table. */
2099			tab->flags = flags;
2100			version = (flags >> 56) & 0xff;
2101			if (version != 0)
2102				continue;	/* No tb table here. */
2103			/* Now, like the version, some of the flags are values
2104			 that are more conveniently extracted... */
2105			tab->fp_saved = (flags >> 24) & 0x3f;
2106			tab->gpr_saved = (flags >> 16) & 0x3f;
2107			tab->fixedparms = (flags >> 8) & 0xff;
2108			tab->floatparms = (flags >> 1) & 0x7f;
2109			codeaddr += 8;
2110			num_parms = tab->fixedparms + tab->floatparms;
2111			if (num_parms) {
2112				unsigned int parminfo;
2113				int parm;
2114				if (num_parms > 32)
2115					return 1;	/* incomplete */
2116				nr = mread(codeaddr, &parminfo, 4);
2117				if (nr != 4)
2118					return 1;	/* incomplete */
2119				/* decode parminfo...32 bits.
2120				 A zero means fixed.  A one means float and the
2121				 following bit determines single (0) or double (1).
2122				 */
2123				for (parm = 0; parm < num_parms; parm++) {
2124					if (parminfo & 0x80000000) {
2125						parminfo <<= 1;
2126						if (parminfo & 0x80000000)
2127							tab->parminfo[parm] = TBTAB_PARMDFLOAT;
2128						else
2129							tab->parminfo[parm] = TBTAB_PARMSFLOAT;
2130					} else {
2131						tab->parminfo[parm] = TBTAB_PARMFIXED;
2132					}
2133					parminfo <<= 1;
2134				}
2135				codeaddr += 4;
2136			}
2137			if (flags & TBTAB_FLAGSHASTBOFF) {
2138				nr = mread(codeaddr, &tab->tb_offset, 4);
2139				if (nr != 4)
2140					return 1;	/* incomplete */
2141				if (tab->tb_offset > 0) {
2142					tab->funcstart = tbtab_start - tab->tb_offset;
2143				}
2144				codeaddr += 4;
2145			}
2146			/* hand_mask appears to be always be omitted. */
2147			if (flags & TBTAB_FLAGSHASCTL) {
2148				/* Assume this will never happen for C or asm */
2149				return 1;	/* incomplete */
2150			}
2151			if (flags & TBTAB_FLAGSNAMEPRESENT) {
2152				short namlen;
2153				nr = mread(codeaddr, &namlen, 2);
2154				if (nr != 2)
2155					return 1;	/* incomplete */
2156				if (namlen >= sizeof(tab->name))
2157					namlen = sizeof(tab->name)-1;
2158				codeaddr += 2;
2159				nr = mread(codeaddr, tab->name, namlen);
2160				tab->name[namlen] = '\0';
2161				codeaddr += namlen;
2162			}
2163			return 1;
2164		}
2165	}
2166	return 0;	/* hit max...sorry. */
2167}
2168
2169void
2170mem_translate()
2171{
2172	int c;
2173	unsigned long ea, va, vsid, vpn, page, hpteg_slot_primary, hpteg_slot_secondary, primary_hash, i, *steg, esid, stabl;
2174	HPTE *  hpte;
2175	struct mm_struct * mm;
2176	pte_t  *ptep = NULL;
2177	void * pgdir;
2178
2179	c = inchar();
2180	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2181		termch = c;
2182	scanhex((void *)&ea);
2183
2184	if ((ea >= KRANGE_START) && (ea <= (KRANGE_START + (1UL<<60)))) {
2185		ptep = 0;
2186		vsid = get_kernel_vsid(ea);
2187		va = ( vsid << 28 ) | ( ea & 0x0fffffff );
2188	} else {
2189		// if in vmalloc range, use the vmalloc page directory
2190		if ( ( ea >= VMALLOC_START ) && ( ea <= VMALLOC_END ) ) {
2191			mm = &init_mm;
2192			vsid = get_kernel_vsid( ea );
2193		}
2194		// if in ioremap range, use the ioremap page directory
2195		else if ( ( ea >= IMALLOC_START ) && ( ea <= IMALLOC_END ) ) {
2196			mm = &ioremap_mm;
2197			vsid = get_kernel_vsid( ea );
2198		}
2199		// if in user range, use the current task's page directory
2200		else if ( ( ea >= USER_START ) && ( ea <= USER_END ) ) {
2201			mm = current->mm;
2202			vsid = get_vsid(mm->context, ea );
2203		}
2204		pgdir = mm->pgd;
2205		va = ( vsid << 28 ) | ( ea & 0x0fffffff );
2206		ptep = find_linux_pte( pgdir, ea );
2207	}
2208
2209	vpn = ((vsid << 28) | (((ea) & 0xFFFF000))) >> 12;
2210	page = vpn & 0xffff;
2211	esid = (ea >> 28)  & 0xFFFFFFFFF;
2212
2213  // Search the primary group for an available slot
2214	primary_hash = ( vsid & 0x7fffffffff ) ^ page;
2215	hpteg_slot_primary = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
2216	hpteg_slot_secondary = ( ~primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
2217
2218	printf("ea             : %.16lx\n", ea);
2219	printf("esid           : %.16lx\n", esid);
2220	printf("vsid           : %.16lx\n", vsid);
2221
2222	printf("\nSoftware Page Table\n-------------------\n");
2223	printf("ptep           : %.16lx\n", ((unsigned long *)ptep));
2224	if(ptep) {
2225		printf("*ptep          : %.16lx\n", *((unsigned long *)ptep));
2226	}
2227
2228	hpte  = htab_data.htab  + hpteg_slot_primary;
2229	printf("\nHardware Page Table\n-------------------\n");
2230	printf("htab base      : %.16lx\n", htab_data.htab);
2231	printf("slot primary   : %.16lx\n", hpteg_slot_primary);
2232	printf("slot secondary : %.16lx\n", hpteg_slot_secondary);
2233	printf("\nPrimary Group\n");
2234	for (i=0; i<8; ++i) {
2235		if ( hpte->dw0.dw0.v != 0 ) {
2236			printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1);
2237			printf("          vsid: %.13lx   api: %.2lx  hash: %.1lx\n",
2238			       (hpte->dw0.dw0.avpn)>>5,
2239			       (hpte->dw0.dw0.avpn) & 0x1f,
2240			       (hpte->dw0.dw0.h));
2241			printf("          rpn: %.13lx \n", (hpte->dw1.dw1.rpn));
2242			printf("           pp: %.1lx \n",
2243			       ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp));
2244			printf("        wimgn: %.2lx  reference: %.1lx  change: %.1lx\n",
2245			       ((hpte->dw1.dw1.w)<<4)|
2246			       ((hpte->dw1.dw1.i)<<3)|
2247			       ((hpte->dw1.dw1.m)<<2)|
2248			       ((hpte->dw1.dw1.g)<<1)|
2249			       ((hpte->dw1.dw1.n)<<0),
2250			       hpte->dw1.dw1.r, hpte->dw1.dw1.c);
2251		}
2252		hpte++;
2253	}
2254
2255	printf("\nSecondary Group\n");
2256	// Search the secondary group
2257	hpte  = htab_data.htab  + hpteg_slot_secondary;
2258	for (i=0; i<8; ++i) {
2259		if(hpte->dw0.dw0.v) {
2260			printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1);
2261			printf("          vsid: %.13lx   api: %.2lx  hash: %.1lx\n",
2262			       (hpte->dw0.dw0.avpn)>>5,
2263			       (hpte->dw0.dw0.avpn) & 0x1f,
2264			       (hpte->dw0.dw0.h));
2265			printf("          rpn: %.13lx \n", (hpte->dw1.dw1.rpn));
2266			printf("           pp: %.1lx \n",
2267			       ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp));
2268			printf("        wimgn: %.2lx  reference: %.1lx  change: %.1lx\n",
2269			       ((hpte->dw1.dw1.w)<<4)|
2270			       ((hpte->dw1.dw1.i)<<3)|
2271			       ((hpte->dw1.dw1.m)<<2)|
2272			       ((hpte->dw1.dw1.g)<<1)|
2273			       ((hpte->dw1.dw1.n)<<0),
2274			       hpte->dw1.dw1.r, hpte->dw1.dw1.c);
2275		}
2276		hpte++;
2277	}
2278
2279	printf("\nHardware Segment Table\n-----------------------\n");
2280	stabl = (unsigned long)(KERNELBASE+(_ASR&0xFFFFFFFFFFFFFFFE));
2281	steg = (unsigned long *)((stabl) | ((esid & 0x1f) << 7));
2282
2283	printf("stab base      : %.16lx\n", stabl);
2284	printf("slot           : %.16lx\n", steg);
2285
2286	for (i=0; i<8; ++i) {
2287		printf("%d: (ste) %.16lx %.16lx\n", i,
2288		       *((unsigned long *)(steg+i*2)),*((unsigned long *)(steg+i*2+1)) );
2289	}
2290}
2291
2292void mem_check()
2293{
2294	unsigned long htab_size_bytes;
2295	unsigned long htab_end;
2296	unsigned long last_rpn;
2297	HPTE *hpte1, *hpte2;
2298
2299	htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG
2300	htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
2301	// last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT;
2302	last_rpn = 0xfffff;
2303
2304	printf("\nHardware Page Table Check\n-------------------\n");
2305	printf("htab base      : %.16lx\n", htab_data.htab);
2306	printf("htab size      : %.16lx\n", htab_size_bytes);
2307
2308	for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
2309		if ( hpte1->dw0.dw0.v != 0 ) {
2310			if ( hpte1->dw1.dw1.rpn <= last_rpn ) {
2311				for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) {
2312					if ( hpte2->dw0.dw0.v != 0 ) {
2313						if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) {
2314							printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
2315							printf("   hpte1: %16.16lx  *hpte1: %16.16lx %16.16lx\n",
2316							       hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2317							printf("   hpte2: %16.16lx  *hpte2: %16.16lx %16.16lx\n",
2318							       hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1);
2319						}
2320					}
2321				}
2322			} else {
2323				printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
2324				printf("   hpte: %16.16lx  *hpte: %16.16lx %16.16lx\n",
2325				       hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2326			}
2327		}
2328	}
2329	printf("\nDone -------------------\n");
2330}
2331
2332void mem_find_real()
2333{
2334	unsigned long htab_size_bytes;
2335	unsigned long htab_end;
2336	unsigned long last_rpn;
2337	HPTE *hpte1;
2338	unsigned long pa, rpn;
2339	int c;
2340
2341	c = inchar();
2342	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2343		termch = c;
2344	scanhex((void *)&pa);
2345	rpn = pa >> 12;
2346
2347	htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG
2348	htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
2349	// last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT;
2350	last_rpn = 0xfffff;
2351
2352	printf("\nMem Find RPN\n-------------------\n");
2353	printf("htab base      : %.16lx\n", htab_data.htab);
2354	printf("htab size      : %.16lx\n", htab_size_bytes);
2355
2356	for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
2357		if ( hpte1->dw0.dw0.v != 0 ) {
2358			if ( hpte1->dw1.dw1.rpn == rpn ) {
2359				printf(" Found rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
2360				printf("      hpte: %16.16lx  *hpte1: %16.16lx %16.16lx\n",
2361				       hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2362			}
2363		}
2364	}
2365	printf("\nDone -------------------\n");
2366}
2367
2368void mem_find_vsid()
2369{
2370	unsigned long htab_size_bytes;
2371	unsigned long htab_end;
2372	HPTE *hpte1;
2373	unsigned long vsid;
2374	int c;
2375
2376	c = inchar();
2377	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2378		termch = c;
2379	scanhex((void *)&vsid);
2380
2381	htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG
2382	htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
2383
2384	printf("\nMem Find VSID\n-------------------\n");
2385	printf("htab base      : %.16lx\n", htab_data.htab);
2386	printf("htab size      : %.16lx\n", htab_size_bytes);
2387
2388	for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
2389		if ( hpte1->dw0.dw0.v != 0 ) {
2390			if ( ((hpte1->dw0.dw0.avpn)>>5) == vsid ) {
2391				printf(" Found vsid: %.16lx \n", ((hpte1->dw0.dw0.avpn) >> 5));
2392				printf("       hpte: %16.16lx  *hpte1: %16.16lx %16.16lx\n",
2393				       hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2394			}
2395		}
2396	}
2397	printf("\nDone -------------------\n");
2398}
2399
2400void mem_map_check_slab()
2401{
2402	int i, slab_count;
2403
2404	i = max_mapnr;
2405	slab_count = 0;
2406
2407	while (i-- > 0)  {
2408		if (PageSlab(mem_map+i)){
2409			printf(" slab entry - mem_map entry =%p  \n", mem_map+i);
2410			slab_count ++;
2411		}
2412	}
2413
2414	printf(" count of pages for slab = %d \n", slab_count);
2415}
2416
2417void mem_map_lock_pages()
2418{
2419	int i, lock_count;
2420
2421	i = max_mapnr;
2422	lock_count = 0;
2423
2424	while (i-- > 0)  {
2425		if (PageLocked(mem_map+i)){
2426			printf(" locked entry - mem_map entry =%p  \n", mem_map+i);
2427			lock_count ++;
2428		}
2429	}
2430
2431	printf(" count of locked pages = %d \n", lock_count);
2432}
2433
2434void mem_check_dup_rpn ()
2435{
2436	unsigned long htab_size_bytes;
2437	unsigned long htab_end;
2438	unsigned long last_rpn;
2439	HPTE *hpte1, *hpte2;
2440	int dup_count;
2441	struct task_struct *p;
2442	unsigned long kernel_vsid_c0,kernel_vsid_c1,kernel_vsid_c2,kernel_vsid_c3;
2443	unsigned long kernel_vsid_c4,kernel_vsid_c5,kernel_vsid_d,kernel_vsid_e;
2444	unsigned long kernel_vsid_f;
2445	unsigned long vsid0,vsid1,vsidB,vsid2;
2446
2447	htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG
2448	htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
2449	// last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT;
2450	last_rpn = 0xfffff;
2451
2452	printf("\nHardware Page Table Check\n-------------------\n");
2453	printf("htab base      : %.16lx\n", htab_data.htab);
2454	printf("htab size      : %.16lx\n", htab_size_bytes);
2455
2456
2457	for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
2458		if ( hpte1->dw0.dw0.v != 0 ) {
2459			if ( hpte1->dw1.dw1.rpn <= last_rpn ) {
2460				dup_count = 0;
2461				for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) {
2462					if ( hpte2->dw0.dw0.v != 0 ) {
2463						if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) {
2464							dup_count++;
2465						}
2466					}
2467				}
2468				if(dup_count > 5) {
2469					printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
2470					printf("    mem map array entry %p count = %d \n",
2471					       (mem_map+(hpte1->dw1.dw1.rpn)), (mem_map+(hpte1->dw1.dw1.rpn))->count);
2472					for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) {
2473						if ( hpte2->dw0.dw0.v != 0 ) {
2474							if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) {
2475								printf("   hpte2: %16.16lx  *hpte2: %16.16lx %16.16lx\n",
2476								       hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1);
2477							}
2478						}
2479					}
2480				}
2481			} else {
2482				printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
2483				printf("   hpte: %16.16lx  *hpte: %16.16lx %16.16lx\n",
2484				       hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
2485			}
2486		}
2487		if (xmon_interrupted())
2488			return;
2489	}
2490
2491
2492
2493	// print the kernel vsids
2494	kernel_vsid_c0 =  get_kernel_vsid(0xC000000000000000);
2495	kernel_vsid_c1 =  get_kernel_vsid(0xC000000010000000);
2496	kernel_vsid_c2 =  get_kernel_vsid(0xC000000020000000);
2497	kernel_vsid_c3 =  get_kernel_vsid(0xC000000030000000);
2498	kernel_vsid_c4 =  get_kernel_vsid(0xC000000040000000);
2499	kernel_vsid_c5 =  get_kernel_vsid(0xC000000050000000);
2500	kernel_vsid_d  =  get_kernel_vsid(0xD000000000000000);
2501	kernel_vsid_e  =  get_kernel_vsid(0xE000000000000000);
2502	kernel_vsid_f  =  get_kernel_vsid(0xF000000000000000);
2503
2504	printf(" kernel vsid -  seg c0  = %lx\n",  kernel_vsid_c0 );
2505	printf(" kernel vsid -  seg c1  = %lx\n",  kernel_vsid_c1 );
2506	printf(" kernel vsid -  seg c2  = %lx\n",  kernel_vsid_c2 );
2507	printf(" kernel vsid -  seg c3  = %lx\n",  kernel_vsid_c3 );
2508	printf(" kernel vsid -  seg c4  = %lx\n",  kernel_vsid_c4 );
2509	printf(" kernel vsid -  seg c5  = %lx\n",  kernel_vsid_c5 );
2510	printf(" kernel vsid -  seg d   = %lx\n",  kernel_vsid_d );
2511	printf(" kernel vsid -  seg e   = %lx\n",  kernel_vsid_e );
2512	printf(" kernel vsid -  seg f   = %lx\n",  kernel_vsid_f );
2513
2514
2515  // print a list of valid vsids for the tasks
2516	read_lock(&tasklist_lock);
2517	for_each_task(p)
2518		if(p->mm) {
2519			struct mm_struct *mm = p->mm;
2520			printf(" task = %p  mm =  %lx  pgd   %lx\n",
2521			       p, mm, mm->pgd);
2522			vsid0 = get_vsid( mm->context, 0 );
2523			vsid1 = get_vsid( mm->context, 0x10000000 );
2524			vsid2 = get_vsid( mm->context, 0x20000000 );
2525			vsidB = get_vsid( mm->context, 0xB0000000 );
2526			printf("            context = %lx  vsid seg 0  = %lx\n",  mm->context, vsid0 );
2527			printf("                           vsid seg 1  = %lx\n",  vsid1 );
2528			printf("                           vsid seg 2  = %lx\n",  vsid2 );
2529			printf("                           vsid seg 2  = %lx\n",  vsidB );
2530
2531			printf("\n");
2532		};
2533	read_unlock(&tasklist_lock);
2534
2535	printf("\nDone -------------------\n");
2536}
2537
2538
2539
2540void mem_check_pagetable_vsids ()
2541{
2542	unsigned long htab_size_bytes;
2543	unsigned long htab_end;
2544	unsigned long last_rpn;
2545	struct task_struct *p;
2546	unsigned long valid_table_count,invalid_table_count,bogus_rpn_count;
2547	int found;
2548	unsigned long user_address_table_count,kernel_page_table_count;
2549	unsigned long pt_vsid;
2550	HPTE *hpte1;
2551
2552
2553	htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG
2554	htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
2555	// last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT;
2556	last_rpn = 0xfffff;
2557
2558	printf("\nHardware Page Table Check\n-------------------\n");
2559	printf("htab base      : %.16lx\n", htab_data.htab);
2560	printf("htab size      : %.16lx\n", htab_size_bytes);
2561
2562	valid_table_count = 0;
2563	invalid_table_count = 0;
2564	bogus_rpn_count = 0;
2565	user_address_table_count = 0;
2566	kernel_page_table_count = 0;
2567	for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
2568		if ( hpte1->dw0.dw0.v != 0 ) {
2569			valid_table_count++;
2570			if ( hpte1->dw1.dw1.rpn <= last_rpn ) {
2571				pt_vsid =  (hpte1->dw0.dw0.avpn) >> 5;
2572				if ((pt_vsid == get_kernel_vsid(0xC000000000000000)) |
2573				    (pt_vsid == get_kernel_vsid(0xC000000010000000)) |
2574				    (pt_vsid == get_kernel_vsid(0xC000000020000000)) |
2575				    (pt_vsid == get_kernel_vsid(0xC000000030000000)) |
2576				    (pt_vsid == get_kernel_vsid(0xC000000040000000)) |
2577				    (pt_vsid == get_kernel_vsid(0xC000000050000000)) |
2578				    (pt_vsid == get_kernel_vsid(0xD000000000000000)) |
2579				    (pt_vsid == get_kernel_vsid(0xE000000000000000)) |
2580				    (pt_vsid == get_kernel_vsid(0xF000000000000000)) ) {
2581					kernel_page_table_count ++;
2582				} else {
2583					read_lock(&tasklist_lock);
2584					found = 0;
2585					for_each_task(p) {
2586						if(p->mm && (found == 0)) {
2587							struct mm_struct *mm = p->mm;
2588
2589							if ((pt_vsid == get_vsid( mm->context, 0 )) |
2590							    (pt_vsid == get_vsid( mm->context, 0x10000000 )) |
2591							    (pt_vsid == get_vsid( mm->context, 0x20000000 )) |
2592							    (pt_vsid == get_vsid( mm->context, 0x30000000 )) |
2593							    (pt_vsid == get_vsid( mm->context, 0x40000000 )) |
2594							    (pt_vsid == get_vsid( mm->context, 0x50000000 )) |
2595							    (pt_vsid == get_vsid( mm->context, 0x60000000 )) |
2596							    (pt_vsid == get_vsid( mm->context, 0x70000000 )) |
2597							    (pt_vsid == get_vsid( mm->context, 0x80000000 )) |
2598							    (pt_vsid == get_vsid( mm->context, 0x90000000 )) |
2599							    (pt_vsid == get_vsid( mm->context, 0xA0000000 )) |
2600							    (pt_vsid == get_vsid( mm->context, 0xB0000000 ))) {
2601								user_address_table_count ++;
2602								found = 1;
2603							}
2604						}
2605					}
2606					read_unlock(&tasklist_lock);
2607					if (found == 0)
2608					{
2609						printf(" vsid not found vsid = %lx, hpte = %p  \n",
2610						       pt_vsid,hpte1);
2611						printf("    rpn in entry = %lx \n", hpte1->dw1.dw1.rpn);
2612						printf("    mem map address = %lx  \n", mem_map + (hpte1->dw1.dw1.rpn));
2613
2614					} else //  found
2615					{
2616					}
2617
2618				}  // good rpn
2619
2620			} else {
2621				bogus_rpn_count ++;
2622			}
2623		} else {
2624			invalid_table_count++;
2625		}
2626	}
2627
2628
2629	printf(" page table valid counts - valid entries = %lx  invalid entries =  %lx \n",
2630	       valid_table_count, invalid_table_count);
2631
2632	printf("  bogus rpn entries ( probably io) = %lx \n", bogus_rpn_count);
2633
2634
2635
2636	printf(" page table counts - kernel entries = %lx  user entries =  %lx \n",
2637	       kernel_page_table_count, user_address_table_count);
2638
2639	printf("\nDone -------------------\n");
2640
2641}
2642
2643static void debug_trace(void) {
2644        unsigned long val, cmd, on;
2645
2646	cmd = skipbl();
2647	if (cmd == '\n') {
2648		/* show current state */
2649		unsigned long i;
2650		printf("naca->debug_switch = 0x%lx\n", naca->debug_switch);
2651		for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) {
2652			on = PPCDBG_BITVAL(i) & naca->debug_switch;
2653			printf("%02x %s %12s   ", i, on ? "on " : "off",  trace_names[i] ? trace_names[i] : "");
2654			if (((i+1) % 3) == 0)
2655				printf("\n");
2656		}
2657		printf("\n");
2658		return;
2659	}
2660	while (cmd != '\n') {
2661		on = 1;	/* default if no sign given */
2662		while (cmd == '+' || cmd == '-') {
2663			on = (cmd == '+');
2664			cmd = inchar();
2665			if (cmd == ' ' || cmd == '\n') {  /* Turn on or off based on + or - */
2666				naca->debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE;
2667				printf("Setting all values to %s...\n", on ? "on" : "off");
2668				if (cmd == '\n') return;
2669				else cmd = skipbl();
2670			}
2671			else
2672				termch = cmd;
2673		}
2674		termch = cmd;	/* not +/- ... let scanhex see it */
2675		scanhex((void *)&val);
2676		if (val >= 64) {
2677			printf("Value %x out of range:\n", val);
2678			return;
2679		}
2680		if (on) {
2681			naca->debug_switch |= PPCDBG_BITVAL(val);
2682			printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2683		} else {
2684			naca->debug_switch &= ~PPCDBG_BITVAL(val);
2685			printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2686		}
2687		cmd = skipbl();
2688	}
2689}
2690