2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * @OSF_FREE_COPYRIGHT@
32 * @APPLE_FREE_COPYRIGHT@
36 * Author: Bill Angell, Apple
39 * exceptions and certain C functions write into a trace table which
40 * can be examined via the machine 'lt' command under kdb
44 #include <string.h> /* For strcpy() */
45 #include <mach/boolean.h>
46 #include <machine/db_machdep.h>
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>
67 #include <ppc/savearea.h>
68 #include <ppc/vmachmon.h>
70 void db_dumppca(unsigned int ptegindex
);
71 void db_dumpmapping(struct mapping
*mp
); /* Dump out a mapping */
72 extern kmod_info_t
*kmod
; /* Find the kmods */
74 db_addr_t db_low_trace_prev
= 0;
77 * Print out the low level trace table:
79 * Displays the entry and 15 before it in newest to oldest order
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
86 void db_low_trace(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
89 unsigned int tempx
, cnt
;
90 unsigned int xTraceCurr
, xTraceStart
, xTraceEnd
, cxltr
;
96 cnt
= 16; /* Default to 16 entries */
98 xTraceCurr
= trcWork
.traceCurr
; /* Transfer current pointer */
99 xTraceStart
= trcWork
.traceStart
; /* Transfer start of table */
100 xTraceEnd
= trcWork
.traceEnd
; /* Transfer end of table */
102 if(addr
== -1) cnt
= 0x7FFFFFFF; /* Max the count */
104 if(!addr
|| (addr
== -1)) {
105 addr
=xTraceCurr
-sizeof(LowTraceRecord
); /* Start at the newest */
106 if((unsigned int)addr
<xTraceStart
) addr
=xTraceEnd
-sizeof(LowTraceRecord
); /* Wrap low back to high */
109 if((unsigned int)addr
<xTraceStart
||(unsigned int)addr
>=xTraceEnd
) { /* In the table? */
110 db_printf("address not in low memory trace table\n"); /* Tell the fool */
111 return; /* Leave... */
114 if((unsigned int)addr
&0x0000007F) { /* Proper alignment? */
115 db_printf("address not aligned on trace entry boundary (0x80)\n"); /* Tell 'em */
116 return; /* Leave... */
119 xxltr
= addr
; /* Set the start */
120 cxltr
= ((xTraceCurr
== xTraceStart
? xTraceEnd
: xTraceCurr
) - sizeof(LowTraceRecord
)); /* Get address of newest entry */
122 db_low_trace_prev
= addr
; /* Starting point */
124 for(i
=0; i
< cnt
; i
++) { /* Dump the 16 (or all) entries */
126 ReadReal((addr64_t
)xxltr
, (unsigned int *)&xltr
); /* Get the first half */
127 ReadReal((addr64_t
)xxltr
+ 32, &(((unsigned int *)&xltr
)[8])); /* Get the second half */
128 ReadReal((addr64_t
)xxltr
+ 64, &(((unsigned int *)&xltr
)[16])); /* Get the second half */
129 ReadReal((addr64_t
)xxltr
+ 96, &(((unsigned int *)&xltr
)[24])); /* Get the second half */
131 db_printf("\n%s%08llX %1X %08X %08X - %04X", (xxltr
!= cxltr
? " " : "*"),
133 (xltr
.LTR_cpu
& 0xFF), xltr
.LTR_timeHi
, xltr
.LTR_timeLo
,
134 (xltr
.LTR_excpt
& 0x8000 ? 0xFFFF : xltr
.LTR_excpt
* 64)); /* Print the first line */
136 if(xltr
.LTR_cpu
& 0xFF00) db_printf(", sflgs = %02X\n", ((xltr
.LTR_cpu
>> 8) & 0xFF));
137 else db_printf("\n");
139 db_printf(" DAR/DSR/CR: %016llX %08X %08X\n", xltr
.LTR_dar
, xltr
.LTR_dsisr
, xltr
.LTR_cr
);
141 db_printf(" SRR0/SRR1 %016llX %016llX\n", xltr
.LTR_srr0
, xltr
.LTR_srr1
);
142 db_printf(" LR/CTR %016llX %016llX\n", xltr
.LTR_lr
, xltr
.LTR_ctr
);
144 db_printf(" R0/R1/R2 %016llX %016llX %016llX\n", xltr
.LTR_r0
, xltr
.LTR_r1
, xltr
.LTR_r2
);
145 db_printf(" R3/R4/R5 %016llX %016llX %016llX\n", xltr
.LTR_r3
, xltr
.LTR_r4
, xltr
.LTR_r5
);
146 db_printf(" R6/sv/rsv %016llX %016llX %08X\n", xltr
.LTR_r6
, xltr
.LTR_save
, xltr
.LTR_rsvd0
);
148 if((cnt
!= 16) && (xxltr
== xTraceCurr
)) break; /* If whole table dump, exit when we hit start again... */
150 xxltr
-=sizeof(LowTraceRecord
); /* Back it on up */
151 if(xxltr
<xTraceStart
)
152 xxltr
=(xTraceEnd
-sizeof(LowTraceRecord
)); /* Wrap low back to high */
155 db_next
= (db_expr_t
)(xxltr
);
161 * Print out 256 bytes
166 void db_display_long(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
170 for(i
=0; i
<8; i
++) { /* Print 256 bytes */
171 db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr
, /* Print a line */
172 ((unsigned long *)addr
)[0], ((unsigned long *)addr
)[1], ((unsigned long *)addr
)[2], ((unsigned long *)addr
)[3],
173 ((unsigned long *)addr
)[4], ((unsigned long *)addr
)[5], ((unsigned long *)addr
)[6], ((unsigned long *)addr
)[7]);
174 addr
=(db_expr_t
)(addr
+0x00000020); /* Point to next address */
181 unsigned char xtran
[256] = {
182 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
183 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* 0x */
184 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* 1x */
185 ' ', '!', '"', '#', '$', '%', '&',0x27, '(', ')', '*', '+', ',', '-', '.', '/', /* 2x */
186 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', /* 3x */
187 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 4x */
188 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',0x5C, ']', '^', '_', /* 5x */
189 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 6x */
190 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '.', /* 7x */
191 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* 8x */
192 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* 9x */
193 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Ax */
194 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Bx */
195 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Cx */
196 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Dx */
197 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Ex */
198 '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Fx */
202 * Print out 256 bytes in characters
207 void db_display_char(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
210 unsigned char xlt
[256], *xaddr
;
212 xaddr
= (unsigned char *)addr
;
215 for(i
= 0; i
< 8; i
++) { /* Print 256 bytes */
217 for(k
= 0; k
< 32; k
++) {
218 xlt
[j
] = xtran
[*xaddr
];
228 db_printf("%016llX %s\n", (addr64_t
)(xaddr
- 32), xlt
); /* Print a line */
231 db_next
= (db_expr_t
)xaddr
;
237 * Print out 256 bytes of real storage
239 * Displays the entry and 15 before it in newest to oldest order
243 void db_display_real(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
246 unsigned int xbuf
[8];
248 for(i
=0; i
<8; i
++) { /* Print 256 bytes */
249 ReadReal(addr
, &xbuf
[0]); /* Get the real storage data */
250 db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr
, /* Print a line */
251 xbuf
[0], xbuf
[1], xbuf
[2], xbuf
[3],
252 xbuf
[4], xbuf
[5], xbuf
[6], xbuf
[7]);
253 addr
= addr
+ 0x00000020; /* Point to next address */
258 unsigned int dvspace
= 0;
261 * Print out virtual to real translation information
264 * dm vaddr [space] (defaults to last entered)
266 void db_display_mappings(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
274 if (db_expression(&xspace
)) { /* Get the address space requested */
275 if(xspace
>= maxAdrSp
) {
276 db_printf("requested address space (%llX) larger than max (%X)\n", xspace
, maxAdrSp
- 1);
279 dvspace
= xspace
; /* Get the space or set default */
282 db_printf("mapping information for %016llX in space %8X:\n", addr
, dvspace
);
284 pmap
= pmapTrans
[dvspace
].pmapVAddr
; /* Find the pmap address */
285 if(!pmap
) { /* The pmap is not in use */
286 db_printf("The space %X is not assigned to a pmap\n", dvspace
); /* Say we are wrong */
290 mp
= hw_find_map(pmap
, (addr64_t
)addr
, &lnextva
); /* Try to find the mapping for this address */
291 if((unsigned int)mp
== mapRtBadLk
) { /* Did we lock up ok? */
292 db_printf("Timeout locking physical entry for virtual address %016ll8X\n", addr
);
296 if(!mp
) { /* Did we find one? */
297 db_printf("Not mapped\n");
298 return; /* Didn't find any, return FALSE... */
301 mapping_drop_busy(mp
); /* The mapping shouldn't be changing */
303 db_dumpmapping(mp
); /* Dump it all out */
305 return; /* Tell them we did it */
311 * Print out hash table data
314 * dh vaddr [space] (defaults to last entered)
316 void db_display_hash(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
319 unsigned int seg
, vsid
, ptegindex
, htsize
;
321 addr64_t lnextva
, llva
, vpn
, esid
;
325 llva
= (addr64_t
)((unsigned int)addr
); /* Make sure we are 64-bit now */
327 s4bit
= !((PerProcTable
[0].ppe_vaddr
->pf
.Available
& pf64Bit
) == 0); /* Are we a big guy? */
328 if (db_expression(&xspace
)) { /* Get the address space requested */
329 if(xspace
>= maxAdrSp
) {
330 db_printf("requested address space (%llX) larger than max (%X)\n", xspace
, maxAdrSp
- 1);
333 dvspace
= xspace
; /* Get the space or set default */
336 pmap
= pmapTrans
[dvspace
].pmapVAddr
; /* Find the pmap address */
337 if(!pmap
) { /* The pmap is not in use */
338 db_printf("The space %X is not assigned to a pmap\n", dvspace
); /* Say we are wrong */
342 hash
= (uint64_t)pmap
->space
| ((uint64_t)pmap
->space
<< maxAdrSpb
) | ((uint64_t)pmap
->space
<< (2 * maxAdrSpb
)); /* Get hash value */
343 hash
= hash
& 0x0000001FFFFFFFFF; /* Make sure we stay within supported ranges */
345 esid
= ((llva
>> 14) & -maxAdrSp
) ^ hash
; /* Get ESID */
346 llva
= ((llva
>> 12) & 0xFFFF) ^ esid
; /* Get index into hash table */
348 if(s4bit
) htsize
= hash_table_size
>> 7; /* Get number of entries in hash table for 64-bit */
349 else htsize
= hash_table_size
>> 6; /* get number of entries in hash table for 32-bit */
351 ptegindex
= llva
& (htsize
- 1); /* Get the index to the pteg and pca */
352 db_dumppca(ptegindex
); /* dump the info */
354 return; /* Tell them we did it */
360 * Displays all of the in-use pmaps in the system.
364 void db_display_pmap(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
368 unsigned int v0
, v1
, st0
, st1
;
371 if(!have_addr
) pmap
= kernel_pmap
; /* Start at the beginning */
373 db_printf("PMAP (real) Next Prev Space Flags Ref spaceNum Resident Wired\n");
374 // xxxxxxxx rrrrrrrrrrrrrrrr xxxxxxxx pppppppp ssssssss cccccccc vvvvvvvv nnnnnnnn rrrrrrrr wwwwwwwww
375 while(1) { /* Do them all */
376 db_printf("%08X %016llX %08X %08X %08X %08X %08X %08X %08X %08X\n",
377 pmap
, (addr64_t
)pmap
^ pmap
->pmapvr
,
378 pmap
->pmap_link
.next
, pmap
->pmap_link
.prev
,
379 pmap
->space
, pmap
->pmapFlags
, pmap
->ref_count
, pmap
->spaceNum
,
380 pmap
->stats
.resident_count
,
381 pmap
->stats
.wired_count
);
383 db_printf("lists = %d, rand = %08X, visits = %016llX, searches = %08X\n",
384 pmap
->pmapCurLists
, pmap
->pmapRandNum
,
385 pmap
->pmapSearchVisits
, pmap
->pmapSearchCnt
);
387 db_printf("cctl = %08X, SCSubTag = %016llX\n",
388 pmap
->pmapCCtl
, pmap
->pmapSCSubTag
);
390 for(i
= 0; i
< 16; i
+=2) {
391 v0
= (pmap
->pmapCCtl
>> (31 - i
) & 1); /* Get high order bit */
392 v1
= (pmap
->pmapCCtl
>> (30 - i
) & 1); /* Get high order bit */
393 st0
= (pmap
->pmapSCSubTag
>> (60 - (4 * i
))) & 0xF; /* Get the sub-tag */
394 st1
= (pmap
->pmapSCSubTag
>> (56 - (4 * i
))) & 0xF; /* Get the sub-tag */
396 db_printf(" %01X %01X %016llX/%016llX %01X %01X %016llX/%016llX\n",
397 v0
, st0
, pmap
->pmapSegCache
[i
].sgcESID
, pmap
->pmapSegCache
[i
].sgcVSID
,
398 v1
, st1
, pmap
->pmapSegCache
[i
+1].sgcESID
, pmap
->pmapSegCache
[i
+1].sgcVSID
);
402 if(have_addr
) break; /* Do only one if address supplied */
403 pmap
= (pmap_t
)pmap
->pmap_link
.next
; /* Skip to the next */
404 if(pmap
== kernel_pmap
) break; /* We've wrapped, we're done */
411 * Checks the pmap skip lists
416 void db_check_pmaps(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
424 if(!have_addr
) pmap
= kernel_pmap
; /* If no map supplied, start with kernel */
426 while(1) { /* Do them all */
427 ret
= mapSkipListVerifyC(pmap
, &dumpa
); /* Check out the map */
428 if(!ret
) db_printf("Skiplists verified ok, pmap = %08X\n", pmap
);
430 db_printf("Verification failure at %08X, pmap = %08X\n", ret
, pmap
);
431 for(i
= 0; i
< 32; i
+= 4) {
432 db_printf("R%02d %016llX %016llX %016llX %016llX\n", i
,
433 dumpa
[i
], dumpa
[i
+ 1], dumpa
[i
+ 2], dumpa
[i
+ 3]);
436 if(have_addr
) break; /* Do only one if address supplied */
437 pmap
= (pmap_t
)pmap
->pmap_link
.next
; /* Skip to the next */
438 if(pmap
== kernel_pmap
) break; /* We've wrapped, we're done */
447 * Displays iokit junk
452 void db_piokjunk(void);
454 void db_display_iokit(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
462 * Prints out a mapping control block
466 void db_dumpmapping(struct mapping
*mp
) { /* Dump out a mapping */
471 db_printf("Dump of mapping block: %08X, pmap: %08X (%016llX)\n", mp
, pmapTrans
[mp
->mpSpace
].pmapVAddr
,
472 pmapTrans
[mp
->mpSpace
].pmapPAddr
); /* Header */
473 db_printf(" mpFlags: %08X\n", mp
->mpFlags
);
474 db_printf(" mpSpace: %04X\n", mp
->mpSpace
);
475 db_printf(" mpBSize: %04X\n", mp
->u
.mpBSize
);
476 db_printf(" mpPte: %08X\n", mp
->mpPte
);
477 db_printf(" mpPAddr: %08X\n", mp
->mpPAddr
);
478 db_printf(" mpVAddr: %016llX\n", mp
->mpVAddr
);
479 db_printf(" mpAlias: %016llX\n", mp
->mpAlias
);
480 db_printf(" mpList00: %016llX\n", mp
->mpList0
);
482 for(i
= 1; i
< (mp
->mpFlags
& mpLists
); i
++) { /* Dump out secondary physical skip lists */
483 db_printf(" mpList%02d: %016llX\n", i
, mp
->mpList
[i
- 1]);
490 * Prints out a PTEG and PCA
494 void db_dumppca(unsigned int ptegindex
) {
496 addr64_t pteg
, pca
, llva
;
497 unsigned int xpteg
[32], xpca
[8], space
, hash
, pva
, seg
, api
, va
;
499 unsigned long long llslot
, llseg
, llhash
;
501 s4bit
= !((PerProcTable
[0].ppe_vaddr
->pf
.Available
& pf64Bit
) == 0); /* Are we a big guy? */
503 pteg
= hash_table_base
+ (ptegindex
<< 6); /* Point to the PTEG */
504 if(s4bit
) pteg
= hash_table_base
+ (ptegindex
<< 7); /* Point to the PTEG */
505 pca
= hash_table_base
- ((ptegindex
+ 1) * 4); /* Point to the PCA */
506 db_printf("PTEG = %016llX, PCA = %016llX (index = %08X)\n", pteg
, pca
, ptegindex
);
508 ReadReal(pteg
, &xpteg
[0]); /* Get first half of the pteg */
509 ReadReal(pteg
+ 0x20, &xpteg
[8]); /* Get second half of the pteg */
510 ReadReal(pca
, &xpca
[0]); /* Get pca */
512 db_printf("PCA: free = %02X, steal = %02X, auto = %02X, misc = %02X\n",
513 ((xpca
[0] >> 24) & 255), ((xpca
[0] >> 16) & 255), ((xpca
[0] >> 8) & 255), xpca
[0] & 255);
515 if(!s4bit
) { /* Little guy? */
517 for(i
= 0; i
< 16; i
+= 2) { /* Step through pteg */
518 db_printf("%08X %08X - ", xpteg
[i
], xpteg
[i
+ 1]); /* Dump the pteg slot */
520 if(xpteg
[i
] & 0x80000000) db_printf(" valid - "); /* Is it valid? */
521 else db_printf("invalid - "); /* Nope, invalid */
523 space
= (xpteg
[i
] >> 7) & (maxAdrSp
- 1); /* Extract the space */
524 hash
= space
| (space
<< maxAdrSpb
) | (space
<< (2 * maxAdrSpb
)); /* Get the hash */
525 pva
= ptegindex
^ hash
; /* Get part of the vaddr */
526 seg
= (xpteg
[i
] >> 7) ^ hash
; /* Get the segment number */
527 api
= (xpteg
[i
] & 0x3F); /* Get the API */
528 va
= ((seg
<< (28 - maxAdrSpb
)) & 0xF0000000) | (api
<< 22) | ((pva
<< 12) & 0x003FF000); /* Get the vaddr */
529 db_printf("va = %08X\n", va
);
533 ReadReal(pteg
+ 0x40, &xpteg
[16]); /* Get third half of the pteg */
534 ReadReal(pteg
+ 0x60, &xpteg
[24]); /* Get fourth half of the pteg */
536 for(i
= 0; i
< 32; i
+= 4) { /* Step through pteg */
537 db_printf("%08X%08X %08X%08X - ", xpteg
[i
], xpteg
[i
+ 1], xpteg
[i
+ 2], xpteg
[i
+ 3]); /* Dump the pteg slot */
539 if(xpteg
[i
+ 1] & 1) db_printf(" valid - "); /* Is it valid? */
540 else db_printf("invalid - "); /* Nope, invalid */
542 llslot
= ((long long)xpteg
[i
] << 32) | (long long)xpteg
[i
+ 1]; /* Make a long long version of this */
543 space
= (llslot
>> 12) & (maxAdrSp
- 1); /* Extract the space */
544 llhash
= (unsigned long long)space
| ((unsigned long long)space
<< maxAdrSpb
) | ((unsigned long long)space
<< (2 * maxAdrSpb
)); /* Get the hash */
545 llhash
= llhash
& 0x0000001FFFFFFFFFULL
; /* Make sure we stay within supported ranges */
546 pva
= (unsigned long long)ptegindex
^ llhash
; /* Get part of the vaddr */
547 llseg
= (llslot
>> 12) ^ llhash
; /* Get the segment number */
548 api
= (llslot
>> 7) & 0x1F; /* Get the API */
549 llva
= ((llseg
<< (28 - maxAdrSpb
)) & 0xFFFFFFFFF0000000ULL
) | (api
<< 23) | ((pva
<< 12) & 0x007FF000); /* Get the vaddr */
550 db_printf("va = %016llX\n", llva
);
559 * Print out 256 bytes of virtual storage
562 * dv [entaddr] [space]
563 * address must be on 32-byte boundary. It will be rounded down if not
565 void db_display_virtual(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
567 int i
, size
, lines
, rlines
;
568 unsigned int xbuf
[8];
576 if (db_expression(&xspace
)) { /* Parse the space ID */
577 if(xspace
>= (1 << maxAdrSpb
)) { /* Check if they gave us a sane space number */
578 db_printf("Invalid space ID: %llX - max is %X\n", xspace
, (1 << maxAdrSpb
) - 1);
581 dvspace
= xspace
; /* Get the space or set default */
584 pmap
= (pmap_t
)pmapTrans
[dvspace
].pmapVAddr
; /* Find the pmap address */
585 if((unsigned int)pmap
== 0) { /* Is there actually a pmap here? */
586 db_printf("Address space not found: %X\n", dvspace
); /* Complain */
592 size
= 4096 - (addr
& 0x00000FFF); /* Bytes left on page */
593 lines
= size
/ 32; /* Number of lines in first or only part */
594 if(lines
> 8) lines
= 8;
596 if(rlines
< 0) lines
= 0;
598 db_printf("Dumping %016llX (pmap = %08X, space = %X); ", addr
, pmap
, dvspace
);
600 pnum
= pmap_find_phys(pmap
, (addr64_t
)addr
); /* Phynd the Physical */
601 if(!pnum
) { /* Did we find one? */
602 db_printf("Not mapped\n");
603 return; /* Didn't find any, return FALSE... */
606 pa
= (addr64_t
)(pnum
<< 12) | (addr64_t
)(addr
& 0xFFF); /* Get the physical address */
607 db_printf("phys = %016llX\n", pa
);
609 for(i
=0; i
<lines
; i
++) { /* Print n bytes */
610 ReadReal(pa
, &xbuf
[0]); /* Get the real storage data */
611 db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr
, /* Print a line */
612 xbuf
[0], xbuf
[1], xbuf
[2], xbuf
[3],
613 xbuf
[4], xbuf
[5], xbuf
[6], xbuf
[7]);
614 addr
= (db_expr_t
)(addr
+ 0x00000020); /* Point to next address */
615 pa
= pa
+ 0x00000020; /* Point to next address */
621 db_printf("Dumping %016llX (pmap = %08X, space = %X); ", addr
, pmap
, dvspace
);
623 pnum
= pmap_find_phys(pmap
, (addr64_t
)((unsigned int)addr
)); /* Phynd the Physical */
624 if(!pnum
) { /* Did we find one? */
625 db_printf("Not mapped\n");
626 return; /* Didn't find any, return FALSE... */
629 pa
= (addr64_t
)(pnum
<< 12) | (addr64_t
)((unsigned int)addr
& 0xFFF); /* Get the physical address */
630 db_printf("phys = %016llX\n", pa
);
632 for(i
=0; i
<rlines
; i
++) { /* Print n bytes */
633 ReadReal(pa
, &xbuf
[0]); /* Get the real storage data */
634 db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr
, /* Print a line */
635 xbuf
[0], xbuf
[1], xbuf
[2], xbuf
[3],
636 xbuf
[4], xbuf
[5], xbuf
[6], xbuf
[7]);
637 addr
= (db_expr_t
)(addr
+ 0x00000020); /* Point to next address */
638 pa
= pa
+ 0x00000020; /* Point to next address */
647 * Print out savearea stuff
655 void db_display_save(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
657 int i
, j
, totsaves
, tottasks
, taskact
, chainsize
, vmid
, didvmhead
;
658 processor_set_t pset
= &default_pset
;
662 vmmCntrlTable
*CTable
;
667 for(task
= (task_t
)pset
->tasks
.next
; task
!= (task_t
)&pset
->tasks
.next
; task
= (task_t
)task
->pset_tasks
.next
) { /* Go through the tasks */
668 taskact
= 0; /* Reset activation count */
669 db_printf("\nTask %4d @%08X:\n", tottasks
, task
); /* Show where we're at */
670 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 */
671 db_printf(" Act %4d @%08X - p: %08X current context: %08X\n",
672 taskact
, act
, act
->machine
.pcb
, act
->machine
.curctx
);
674 save
= (savearea
*)act
->machine
.pcb
; /* Set the start of the normal chain */
677 db_printf(" General context - fp: %08X fl: %08X fc: %d vp: %08X vl: %08X vp: %d\n",
678 act
->machine
.facctx
.FPUsave
, act
->machine
.facctx
.FPUlevel
, act
->machine
.facctx
.FPUcpu
,
679 act
->machine
.facctx
.VMXsave
, act
->machine
.facctx
.VMXlevel
, act
->machine
.facctx
.VMXcpu
);
681 while(save
) { /* Do them all */
682 totsaves
++; /* Count savearea */
683 db_printf(" Norm %08X: %016llX %016llX - tot = %d\n", save
, save
->save_srr0
, save
->save_srr1
, totsaves
);
684 save
= (savearea
*)save
->save_hdr
.save_prev
; /* Next one */
685 if(chainsize
++ > chainmax
) { /* See if we might be in a loop */
686 db_printf(" Chain terminated by count (%d) before %08X\n", chainmax
, save
);
691 save
= (savearea
*)act
->machine
.facctx
.FPUsave
; /* Set the start of the floating point chain */
693 while(save
) { /* Do them all */
694 totsaves
++; /* Count savearea */
695 db_printf(" FPU %08X: %08X - tot = %d\n", save
, save
->save_hdr
.save_level
, totsaves
);
696 save
= (savearea
*)save
->save_hdr
.save_prev
; /* Next one */
697 if(chainsize
++ > chainmax
) { /* See if we might be in a loop */
698 db_printf(" Chain terminated by count (%d) before %08X\n", chainmax
, save
);
703 save
= (savearea
*)act
->machine
.facctx
.VMXsave
; /* Set the start of the floating point chain */
705 while(save
) { /* Do them all */
706 totsaves
++; /* Count savearea */
707 db_printf(" Vec %08X: %08X - tot = %d\n", save
, save
->save_hdr
.save_level
, totsaves
);
708 save
= (savearea
*)save
->save_hdr
.save_prev
; /* Next one */
709 if(chainsize
++ > chainmax
) { /* See if we might be in a loop */
710 db_printf(" Chain terminated by count (%d) before %08X\n", chainmax
, save
);
715 if(CTable
= act
->machine
.vmmControl
) { /* Are there virtual machines? */
717 for(vmid
= 0; vmid
< kVmmMaxContexts
; vmid
++) {
719 if(!(CTable
->vmmc
[vmid
].vmmFlags
& vmmInUse
)) continue; /* Skip if vm is not in use */
721 if(!CTable
->vmmc
[vmid
].vmmFacCtx
.FPUsave
&& !CTable
->vmmc
[vmid
].vmmFacCtx
.VMXsave
) continue; /* If neither types, skip this vm */
723 db_printf(" VMachine ID %3d - fp: %08X fl: %08X fc: %d vp: %08X vl: %08X vp: %d\n", vmid
, /* Title it */
724 CTable
->vmmc
[vmid
].vmmFacCtx
.FPUsave
, CTable
->vmmc
[vmid
].vmmFacCtx
.FPUlevel
, CTable
->vmmc
[vmid
].vmmFacCtx
.FPUcpu
,
725 CTable
->vmmc
[vmid
].vmmFacCtx
.VMXsave
, CTable
->vmmc
[vmid
].vmmFacCtx
.VMXlevel
, CTable
->vmmc
[vmid
].vmmFacCtx
.VMXcpu
728 save
= (savearea
*)CTable
->vmmc
[vmid
].vmmFacCtx
.FPUsave
; /* Set the start of the floating point chain */
730 while(save
) { /* Do them all */
731 totsaves
++; /* Count savearea */
732 db_printf(" FPU %08X: %08X - tot = %d\n", save
, save
->save_hdr
.save_level
, totsaves
);
733 save
= (savearea
*)save
->save_hdr
.save_prev
; /* Next one */
734 if(chainsize
++ > chainmax
) { /* See if we might be in a loop */
735 db_printf(" Chain terminated by count (%d) before %08X\n", chainmax
, save
);
740 save
= (savearea
*)CTable
->vmmc
[vmid
].vmmFacCtx
.VMXsave
; /* Set the start of the floating point chain */
742 while(save
) { /* Do them all */
743 totsaves
++; /* Count savearea */
744 db_printf(" Vec %08X: %08X - tot = %d\n", save
, save
->save_hdr
.save_level
, totsaves
);
745 save
= (savearea
*)save
->save_hdr
.save_prev
; /* Next one */
746 if(chainsize
++ > chainmax
) { /* See if we might be in a loop */
747 db_printf(" Chain terminated by count (%d) before %08X\n", chainmax
, save
);
758 db_printf("Total saveareas accounted for: %d\n", totsaves
);
763 * Print out extra registers
769 extern unsigned int dbfloats
[33][2];
770 extern unsigned int dbvecs
[33][4];
771 extern unsigned int dbspecrs
[336];
773 void db_display_xregs(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
777 stSpecrs(dbspecrs
); /* Save special registers */
778 if(PerProcTable
[0].ppe_vaddr
->pf
.Available
& pf64Bit
) {
779 db_printf("PIR: %08X\n", dbspecrs
[0]);
780 db_printf("PVR: %08X\n", dbspecrs
[1]);
781 db_printf("SDR1: %08X.%08X\n", dbspecrs
[26], dbspecrs
[27]);
782 db_printf("HID0: %08X.%08X\n", dbspecrs
[28], dbspecrs
[29]);
783 db_printf("HID1: %08X.%08X\n", dbspecrs
[30], dbspecrs
[31]);
784 db_printf("HID4: %08X.%08X\n", dbspecrs
[32], dbspecrs
[33]);
785 db_printf("HID5: %08X.%08X\n", dbspecrs
[34], dbspecrs
[35]);
786 db_printf("SPRG0: %08X.%08X %08X.%08X\n", dbspecrs
[18], dbspecrs
[19], dbspecrs
[20], dbspecrs
[21]);
787 db_printf("SPRG2: %08X.%08X %08X.%08X\n", dbspecrs
[22], dbspecrs
[23], dbspecrs
[24], dbspecrs
[25]);
789 for(i
= 0; i
< (64 * 4); i
+= 4) {
790 db_printf("SLB %02d: %08X.%08X %08X.%08X\n", i
/ 4, dbspecrs
[80 + i
], dbspecrs
[81 + i
], dbspecrs
[82 + i
], dbspecrs
[83 + i
]);
794 db_printf("PIR: %08X\n", dbspecrs
[0]);
795 db_printf("PVR: %08X\n", dbspecrs
[1]);
796 db_printf("SDR1: %08X\n", dbspecrs
[22]);
797 db_printf("HID0: %08X\n", dbspecrs
[39]);
798 db_printf("HID1: %08X\n", dbspecrs
[40]);
799 db_printf("L2CR: %08X\n", dbspecrs
[41]);
800 db_printf("MSSCR0: %08X\n", dbspecrs
[42]);
801 db_printf("MSSCR1: %08X\n", dbspecrs
[43]);
802 db_printf("THRM1: %08X\n", dbspecrs
[44]);
803 db_printf("THRM2: %08X\n", dbspecrs
[45]);
804 db_printf("THRM3: %08X\n", dbspecrs
[46]);
805 db_printf("ICTC: %08X\n", dbspecrs
[47]);
806 db_printf("L2CR2: %08X\n", dbspecrs
[48]);
807 db_printf("DABR: %08X\n", dbspecrs
[49]);
809 db_printf("DBAT: %08X %08X %08X %08X\n", dbspecrs
[2], dbspecrs
[3], dbspecrs
[4], dbspecrs
[5]);
810 db_printf(" %08X %08X %08X %08X\n", dbspecrs
[6], dbspecrs
[7], dbspecrs
[8], dbspecrs
[9]);
811 db_printf("IBAT: %08X %08X %08X %08X\n", dbspecrs
[10], dbspecrs
[11], dbspecrs
[12], dbspecrs
[13]);
812 db_printf(" %08X %08X %08X %08X\n", dbspecrs
[14], dbspecrs
[15], dbspecrs
[16], dbspecrs
[17]);
813 db_printf("SPRG: %08X %08X %08X %08X\n", dbspecrs
[18], dbspecrs
[19], dbspecrs
[20], dbspecrs
[21]);
815 for(i
= 0; i
< 16; i
+= 8) { /* Print 8 at a time */
816 db_printf("SR%02d: %08X %08X %08X %08X %08X %08X %08X %08X\n", i
,
817 dbspecrs
[23+i
], dbspecrs
[24+i
], dbspecrs
[25+i
], dbspecrs
[26+i
],
818 dbspecrs
[27+i
], dbspecrs
[28+i
], dbspecrs
[29+i
], dbspecrs
[30+i
]);
824 stFloat(dbfloats
); /* Save floating point registers */
825 for(i
= 0; i
< 32; i
+= 4) { /* Print 4 at a time */
826 db_printf("F%02d: %08X %08X %08X %08X %08X %08X %08X %08X\n", i
,
827 dbfloats
[i
][0], dbfloats
[i
][1], dbfloats
[i
+1][0], dbfloats
[i
+1][1],
828 dbfloats
[i
+2][0], dbfloats
[i
+2][1], dbfloats
[i
+3][0], dbfloats
[i
+3][1]);
830 db_printf("FCR: %08X %08X\n", dbfloats
[32][0], dbfloats
[32][1]); /* Print FSCR */
832 if(!stVectors(dbvecs
)) return; /* Return if not Altivec capable */
836 for(i
= 0; i
< 32; i
+= 2) { /* Print 2 at a time */
837 db_printf("V%02d: %08X %08X %08X %08X %08X %08X %08X %08X\n", i
,
838 dbvecs
[i
][0], dbvecs
[i
][1], dbvecs
[i
][2], dbvecs
[i
][3],
839 dbvecs
[i
+1][0], dbvecs
[i
+1][1], dbvecs
[i
+1][2], dbvecs
[i
+1][3]);
841 db_printf("VCR: %08X %08X %08X %08X\n", dbvecs
[32][0], dbvecs
[32][1], dbvecs
[32][2], dbvecs
[32][3]); /* Print VSCR */
843 return; /* Tell them we did it */
849 * Check check mappings and hash table for consistency
853 void db_check_mappings(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
855 addr64_t pteg
, pca
, llva
, lnextva
;
856 unsigned int xpteg
[32], xpca
[8], space
, hash
, pva
, seg
, api
, va
, free
, free2
, xauto
, PTEGcnt
, wimgkk
, wimgxx
, slotoff
;
857 int i
, j
, fnderr
, slot
, slot2
, k
, s4bit
;
860 ppnum_t ppn
, pa
, aoff
;
861 unsigned long long llslot
, llseg
, llhash
;
863 s4bit
= 0; /* Assume dinky? */
864 if(PerProcTable
[0].ppe_vaddr
->pf
.Available
& pf64Bit
) s4bit
= 1; /* Are we a big guy? */
866 PTEGcnt
= hash_table_size
/ 64; /* Get the number of PTEGS */
867 if(s4bit
) PTEGcnt
= PTEGcnt
/ 2; /* PTEGs are twice as big */
869 pteg
= hash_table_base
; /* Start of hash table */
870 pca
= hash_table_base
- 4; /* Start of PCA */
872 for(i
= 0; i
< PTEGcnt
; i
++) { /* Step through them all */
876 ReadReal(pteg
, &xpteg
[0]); /* Get first half of the pteg */
877 ReadReal(pteg
+ 0x20, &xpteg
[8]); /* Get second half of the pteg */
878 if(s4bit
) { /* See if we need the other half */
879 ReadReal(pteg
+ 0x40, &xpteg
[16]); /* Get third half of the pteg */
880 ReadReal(pteg
+ 0x60, &xpteg
[24]); /* Get fourth half of the pteg */
882 ReadReal(pca
, &xpca
[0]); /* Get pca */
884 if(xpca
[0] & 0x00000001) { /* Is PCA locked? */
885 db_printf("Unexpected locked PCA\n"); /* Yeah, this may be bad */
886 fnderr
= 1; /* Remember to print the pca/pteg pair later */
891 for(j
= 0; j
< 7; j
++) { /* Search for duplicates */
892 slot
= j
* 2; /* Point to the slot */
893 if(s4bit
) slot
= slot
* 2; /* Adjust for bigger slots */
894 if(!(xpca
[0] & free
)) { /* Check more if slot is allocated */
895 for(k
= j
+ 1; k
< 8; k
++) { /* Search remaining slots */
896 slot2
= k
* 2; /* Point to the slot */
897 if(s4bit
) slot2
= slot2
* 2; /* Adjust for bigger slots */
898 if((xpteg
[slot
] == xpteg
[slot2
])
899 && (!s4bit
|| (xpteg
[slot
+ 1] == xpteg
[slot2
+ 1]))) { /* Do we have duplicates? */
900 db_printf("Duplicate tags in pteg, slot %d and slot %d\n", j
, k
);
905 free
= free
>> 1; /* Move slot over */
911 for(j
= 0; j
< 8; j
++) { /* Step through the slots */
913 slot
= j
* 2; /* Point to the slot */
914 if(s4bit
) slot
= slot
* 2; /* Hagfish? */
915 if(xpca
[0] & free
) { /* Check if marked free */
916 if((!s4bit
&& (xpteg
[slot
] & 0x80000000)) /* Is a supposedly free slot valid? */
917 || (s4bit
&& (xpteg
[slot
+ 1] & 1))) {
918 db_printf("Free slot still valid - %d\n", j
);
922 else { /* We have an in use slot here */
924 if(!(!s4bit
&& (xpteg
[slot
] & 0x80000000)) /* Is a supposedly in use slot valid? */
925 && !(s4bit
&& (xpteg
[slot
+ 1] & 1))) {
926 db_printf("Inuse slot not valid - %d\n", j
);
929 else { /* Slot is valid, check mapping */
930 if(!s4bit
) { /* Not Hagfish? */
931 space
= (xpteg
[slot
] >> 7) & (maxAdrSp
- 1); /* Extract the space */
932 hash
= space
| (space
<< maxAdrSpb
) | (space
<< (2 * maxAdrSpb
)); /* Get the hash */
933 pva
= i
^ hash
; /* Get part of the vaddr */
934 seg
= (xpteg
[slot
] >> 7) ^ hash
; /* Get the segment number */
935 api
= (xpteg
[slot
] & 0x3F); /* Get the API */
936 va
= ((seg
<< (28 - maxAdrSpb
)) & 0xF0000000) | (api
<< 22) | ((pva
<< 12) & 0x003FF000); /* Get the vaddr */
937 llva
= (addr64_t
)va
; /* Make this a long long */
938 wimgxx
= xpteg
[slot
+ 1] & 0x7F; /* Get the wimg and pp */
939 ppn
= xpteg
[slot
+ 1] >> 12; /* Get physical page number */
940 slotoff
= (i
* 64) + (j
* 8) | 1; /* Get offset to slot and valid bit */
942 else { /* Yes, Hagfish */
943 llslot
= ((long long)xpteg
[slot
] << 32) | (long long)xpteg
[slot
+ 1]; /* Make a long long version of this */
944 space
= (llslot
>> 12) & (maxAdrSp
- 1); /* Extract the space */
945 llhash
= (unsigned long long)space
| ((unsigned long long)space
<< maxAdrSpb
) | ((unsigned long long)space
<< (2 * maxAdrSpb
)); /* Get the hash */
946 llhash
= llhash
& 0x0000001FFFFFFFFFULL
; /* Make sure we stay within supported ranges */
947 pva
= i
^ llhash
; /* Get part of the vaddr */
948 llseg
= ((llslot
>> 12) ^ llhash
); /* Get the segment number */
949 api
= (llslot
>> 7) & 0x1F; /* Get the API */
950 llva
= ((llseg
<< (28 - maxAdrSpb
)) & 0xFFFFFFFFF0000000ULL
) | (api
<< 23) | ((pva
<< 12) & 0x007FF000); /* Get the vaddr */
951 wimgxx
= xpteg
[slot
+ 3] & 0x7F; /* Get the wimg and pp */
952 ppn
= (xpteg
[slot
+ 2] << 20) | (xpteg
[slot
+ 3] >> 12); /* Get physical page number */
953 slotoff
= (i
* 128) + (j
* 16) | 1; /* Get offset to slot and valid bit */
956 pmap
= pmapTrans
[space
].pmapVAddr
; /* Find the pmap address */
957 if(!pmap
) { /* The pmap is not in use */
958 db_printf("The space %08X is not assigned to a pmap, slot = %d\n", space
, slot
); /* Say we are wrong */
963 if (pmap
->pmapFlags
& pmapVMgsaa
) {
966 ret
= hw_find_map_gv(pmap
, llva
, &mpcopy
);
968 mp
= hw_find_map(pmap
, llva
, &lnextva
); /* Try to find the mapping for this address */
969 // db_printf("%08X - %017llX\n", mp, llva);
970 if((unsigned int)mp
== mapRtBadLk
) { /* Did we lock up ok? */
971 db_printf("Timeout locking mapping for for virtual address %016ll8X, slot = %d\n", llva
, j
);
975 if(!mp
) { /* Did we find one? */
976 db_printf("Not mapped, slot = %d, va = %08X\n", j
, (unsigned int)llva
);
981 if((mp
->mpFlags
& 0xFF000000) > 0x01000000) { /* Is busy count too high? */
982 db_printf("Busy count too high, slot = %d\n", j
);
986 if((mp
->mpFlags
& mpType
) == mpBlock
) { /* Is this a block map? */
987 if(!(xpca
[0] & xauto
)) { /* Is it marked as such? */
988 db_printf("mapping marked as block, PCA is not, slot = %d\n", j
);
992 else { /* Is a block */
993 if(xpca
[0] & xauto
) { /* Is it marked as such? */
994 db_printf("mapping not marked as block, PCA is, slot = %d\n", j
);
997 if(mp
->mpPte
!= slotoff
) { /* See if mapping PTEG offset is us */
998 db_printf("mapping does not point to PTE, slot = %d\n", j
);
1003 wimgkk
= (unsigned int)mp
->mpVAddr
; /* Get last half of vaddr where keys, etc are */
1004 wimgkk
= (wimgkk
^ wimgxx
) & 0x7F; /* XOR to find differences from PTE */
1005 if(wimgkk
) { /* See if key in PTE is what we want */
1006 db_printf("key or WIMG does not match, slot = %d\n", j
);
1010 aoff
= (ppnum_t
)((llva
>> 12) - (mp
->mpVAddr
>> 12)); /* Get the offset from vaddr */
1011 pa
= aoff
+ mp
->mpPAddr
; /* Get the physical page number we expect */
1012 if(pa
!= ppn
) { /* Is physical address expected? */
1013 db_printf("Physical address does not match, slot = %d\n", j
);
1017 mapping_drop_busy(mp
); /* We're done with the mapping */
1028 if(fnderr
)db_dumppca(i
); /* Print if error */
1030 pteg
= pteg
+ 64; /* Go to the next one */
1031 if(s4bit
) pteg
= pteg
+ 64; /* Hagfish? */
1032 pca
= pca
- 4; /* Go to the next one */
1041 * Displays all of the kmods in the system.
1045 void db_display_kmod(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
1048 unsigned int strt
, end
;
1050 kmd
= kmod
; /* Start at the start */
1052 db_printf("info addr start - end name ver\n");
1054 while(kmd
) { /* Dump 'em all */
1055 strt
= (unsigned int)kmd
->address
+ kmd
->hdr_size
; /* Get start of kmod text */
1056 end
= (unsigned int)kmd
->address
+ kmd
->size
; /* Get end of kmod */
1057 db_printf("%08X %08X %08X - %08X: %s, %s\n", kmd
, kmd
->address
, strt
, end
,
1058 kmd
->name
, kmd
->version
);
1059 kmd
= kmd
->next
; /* Step to it */
1070 unsigned 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};
1072 void db_gsnoop(db_expr_t addr
, int have_addr
, db_expr_t count
, char * modif
) {
1075 unsigned char *gp
, gpn
[36];
1078 gp
= (unsigned char *)0x8000005C;
1080 for(i
= 0; i
< ngpr
; i
++) gpn
[i
] = gp
[i
]; /* Copy 'em */
1082 for(i
= 0; i
< ngpr
; i
++) {
1083 db_printf("%02X ", gpn
[i
]);
1087 for(i
= 0; i
< ngpr
; i
++) {
1088 if(gpn
[i
] != xxgpo
[i
]) db_printf("^^ ");
1089 else db_printf(" ");
1093 for(i
= 0; i
< ngpr
; i
++) xxgpo
[i
] = gpn
[i
]; /* Save 'em */