1/*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_FREE_COPYRIGHT@
30 */
31/*
32 * @APPLE_FREE_COPYRIGHT@
33 */
34
35/*
36 *	Author: Bill Angell, Apple
37 *	Date:	6/97
38 *
39 * exceptions and certain C functions write into a trace table which
40 * can be examined via the machine 'lt' command under kdb
41 */
42
43
44#include <string.h>			/* For strcpy() */
45#include <mach/boolean.h>
46#include <machine/db_machdep.h>
47
48#include <ddb/db_access.h>
49#include <ddb/db_lex.h>
50#include <ddb/db_output.h>
51#include <ddb/db_command.h>
52#include <ddb/db_sym.h>
53#include <ddb/db_task_thread.h>
54#include <ddb/db_command.h>		/* For db_option() */
55#include <ddb/db_examine.h>
56#include <ddb/db_expr.h>
57#include <kern/thread.h>
58#include <kern/task.h>
59#include <mach/vm_param.h>
60#include <mach/kmod.h>
61#include <ppc/Firmware.h>
62#include <ppc/low_trace.h>
63#include <ppc/db_low_trace.h>
64#include <ppc/mappings.h>
65#include <ppc/pmap.h>
66#include <ppc/mem.h>
67#include <ppc/savearea.h>
68#include <ppc/vmachmon.h>
69
70void db_dumppca(unsigned int ptegindex);
71void db_dumpmapping(struct mapping *mp); 					/* Dump out a mapping */
72extern kmod_info_t *kmod;									/* Find the kmods */
73
74db_addr_t	db_low_trace_prev = 0;
75
76/*
77 *		Print out the low level trace table:
78 *
79 *		Displays the entry and 15 before it in newest to oldest order
80 *
81 *		lt [entaddr]
82
83 *		If entaddr is omitted, it starts with the most current
84 *		If entaddr = 0, it starts with the most current and does the whole table
85 */
86void
87db_low_trace(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif)
88{
89	int		c, i;
90	unsigned int tempx, cnt;
91	unsigned int xTraceCurr, xTraceStart, xTraceEnd, cxltr;
92	db_addr_t	next_addr;
93	LowTraceRecord xltr;
94	unsigned char cmark;
95	addr64_t xxltr;
96
97	cnt = 16;													/* Default to 16 entries */
98
99	xTraceCurr = trcWork.traceCurr;								/* Transfer current pointer */
100	xTraceStart = trcWork.traceStart;							/* Transfer start of table */
101	xTraceEnd = trcWork.traceEnd;								/* Transfer end of table */
102
103	if(addr == -1) cnt = 0x7FFFFFFF;							/* Max the count */
104
105	if(!addr || (addr == -1)) {
106		addr=xTraceCurr-sizeof(LowTraceRecord);					/* Start at the newest */
107		if((unsigned int)addr<xTraceStart) addr=xTraceEnd-sizeof(LowTraceRecord);	/* Wrap low back to high */
108	}
109
110	if((unsigned int)addr<xTraceStart||(unsigned int)addr>=xTraceEnd) {	/* In the table? */
111		db_printf("address not in low memory trace table\n");	/* Tell the fool */
112		return;													/* Leave... */
113	}
114
115	if((unsigned int)addr&0x0000007F) {							/* Proper alignment? */
116		db_printf("address not aligned on trace entry boundary (0x80)\n");	/* Tell 'em */
117		return;													/* Leave... */
118	}
119
120	xxltr = addr;												/* Set the start */
121	cxltr = ((xTraceCurr == xTraceStart ? xTraceEnd : xTraceCurr) - sizeof(LowTraceRecord));	/* Get address of newest entry */
122
123	db_low_trace_prev = addr;									/* Starting point */
124
125	for(i=0; i < cnt; i++) {									/* Dump the 16 (or all) entries */
126
127		ReadReal((addr64_t)xxltr, (unsigned int *)&xltr);					/* Get the first half */
128		ReadReal((addr64_t)xxltr + 32, &(((unsigned int *)&xltr)[8]));		/* Get the second half */
129		ReadReal((addr64_t)xxltr + 64, &(((unsigned int *)&xltr)[16]));		/* Get the second half */
130		ReadReal((addr64_t)xxltr + 96, &(((unsigned int *)&xltr)[24]));		/* Get the second half */
131
132		db_printf("\n%s%08llX  %1X  %08X %08X - %04X", (xxltr != cxltr ? " " : "*"),
133			xxltr,
134			(xltr.LTR_cpu & 0xFF), xltr.LTR_timeHi, xltr.LTR_timeLo,
135			(xltr.LTR_excpt & 0x8000 ? 0xFFFF : xltr.LTR_excpt * 64));	/* Print the first line */
136
137		if(xltr.LTR_cpu & 0xFF00) db_printf(", sflgs = %02X\n", ((xltr.LTR_cpu >> 8) & 0xFF));
138		else db_printf("\n");
139
140		db_printf("              DAR/DSR/CR: %016llX %08X %08X\n", xltr.LTR_dar, xltr.LTR_dsisr, xltr.LTR_cr);
141
142		db_printf("                SRR0/SRR1 %016llX %016llX\n",  xltr.LTR_srr0, xltr.LTR_srr1);
143		db_printf("                LR/CTR    %016llX %016llX\n",  xltr.LTR_lr, xltr.LTR_ctr);
144
145		db_printf("                R0/R1/R2  %016llX %016llX %016llX\n", xltr.LTR_r0, xltr.LTR_r1, xltr.LTR_r2);
146		db_printf("                R3/R4/R5  %016llX %016llX %016llX\n", xltr.LTR_r3, xltr.LTR_r4, xltr.LTR_r5);
147		db_printf("              R6/sv/rsv   %016llX %016llX %08X\n", xltr.LTR_r6, xltr.LTR_save, xltr.LTR_rsvd0);
148
149		if((cnt != 16) && (xxltr == xTraceCurr)) break;			/* If whole table dump, exit when we hit start again... */
150
151		xxltr-=sizeof(LowTraceRecord);							/* Back it on up */
152		if(xxltr<xTraceStart)
153			xxltr=(xTraceEnd-sizeof(LowTraceRecord));			/* Wrap low back to high */
154
155	}
156	db_next = (db_expr_t)(xxltr);
157}
158
159
160/*
161 *		Print out 256 bytes
162 *
163 *
164 *		dl [entaddr]
165 */
166void
167db_display_long(db_expr_t addr, __unused boolean_t have_addr,
168		db_expr_t count, char * modif)
169{
170	int				i;
171
172	for(i=0; i<8; i++) {									/* Print 256 bytes */
173		db_printf("%016llX   %08X %08X %08X %08X  %08X %08X %08X %08X\n", addr,	/* Print a line */
174			((unsigned long *)addr)[0], ((unsigned long *)addr)[1], ((unsigned long *)addr)[2], ((unsigned long *)addr)[3],
175			((unsigned long *)addr)[4], ((unsigned long *)addr)[5], ((unsigned long *)addr)[6], ((unsigned long *)addr)[7]);
176		addr=(db_expr_t)(addr+0x00000020);					/* Point to next address */
177	}
178	db_next = addr;
179
180
181}
182
183unsigned char xtran[256] = {
184/*  x0   x1   x2   x3   x4   x5   x6   x7   x8   x9   xA   xB   xC   xD   xE   xF   	   */
185	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* 0x */
186	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* 1x */
187	' ', '!', '"', '#', '$', '%', '&',0x27, '(', ')', '*', '+', ',', '-', '.', '/',  /* 2x */
188	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',  /* 3x */
189	'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',  /* 4x */
190	'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',0x5C, ']', '^', '_',  /* 5x */
191	'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',  /* 6x */
192	'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '.',  /* 7x */
193	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* 8x */
194	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* 9x */
195	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* Ax */
196	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* Bx */
197	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* Cx */
198	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* Dx */
199	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* Ex */
200	'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',  /* Fx */
201};
202
203/*
204 *		Print out 256 bytes in characters
205 *
206 *
207 *		dc [entaddr]
208 */
209void
210db_display_char(db_expr_t addr, boolean_t have_addr, db_expr_t count,
211		char * modif)
212{
213
214	int				i, j, k;
215	unsigned char xlt[256], *xaddr;
216
217	xaddr = (unsigned char *)addr;
218
219
220	for(i = 0; i < 8; i++) {								/* Print 256 bytes */
221		j = 0;
222		for(k = 0; k < 32; k++) {
223			xlt[j] = xtran[*xaddr];
224			xaddr++;
225			j++;
226			if((k & 3) == 3) {
227				xlt[j] = ' ';
228				j++;
229			}
230		}
231		xlt[j] = 0;
232
233		db_printf("%016llX   %s\n", (addr64_t)(xaddr - 32), xlt);	/* Print a line */
234	}
235
236	db_next = (db_expr_t)xaddr;
237
238
239}
240
241/*
242 *		Print out 256 bytes of real storage
243 *
244 *		Displays the entry and 15 before it in newest to oldest order
245 *
246 *		dr [entaddr]
247 */
248void
249db_display_real(db_expr_t addr, boolean_t have_addr, db_expr_t count,
250		char *modif)
251{
252	int				i;
253	unsigned int xbuf[8];
254
255	for(i=0; i<8; i++) {									/* Print 256 bytes */
256		ReadReal(addr, &xbuf[0]);							/* Get the real storage data */
257		db_printf("%016llX   %08X %08X %08X %08X  %08X %08X %08X %08X\n", addr,	/* Print a line */
258			xbuf[0], xbuf[1], xbuf[2], xbuf[3],
259			xbuf[4], xbuf[5], xbuf[6], xbuf[7]);
260		addr = addr + 0x00000020;							/* Point to next address */
261	}
262	db_next = addr;
263}
264
265unsigned int	dvspace = 0;
266
267/*
268 *		Print out virtual to real translation information
269 *
270 *
271 *		dm vaddr [space] (defaults to last entered)
272 */
273void
274db_display_mappings(db_expr_t addr, boolean_t have_addr, db_expr_t count,
275		    char *modif)
276{
277	db_expr_t	xspace;
278	pmap_t			pmap;
279	addr64_t		lnextva;
280
281	mapping_t	*mp;
282
283	if (db_expression(&xspace)) {							/* Get the address space requested */
284		if(xspace >= maxAdrSp) {
285			db_printf("requested address space (%llX) larger than max (%X)\n", xspace, maxAdrSp - 1);
286			return;
287		}
288		dvspace = xspace;									/* Get the space or set default */
289	}
290
291	db_printf("mapping information for %016llX in space %8X:\n", addr, dvspace);
292
293	pmap = pmapTrans[dvspace].pmapVAddr;					/* Find the pmap address */
294	if(!pmap) {												/* The pmap is not in use */
295		db_printf("The space %X is not assigned to a pmap\n", dvspace);	/* Say we are wrong */
296		return;
297	}
298
299	mp = hw_find_map(pmap, (addr64_t)addr, &lnextva);		/* Try to find the mapping for this address */
300	if((unsigned int)mp == mapRtBadLk) {					/* Did we lock up ok? */
301		db_printf("Timeout locking physical entry for virtual address %016ll8X\n", addr);
302		return;
303	}
304
305	if(!mp) {												/* Did we find one? */
306		db_printf("Not mapped\n");
307		return;												/* Didn't find any, return FALSE... */
308	}
309
310	mapping_drop_busy(mp);									/* The mapping shouldn't be changing */
311
312	db_dumpmapping(mp);										/* Dump it all out */
313
314	/* Tell them we did it */
315}
316
317/*
318 *		Print out hash table data
319 *
320 *
321 *		dh vaddr [space] (defaults to last entered)
322 */
323void
324db_display_hash(db_expr_t addr, boolean_t have_addr, db_expr_t count,
325		char *modif)
326{
327	db_expr_t		xspace;
328	unsigned int	seg, vsid, ptegindex, htsize;
329	pmap_t			pmap;
330	addr64_t		lnextva, llva, vpn, esid;
331	uint64_t		hash;
332	int 			s4bit;
333
334	llva = (addr64_t)((unsigned int)addr);					/* Make sure we are 64-bit now */
335
336	s4bit = !((PerProcTable[0].ppe_vaddr->pf.Available & pf64Bit) == 0);	/* Are we a big guy? */
337	if (db_expression(&xspace)) {							/* Get the address space requested */
338		if(xspace >= maxAdrSp) {
339			db_printf("requested address space (%llX) larger than max (%X)\n", xspace, maxAdrSp - 1);
340			return;
341		}
342		dvspace = xspace;									/* Get the space or set default */
343	}
344
345	pmap = pmapTrans[dvspace].pmapVAddr;					/* Find the pmap address */
346	if(!pmap) {												/* The pmap is not in use */
347		db_printf("The space %X is not assigned to a pmap\n", dvspace);	/* Say we are wrong */
348		return;
349	}
350
351	hash = (uint64_t)pmap->space | ((uint64_t)pmap->space << maxAdrSpb) | ((uint64_t)pmap->space << (2 * maxAdrSpb));	/* Get hash value */
352	hash = hash & 0x0000001FFFFFFFFF;						/* Make sure we stay within supported ranges */
353
354	esid = ((llva >> 14) & -maxAdrSp) ^ hash;				/* Get ESID */
355	llva = ((llva >> 12) & 0xFFFF) ^ esid;					/* Get index into hash table */
356
357	if(s4bit) htsize = hash_table_size >> 7;				/* Get number of entries in hash table for 64-bit */
358	else htsize = hash_table_size >> 6;						/* get number of entries in hash table for 32-bit */
359
360	ptegindex = llva & (htsize - 1);						/* Get the index to the pteg and pca */
361	db_dumppca(ptegindex);									/* dump the info */
362
363	/* Tell them we did it */
364}
365
366/*
367 *		Displays all of the in-use pmaps in the system.
368 *
369  *		dp
370 */
371void
372db_display_pmap(db_expr_t addr, boolean_t have_addr, db_expr_t count,
373		char *modif)
374{
375	pmap_t			pmap;
376	int i;
377	unsigned int v0, v1, st0, st1;
378
379	pmap = (pmap_t)addr;
380	if(!have_addr) pmap = kernel_pmap;						/* Start at the beginning */
381
382	db_printf("PMAP     (real)            Next     Prev     Space    Flags    Ref      spaceNum Resident Wired\n");
383//	           xxxxxxxx rrrrrrrrrrrrrrrr  xxxxxxxx pppppppp ssssssss cccccccc vvvvvvvv nnnnnnnn rrrrrrrr wwwwwwwww
384	while(1) {												/* Do them all */
385		db_printf("%08X %016llX  %08X %08X %08X %08X %08X %08X %08X %08X\n",
386			pmap, (addr64_t)pmap ^ pmap->pmapvr,
387			pmap->pmap_link.next,  pmap->pmap_link.prev,
388			pmap->space, pmap->pmapFlags, pmap->ref_count, pmap->spaceNum,
389			pmap->stats.resident_count,
390			pmap->stats.wired_count);
391
392		db_printf("lists = %d, rand = %08X, visits = %016llX, searches = %08X\n",
393			pmap->pmapCurLists, pmap->pmapRandNum,
394			pmap->pmapSearchVisits, pmap->pmapSearchCnt);
395
396		db_printf("cctl = %08X, SCSubTag = %016llX\n",
397			pmap->pmapCCtl, pmap->pmapSCSubTag);
398
399		for(i = 0; i < 16; i +=2) {
400			v0 = (pmap->pmapCCtl >> (31 - i) & 1);			/* Get high order bit */
401			v1 = (pmap->pmapCCtl >> (30 - i) & 1);			/* Get high order bit */
402			st0 = (pmap->pmapSCSubTag >> (60 - (4 * i))) & 0xF;	/* Get the sub-tag */
403			st1 = (pmap->pmapSCSubTag >> (56 - (4 * i))) & 0xF;	/* Get the sub-tag */
404
405			db_printf("         %01X %01X %016llX/%016llX  %01X %01X %016llX/%016llX\n",
406				v0, st0, pmap->pmapSegCache[i].sgcESID, pmap->pmapSegCache[i].sgcVSID,
407				v1, st1, pmap->pmapSegCache[i+1].sgcESID, pmap->pmapSegCache[i+1].sgcVSID);
408		}
409
410		db_printf("\n");
411		if(have_addr) break;								/* Do only one if address supplied */
412		pmap = (pmap_t)pmap->pmap_link.next;				/* Skip to the next */
413		if(pmap == kernel_pmap) break;						/* We've wrapped, we're done */
414	}
415}
416
417
418/*
419 *		Checks the pmap skip lists
420 *
421 *
422 *		cp pmap
423 */
424void
425db_check_pmaps(db_expr_t addr, boolean_t have_addr, db_expr_t count,
426	       char *modif)
427{
428	int				i;
429	unsigned int ret;
430	uint64_t dumpa[32];
431	pmap_t pmap;
432
433	pmap = (pmap_t)addr;
434	if(!have_addr) pmap = kernel_pmap;						/* If no map supplied, start with kernel */
435
436	while(1) {												/* Do them all */
437		ret = mapSkipListVerifyC(pmap, &dumpa);							/* Check out the map */
438		if(!ret) db_printf("Skiplists verified ok, pmap = %08X\n", pmap);
439		else {
440			db_printf("Verification failure at %08X, pmap = %08X\n", ret, pmap);
441			for(i = 0; i < 32; i += 4) {
442				db_printf("R%02d  %016llX  %016llX  %016llX  %016llX\n", i,
443					dumpa[i], dumpa[i + 1], dumpa[i + 2], dumpa[i + 3]);
444			}
445		}
446		if(have_addr) break;								/* Do only one if address supplied */
447		pmap = (pmap_t)pmap->pmap_link.next;				/* Skip to the next */
448		if(pmap == kernel_pmap) break;						/* We've wrapped, we're done */
449	}
450}
451
452
453/*
454 *		Displays iokit junk
455 *
456  *		di
457 */
458
459void db_piokjunk(void);
460
461void
462db_display_iokit(__unused db_expr_t addr, __unused boolean_t have_addr,
463		 __unused db_expr_t count, __unused char *modif)
464{
465	db_piokjunk();
466}
467
468/*
469 *		Prints out a mapping control block
470 *
471 */
472
473void db_dumpmapping(struct mapping *mp) { 					/* Dump out a mapping */
474
475	pmap_t pmap;
476	int i;
477
478	db_printf("Dump of mapping block: %08X,  pmap: %08X (%016llX)\n", mp, pmapTrans[mp->mpSpace].pmapVAddr,
479		pmapTrans[mp->mpSpace].pmapPAddr);			/* Header */
480	db_printf("              mpFlags: %08X\n", mp->mpFlags);
481	db_printf("              mpSpace: %04X\n", mp->mpSpace);
482	db_printf("              mpBSize: %04X\n", mp->u.mpBSize);
483	db_printf("                mpPte: %08X\n", mp->mpPte);
484	db_printf("              mpPAddr: %08X\n", mp->mpPAddr);
485	db_printf("              mpVAddr: %016llX\n", mp->mpVAddr);
486	db_printf("              mpAlias: %016llX\n", mp->mpAlias);
487	db_printf("             mpList00: %016llX\n", mp->mpList0);
488
489	for(i = 1; i < (mp->mpFlags & mpLists); i++) {			/* Dump out secondary physical skip lists */
490		db_printf("             mpList%02d: %016llX\n", i, mp->mpList[i - 1]);
491	}
492}
493
494/*
495 *		Prints out a PTEG and PCA
496 *
497 */
498
499void db_dumppca(unsigned int ptegindex) {
500
501	addr64_t pteg, pca, llva;
502	unsigned int xpteg[32], xpca[8], space, hash, pva, seg, api, va;
503	int i, s4bit;
504	unsigned long long llslot, llseg, llhash;
505
506	s4bit = !((PerProcTable[0].ppe_vaddr->pf.Available & pf64Bit) == 0);	/* Are we a big guy? */
507
508	pteg = hash_table_base + (ptegindex << 6);				/* Point to the PTEG */
509	if(s4bit) pteg = hash_table_base + (ptegindex << 7);	/* Point to the PTEG */
510	pca  = hash_table_base - ((ptegindex + 1) * 4);			/* Point to the PCA */
511	db_printf("PTEG = %016llX, PCA = %016llX (index = %08X)\n", pteg, pca, ptegindex);
512
513	ReadReal(pteg, &xpteg[0]);								/* Get first half of the pteg */
514	ReadReal(pteg + 0x20, &xpteg[8]);						/* Get second half of the pteg */
515	ReadReal(pca, &xpca[0]);								/* Get pca */
516
517	db_printf("PCA: free = %02X, steal = %02X, auto = %02X, misc = %02X\n",
518		((xpca[0] >> 24) & 255), ((xpca[0] >> 16) & 255), ((xpca[0] >> 8) & 255), xpca[0] & 255);
519
520	if(!s4bit) {											/* Little guy? */
521
522		for(i = 0; i < 16; i += 2) {						/* Step through pteg */
523			db_printf("%08X %08X - ", xpteg[i], xpteg[i + 1]);	/* Dump the pteg slot */
524
525			if(xpteg[i] & 0x80000000) db_printf("  valid - ");	/* Is it valid? */
526			else db_printf("invalid - ");					/* Nope, invalid */
527
528			space = (xpteg[i] >> 7) & (maxAdrSp - 1);		/* Extract the space */
529			hash = space | (space << maxAdrSpb) | (space << (2 * maxAdrSpb));	/* Get the hash */
530			pva =  ptegindex ^ hash;						/* Get part of the vaddr */
531			seg = (xpteg[i] >> 7) ^ hash;					/* Get the segment number */
532			api = (xpteg[i] & 0x3F);						/* Get the API */
533			va = ((seg << (28 - maxAdrSpb)) & 0xF0000000) | (api << 22) | ((pva << 12) & 0x003FF000);	/* Get the vaddr */
534			db_printf("va = %08X\n", va);
535		}
536	}
537	else {
538		ReadReal(pteg + 0x40, &xpteg[16]);					/* Get third half of the pteg */
539		ReadReal(pteg + 0x60, &xpteg[24]);					/* Get fourth half of the pteg */
540
541		for(i = 0; i < 32; i += 4) {						/* Step through pteg */
542			db_printf("%08X%08X %08X%08X - ", xpteg[i], xpteg[i + 1], xpteg[i + 2], xpteg[i + 3]);	/* Dump the pteg slot */
543
544			if(xpteg[i + 1] & 1) db_printf("  valid - ");	/* Is it valid? */
545			else db_printf("invalid - ");					/* Nope, invalid */
546
547			llslot = ((long long)xpteg[i] << 32) | (long long)xpteg[i + 1];	/* Make a long long version of this */
548			space = (llslot >> 12) & (maxAdrSp - 1);		/* Extract the space */
549			llhash = (unsigned long long)space | ((unsigned long long)space << maxAdrSpb) | ((unsigned long long)space << (2 * maxAdrSpb));	/* Get the hash */
550			llhash = llhash & 0x0000001FFFFFFFFFULL;		/* Make sure we stay within supported ranges */
551			pva =  (unsigned long long)ptegindex ^ llhash;	/* Get part of the vaddr */
552			llseg = (llslot >> 12) ^ llhash;				/* Get the segment number */
553			api = (llslot >> 7) & 0x1F;						/* Get the API */
554			llva = ((llseg << (28 - maxAdrSpb)) & 0xFFFFFFFFF0000000ULL) | (api << 23) | ((pva << 12) & 0x007FF000);	/* Get the vaddr */
555			db_printf("va = %016llX\n", llva);
556		}
557	}
558}
559
560
561/*
562 *		Print out 256 bytes of virtual storage
563 *
564 *
565 *		dv [entaddr] [space]
566 *		address must be on 32-byte boundary.  It will be rounded down if not
567 */
568void
569db_display_virtual(db_expr_t addr, boolean_t have_addr, db_expr_t count,
570		   char *modif)
571{
572
573	int			i, size, lines, rlines;
574	unsigned int 	xbuf[8];
575	db_expr_t	xspace;
576	pmap_t		pmap;
577
578	mapping_t	*mp, *mpv;
579	addr64_t	pa;
580	ppnum_t		pnum;
581
582	if (db_expression(&xspace)) {							/* Parse the space ID */
583		if(xspace >= (1 << maxAdrSpb)) {					/* Check if they gave us a sane space number */
584			db_printf("Invalid space ID: %llX - max is %X\n", xspace, (1 << maxAdrSpb) - 1);
585			return;
586		}
587		dvspace = xspace;									/* Get the space or set default */
588	}
589
590	pmap = (pmap_t)pmapTrans[dvspace].pmapVAddr;			/* Find the pmap address */
591	if((unsigned int)pmap == 0) {							/* Is there actually a pmap here? */
592		db_printf("Address space not found: %X\n", dvspace);	/* Complain */
593		return;
594	}
595
596	addr &= -32;
597
598	size = 4096 - (addr & 0x00000FFF);						/* Bytes left on page */
599	lines = size / 32;										/* Number of lines in first or only part */
600	if(lines > 8) lines = 8;
601	rlines = 8 - lines;
602	if(rlines < 0) lines = 0;
603
604	db_printf("Dumping %016llX (pmap = %08X, space = %X); ", addr, pmap, dvspace);
605
606	pnum = pmap_find_phys(pmap, (addr64_t)addr);			/* Phynd the Physical */
607	if(!pnum) {												/* Did we find one? */
608		db_printf("Not mapped\n");
609		return;												/* Didn't find any, return FALSE... */
610	}
611
612	pa = (addr64_t)(pnum << 12) | (addr64_t)(addr & 0xFFF);	/* Get the physical address */
613	db_printf("phys = %016llX\n", pa);
614
615	for(i=0; i<lines; i++) {								/* Print n bytes */
616		ReadReal(pa, &xbuf[0]);								/* Get the real storage data */
617		db_printf("%016llX   %08X %08X %08X %08X  %08X %08X %08X %08X\n", addr,	/* Print a line */
618			xbuf[0], xbuf[1], xbuf[2], xbuf[3],
619			xbuf[4], xbuf[5], xbuf[6], xbuf[7]);
620		addr = (db_expr_t)(addr + 0x00000020);				/* Point to next address */
621		pa = pa + 0x00000020;								/* Point to next address */
622	}
623	db_next = addr;
624
625	if(!rlines) return;
626
627	db_printf("Dumping %016llX (pmap = %08X, space = %X); ", addr, pmap, dvspace);
628
629	pnum = pmap_find_phys(pmap, (addr64_t)((unsigned int)addr));	/* Phynd the Physical */
630	if(!pnum) {												/* Did we find one? */
631		db_printf("Not mapped\n");
632		return;												/* Didn't find any, return FALSE... */
633	}
634
635	pa = (addr64_t)(pnum << 12) | (addr64_t)((unsigned int)addr & 0xFFF);	/* Get the physical address */
636	db_printf("phys = %016llX\n", pa);
637
638	for(i=0; i<rlines; i++) {								/* Print n bytes */
639		ReadReal(pa, &xbuf[0]);								/* Get the real storage data */
640		db_printf("%016llX   %08X %08X %08X %08X  %08X %08X %08X %08X\n", addr,	/* Print a line */
641			xbuf[0], xbuf[1], xbuf[2], xbuf[3],
642			xbuf[4], xbuf[5], xbuf[6], xbuf[7]);
643		addr = (db_expr_t)(addr + 0x00000020);				/* Point to next address */
644		pa = pa + 0x00000020;								/* Point to next address */
645	}
646	db_next = addr;
647
648
649}
650
651
652/*
653 *		Print out savearea stuff
654 *
655 *
656 *		ds
657 */
658
659#define chainmax 32
660
661void
662db_display_save(db_expr_t addr, boolean_t have_addr, db_expr_t count,
663		char *modif)
664{
665	int				i, j, totsaves, tottasks, taskact, chainsize, vmid, didvmhead;
666	task_t			task;
667	thread_act_t	act;
668	struct savearea		*save;
669	vmmCntrlTable	*CTable;
670
671	tottasks = 0;
672	totsaves = 0;
673
674	for(task = (task_t)tasks.next; task != (task_t)&tasks.next; task = (task_t)task->tasks.next) {	/* Go through the tasks */
675		taskact = 0;								/* Reset activation count */
676		db_printf("\nTask %4d @%08X:\n", tottasks, task);	/* Show where we're at */
677		for(act = (thread_act_t)task->threads.next; act != (thread_act_t)&task->threads; act = (thread_act_t)act->task_threads.next) {	/* Go through activations */
678			db_printf("   Act %4d @%08X - p: %08X  current context: %08X\n",
679					  taskact, act, act->machine.pcb, act->machine.curctx);
680
681			save = (struct savearea *)act->machine.pcb; 		/* Set the start of the normal chain */
682			chainsize = 0;
683
684			db_printf("      General context - fp: %08X  fl: %08X  fc: %d  vp: %08X  vl: %08X  vp: %d\n",
685				act->machine.facctx.FPUsave, act->machine.facctx.FPUlevel, act->machine.facctx.FPUcpu,
686				act->machine.facctx.VMXsave, act->machine.facctx.VMXlevel, act->machine.facctx.VMXcpu);
687
688			while(save) {							/* Do them all */
689				totsaves++;							/* Count savearea */
690				db_printf("         Norm %08X: %016llX %016llX - tot = %d\n", save, save->save_srr0, save->save_srr1, totsaves);
691				save = (struct savearea *)save->save_hdr.save_prev;	/* Next one */
692				if(chainsize++ > chainmax) {		/* See if we might be in a loop */
693					db_printf("         Chain terminated by count (%d) before %08X\n", chainmax, save);
694					break;
695				}
696			}
697
698			save = (struct savearea *)act->machine.facctx.FPUsave; 	/* Set the start of the floating point chain */
699			chainsize = 0;
700			while(save) {							/* Do them all */
701				totsaves++;							/* Count savearea */
702				db_printf("         FPU  %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves);
703				save = (struct savearea *)save->save_hdr.save_prev;	/* Next one */
704				if(chainsize++ > chainmax) {		/* See if we might be in a loop */
705					db_printf("         Chain terminated by count (%d) before %08X\n", chainmax, save);
706					break;
707				}
708			}
709
710			save = (struct savearea *)act->machine.facctx.VMXsave; 	/* Set the start of the floating point chain */
711			chainsize = 0;
712			while(save) {							/* Do them all */
713				totsaves++;							/* Count savearea */
714				db_printf("         Vec  %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves);
715				save = (struct savearea *)save->save_hdr.save_prev;	/* Next one */
716				if(chainsize++ > chainmax) {		/* See if we might be in a loop */
717					db_printf("         Chain terminated by count (%d) before %08X\n", chainmax, save);
718					break;
719				}
720			}
721
722			if(CTable = act->machine.vmmControl) {		/* Are there virtual machines? */
723
724				for(vmid = 0; vmid < kVmmMaxContexts; vmid++) {
725
726					if(!(CTable->vmmc[vmid].vmmFlags & vmmInUse)) continue;	/* Skip if vm is not in use */
727
728					if(!CTable->vmmc[vmid].vmmFacCtx.FPUsave && !CTable->vmmc[vmid].vmmFacCtx.VMXsave) continue;	/* If neither types, skip this vm */
729
730					db_printf("      VMachine ID %3d - fp: %08X  fl: %08X  fc: %d  vp: %08X  vl: %08X  vp: %d\n", vmid,	/* Title it */
731						CTable->vmmc[vmid].vmmFacCtx.FPUsave, CTable->vmmc[vmid].vmmFacCtx.FPUlevel, CTable->vmmc[vmid].vmmFacCtx.FPUcpu,
732						CTable->vmmc[vmid].vmmFacCtx.VMXsave, CTable->vmmc[vmid].vmmFacCtx.VMXlevel, CTable->vmmc[vmid].vmmFacCtx.VMXcpu
733					);
734
735					save = (struct savearea *)CTable->vmmc[vmid].vmmFacCtx.FPUsave; 	/* Set the start of the floating point chain */
736					chainsize = 0;
737					while(save) {						/* Do them all */
738						totsaves++;						/* Count savearea */
739						db_printf("         FPU  %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves);
740						save = (struct savearea *)save->save_hdr.save_prev;	/* Next one */
741						if(chainsize++ > chainmax) {	/* See if we might be in a loop */
742							db_printf("         Chain terminated by count (%d) before %08X\n", chainmax, save);
743							break;
744						}
745					}
746
747					save = (struct savearea *)CTable->vmmc[vmid].vmmFacCtx.VMXsave; 	/* Set the start of the floating point chain */
748					chainsize = 0;
749					while(save) {						/* Do them all */
750						totsaves++;						/* Count savearea */
751						db_printf("         Vec  %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves);
752						save = (struct savearea *)save->save_hdr.save_prev;	/* Next one */
753						if(chainsize++ > chainmax) {	/* See if we might be in a loop */
754							db_printf("         Chain terminated by count (%d) before %08X\n", chainmax, save);
755							break;
756						}
757					}
758				}
759			}
760			taskact++;
761		}
762		tottasks++;
763	}
764
765	db_printf("Total saveareas accounted for: %d\n", totsaves);
766}
767
768/*
769 *		Print out extra registers
770 *
771 *
772 *		dx
773 */
774
775extern unsigned int dbfloats[33][2];
776extern unsigned int dbvecs[33][4];
777extern unsigned int dbspecrs[336];
778
779void
780db_display_xregs(db_expr_t addr, boolean_t have_addr, db_expr_t count,
781		 char *modif)
782{
783	int				i, j, pents;
784
785	stSpecrs(dbspecrs);										/* Save special registers */
786	if(PerProcTable[0].ppe_vaddr->pf.Available & pf64Bit) {
787		db_printf("PIR:    %08X\n", dbspecrs[0]);
788		db_printf("PVR:    %08X\n", dbspecrs[1]);
789		db_printf("SDR1:   %08X.%08X\n", dbspecrs[26], dbspecrs[27]);
790		db_printf("HID0:   %08X.%08X\n", dbspecrs[28], dbspecrs[29]);
791		db_printf("HID1:   %08X.%08X\n", dbspecrs[30], dbspecrs[31]);
792		db_printf("HID4:   %08X.%08X\n", dbspecrs[32], dbspecrs[33]);
793		db_printf("HID5:   %08X.%08X\n", dbspecrs[34], dbspecrs[35]);
794		db_printf("SPRG0:  %08X.%08X %08X.%08X\n", dbspecrs[18], dbspecrs[19], dbspecrs[20], dbspecrs[21]);
795		db_printf("SPRG2:  %08X.%08X %08X.%08X\n", dbspecrs[22], dbspecrs[23], dbspecrs[24], dbspecrs[25]);
796		db_printf("\n");
797		for(i = 0; i < (64 * 4); i += 4) {
798			db_printf("SLB %02d: %08X.%08X %08X.%08X\n", i / 4, dbspecrs[80 + i], dbspecrs[81 + i], dbspecrs[82 + i], dbspecrs[83 + i]);
799		}
800	}
801	else {
802		db_printf("PIR:    %08X\n", dbspecrs[0]);
803		db_printf("PVR:    %08X\n", dbspecrs[1]);
804		db_printf("SDR1:   %08X\n", dbspecrs[22]);
805		db_printf("HID0:   %08X\n", dbspecrs[39]);
806		db_printf("HID1:   %08X\n", dbspecrs[40]);
807		db_printf("L2CR:   %08X\n", dbspecrs[41]);
808		db_printf("MSSCR0: %08X\n", dbspecrs[42]);
809		db_printf("MSSCR1: %08X\n", dbspecrs[43]);
810		db_printf("THRM1:  %08X\n", dbspecrs[44]);
811		db_printf("THRM2:  %08X\n", dbspecrs[45]);
812		db_printf("THRM3:  %08X\n", dbspecrs[46]);
813		db_printf("ICTC:   %08X\n", dbspecrs[47]);
814		db_printf("L2CR2:  %08X\n", dbspecrs[48]);
815		db_printf("DABR:   %08X\n", dbspecrs[49]);
816
817		db_printf("DBAT: %08X %08X %08X %08X\n", dbspecrs[2], dbspecrs[3], dbspecrs[4], dbspecrs[5]);
818		db_printf("      %08X %08X %08X %08X\n", dbspecrs[6], dbspecrs[7], dbspecrs[8], dbspecrs[9]);
819		db_printf("IBAT: %08X %08X %08X %08X\n", dbspecrs[10], dbspecrs[11], dbspecrs[12], dbspecrs[13]);
820		db_printf("      %08X %08X %08X %08X\n", dbspecrs[14], dbspecrs[15], dbspecrs[16], dbspecrs[17]);
821		db_printf("SPRG: %08X %08X %08X %08X\n", dbspecrs[18], dbspecrs[19], dbspecrs[20], dbspecrs[21]);
822		db_printf("\n");
823		for(i = 0; i < 16; i += 8) {						/* Print 8 at a time */
824			db_printf("SR%02d: %08X %08X %08X %08X %08X %08X %08X %08X\n", i,
825				dbspecrs[23+i], dbspecrs[24+i], dbspecrs[25+i], dbspecrs[26+i],
826				dbspecrs[27+i], dbspecrs[28+i], dbspecrs[29+i], dbspecrs[30+i]);
827		}
828	}
829
830	db_printf("\n");
831
832	stFloat(dbfloats);										/* Save floating point registers */
833	for(i = 0; i < 32; i += 4) {							/* Print 4 at a time */
834		db_printf("F%02d: %08X %08X  %08X %08X  %08X %08X  %08X %08X\n", i,
835			dbfloats[i][0], dbfloats[i][1], dbfloats[i+1][0], dbfloats[i+1][1],
836			dbfloats[i+2][0], dbfloats[i+2][1], dbfloats[i+3][0], dbfloats[i+3][1]);
837	}
838	db_printf("FCR: %08X %08X\n", dbfloats[32][0], dbfloats[32][1]);	/* Print FSCR */
839
840	if(!stVectors(dbvecs)) return;							/* Return if not Altivec capable */
841
842	db_printf("\n");
843
844	for(i = 0; i < 32; i += 2) {							/* Print 2 at a time */
845		db_printf("V%02d: %08X %08X %08X %08X  %08X %08X %08X %08X\n", i,
846			dbvecs[i][0], dbvecs[i][1], dbvecs[i][2], dbvecs[i][3],
847			dbvecs[i+1][0], dbvecs[i+1][1], dbvecs[i+1][2], dbvecs[i+1][3]);
848	}
849	db_printf("VCR: %08X %08X %08X %08X\n", dbvecs[32][0], dbvecs[32][1], dbvecs[32][2], dbvecs[32][3]);	/* Print VSCR */
850
851	/* Tell them we did it */
852}
853
854/*
855 *		Check check mappings and hash table for consistency
856 *
857  *		cm
858 */
859void
860db_check_mappings(db_expr_t addr, boolean_t have_addr, db_expr_t count,
861		  char *modif)
862{
863	addr64_t  pteg, pca, llva, lnextva;
864	unsigned int xpteg[32], xpca[8], space, hash, pva, seg, api, va, free, free2, xauto, PTEGcnt, wimgkk, wimgxx, slotoff;
865	int i, j, fnderr, slot, slot2, k, s4bit;
866	pmap_t pmap;
867	mapping_t *mp;
868	ppnum_t ppn, pa, aoff;
869	unsigned long long llslot, llseg, llhash;
870
871	s4bit = 0;												/* Assume dinky? */
872	if(PerProcTable[0].ppe_vaddr->pf.Available & pf64Bit) s4bit = 1;	/* Are we a big guy? */
873
874	PTEGcnt = hash_table_size / 64;							/* Get the number of PTEGS */
875	if(s4bit) PTEGcnt = PTEGcnt / 2;						/* PTEGs are twice as big */
876
877	pteg = hash_table_base;									/* Start of hash table */
878	pca = hash_table_base - 4;								/* Start of PCA */
879
880	for(i = 0; i < PTEGcnt; i++) {							/* Step through them all */
881
882		fnderr = 0;
883
884		ReadReal(pteg, &xpteg[0]);							/* Get first half of the pteg */
885		ReadReal(pteg + 0x20, &xpteg[8]);					/* Get second half of the pteg */
886		if(s4bit) {											/* See if we need the other half */
887			ReadReal(pteg + 0x40, &xpteg[16]);				/* Get third half of the pteg */
888			ReadReal(pteg + 0x60, &xpteg[24]);				/* Get fourth half of the pteg */
889		}
890		ReadReal(pca, &xpca[0]);							/* Get pca */
891
892		if(xpca[0] & 0x00000001) {							/* Is PCA locked? */
893			db_printf("Unexpected locked PCA\n");			/* Yeah, this may be bad */
894			fnderr = 1;										/* Remember to print the pca/pteg pair later */
895		}
896
897		free = 0x80000000;
898
899		for(j = 0; j < 7; j++) {							/* Search for duplicates */
900			slot = j * 2;									/* Point to the slot */
901			if(s4bit) slot = slot * 2;						/* Adjust for bigger slots */
902			if(!(xpca[0] & free)) {							/* Check more if slot is allocated */
903				for(k = j + 1; k < 8; k++) {				/* Search remaining slots */
904					slot2 = k * 2;							/* Point to the slot */
905					if(s4bit) slot2 = slot2 * 2;			/* Adjust for bigger slots */
906					if((xpteg[slot] == xpteg[slot2])
907					   && (!s4bit || (xpteg[slot + 1] == xpteg[slot2 + 1]))) {		/* Do we have duplicates? */
908						db_printf("Duplicate tags in pteg, slot %d and slot %d\n", j, k);
909						fnderr = 1;
910					}
911				}
912			}
913			free = free >> 1;								/* Move slot over */
914		}
915
916		free = 0x80000000;
917		xauto = 0x00008000;
918
919		for(j = 0; j < 8; j++) {							/* Step through the slots */
920
921			slot = j * 2;									/* Point to the slot */
922			if(s4bit) slot = slot * 2;						/* Hagfish? */
923			if(xpca[0] & free) {							/* Check if marked free */
924				if((!s4bit && (xpteg[slot] & 0x80000000))	/* Is a supposedly free slot valid? */
925				   || (s4bit && (xpteg[slot + 1] & 1))) {
926					db_printf("Free slot still valid - %d\n", j);
927					fnderr = 1;
928				}
929			}
930			else {											/* We have an in use slot here */
931
932				if(!(!s4bit && (xpteg[slot] & 0x80000000))	/* Is a supposedly in use slot valid? */
933				   && !(s4bit && (xpteg[slot + 1] & 1))) {
934					db_printf("Inuse slot not valid - %d\n", j);
935					fnderr = 1;
936				}
937				else {										/* Slot is valid, check mapping */
938					if(!s4bit) {							/* Not Hagfish? */
939						space = (xpteg[slot] >> 7) & (maxAdrSp - 1);	/* Extract the space */
940						hash = space | (space << maxAdrSpb) | (space << (2 * maxAdrSpb));	/* Get the hash */
941						pva =  i ^ hash;					/* Get part of the vaddr */
942						seg = (xpteg[slot] >> 7) ^ hash;	/* Get the segment number */
943						api = (xpteg[slot] & 0x3F);			/* Get the API */
944						va = ((seg << (28 - maxAdrSpb)) & 0xF0000000) | (api << 22) | ((pva << 12) & 0x003FF000);	/* Get the vaddr */
945						llva = (addr64_t)va;				/* Make this a long long */
946						wimgxx = xpteg[slot + 1] & 0x7F;	/* Get the wimg and pp */
947						ppn = xpteg[slot + 1] >> 12;		/* Get physical page number */
948						slotoff = (i * 64) + (j * 8) | 1;	/* Get offset to slot and valid bit */
949					}
950					else {									/* Yes, Hagfish */
951						llslot = ((long long)xpteg[slot] << 32) | (long long)xpteg[slot + 1];	/* Make a long long version of this */
952						space = (llslot >> 12) & (maxAdrSp - 1);	/* Extract the space */
953						llhash = (unsigned long long)space | ((unsigned long long)space << maxAdrSpb) | ((unsigned long long)space << (2 * maxAdrSpb));	/* Get the hash */
954						llhash = llhash & 0x0000001FFFFFFFFFULL;	/* Make sure we stay within supported ranges */
955						pva =  i ^ llhash;					/* Get part of the vaddr */
956						llseg = ((llslot >> 12) ^ llhash);	/* Get the segment number */
957						api = (llslot >> 7) & 0x1F;			/* Get the API */
958						llva = ((llseg << (28 - maxAdrSpb)) & 0xFFFFFFFFF0000000ULL) | (api << 23) | ((pva << 12) & 0x007FF000);	/* Get the vaddr */
959						wimgxx = xpteg[slot + 3] & 0x7F;	/* Get the wimg and pp */
960						ppn =  (xpteg[slot + 2] << 20) | (xpteg[slot + 3] >> 12);	/* Get physical page number */
961						slotoff = (i * 128) + (j * 16) | 1;		/* Get offset to slot and valid bit */
962					}
963
964					pmap = pmapTrans[space].pmapVAddr;	/* Find the pmap address */
965					if(!pmap) {								/* The pmap is not in use */
966						db_printf("The space %08X is not assigned to a pmap, slot = %d\n", space, slot);	/* Say we are wrong */
967						fnderr = 1;
968						goto dcmout;
969					}
970
971					if (pmap->pmapFlags & pmapVMgsaa) {
972						unsigned int ret;
973						mapping_t mpcopy;
974						ret = hw_find_map_gv(pmap, llva, &mpcopy);
975					} else {
976						mp = hw_find_map(pmap, llva, &lnextva);		/* Try to find the mapping for this address */
977	//					db_printf("%08X - %017llX\n", mp, llva);
978						if((unsigned int)mp == mapRtBadLk) {	/* Did we lock up ok? */
979							db_printf("Timeout locking mapping for for virtual address %016ll8X, slot = %d\n", llva, j);
980							return;
981						}
982
983						if(!mp) {								/* Did we find one? */
984							db_printf("Not mapped, slot = %d, va = %08X\n", j, (unsigned int)llva);
985							fnderr = 1;
986							goto dcmout;
987						}
988
989						if((mp->mpFlags & 0xFF000000) > 0x01000000) {	/* Is busy count too high? */
990							db_printf("Busy count too high, slot = %d\n", j);
991							fnderr = 1;
992						}
993
994						if((mp->mpFlags & mpType) == mpBlock) {		/* Is this a block map? */
995							if(!(xpca[0] & xauto)) {				/* Is it marked as such? */
996								db_printf("mapping marked as block, PCA is not, slot = %d\n", j);
997								fnderr = 1;
998							}
999						}
1000						else {									/* Is a block */
1001							if(xpca[0] & xauto) {				/* Is it marked as such? */
1002								db_printf("mapping not marked as block, PCA is, slot = %d\n", j);
1003								fnderr = 1;
1004							}
1005							if(mp->mpPte != slotoff) {			/* See if mapping PTEG offset is us */
1006								db_printf("mapping does not point to PTE, slot = %d\n", j);
1007								fnderr = 1;
1008							}
1009						}
1010
1011						wimgkk = (unsigned int)mp->mpVAddr;		/* Get last half of vaddr where keys, etc are */
1012						wimgkk = (wimgkk ^ wimgxx) & 0x7F;		/* XOR to find differences from PTE */
1013						if(wimgkk) {							/* See if key in PTE is what we want */
1014							db_printf("key or WIMG does not match, slot = %d\n", j);
1015							fnderr = 1;
1016						}
1017
1018						aoff = (ppnum_t)((llva >> 12) - (mp->mpVAddr >> 12));	/* Get the offset from vaddr */
1019						pa = aoff + mp->mpPAddr;				/* Get the physical page number we expect */
1020						if(pa != ppn) {							/* Is physical address expected? */
1021							db_printf("Physical address does not match, slot = %d\n", j);
1022							fnderr = 1;
1023						}
1024
1025						mapping_drop_busy(mp);					/* We're done with the mapping */
1026					}
1027				}
1028
1029			}
1030dcmout:
1031			free = free >> 1;
1032			xauto = xauto >> 1;
1033		}
1034
1035
1036		if(fnderr)db_dumppca(i);							/* Print if error */
1037
1038		pteg = pteg + 64;									/* Go to the next one */
1039		if(s4bit) pteg = pteg + 64;							/* Hagfish? */
1040		pca = pca - 4;										/* Go to the next one */
1041
1042
1043	}
1044}
1045
1046/*
1047 *		Displays all of the kmods in the system.
1048 *
1049  *		dp
1050 */
1051void
1052db_display_kmod(db_expr_t addr, boolean_t have_addr, db_expr_t count,
1053		char *modif)
1054{
1055	kmod_info_t	*kmd;
1056	unsigned int strt, end;
1057
1058	kmd = kmod;							/* Start at the start */
1059
1060	db_printf("info      addr      start    - end       name ver\n");
1061
1062	while(kmd) {						/* Dump 'em all */
1063		strt = (unsigned int)kmd->address + kmd->hdr_size;	/* Get start of kmod text */
1064		end = (unsigned int)kmd->address + kmd->size;			/* Get end of kmod */
1065		db_printf("%08X  %08X  %08X - %08X: %s, %s\n", kmd, kmd->address, strt, end,
1066			kmd->name, kmd->version);
1067		kmd = kmd->next;				/* Step to it */
1068	}
1069}
1070
1071/*
1072 *		Displays stuff
1073 *
1074  *		gs
1075 */
1076unsigned char xxgpo[36] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1077
1078void
1079db_gsnoop(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif)
1080{
1081	int i, j;
1082	unsigned char *gp, gpn[36];
1083#define ngpr 34
1084
1085	gp = (unsigned char *)0x8000005C;
1086
1087	for(i = 0; i < ngpr; i++) gpn[i] = gp[i];	/* Copy 'em */
1088
1089	for(i = 0; i < ngpr; i++) {
1090		db_printf("%02X ", gpn[i]);
1091	}
1092	db_printf("\n");
1093
1094	for(i = 0; i < ngpr; i++) {
1095		if(gpn[i] != xxgpo[i]) db_printf("^^ ");
1096		else  db_printf("   ");
1097	}
1098	db_printf("\n");
1099
1100	for(i = 0; i < ngpr; i++) xxgpo[i] = gpn[i];	/* Save 'em */
1101}
1102
1103
1104void Dumbo(void);
1105void Dumbo(void){
1106}
1107