]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
2d21ac55 | 2 | * Copyright (c) 2000-2007 Apple Inc. All rights reserved. |
1c79356b | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
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> | |
1c79356b | 67 | #include <ppc/savearea.h> |
9bccf70c | 68 | #include <ppc/vmachmon.h> |
1c79356b | 69 | |
55e303ae | 70 | void db_dumppca(unsigned int ptegindex); |
1c79356b | 71 | void db_dumpmapping(struct mapping *mp); /* Dump out a mapping */ |
1c79356b A |
72 | extern kmod_info_t *kmod; /* Find the kmods */ |
73 | ||
74 | db_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 | */ | |
2d21ac55 A |
86 | void |
87 | db_low_trace(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif) | |
88 | { | |
1c79356b A |
89 | int c, i; |
90 | unsigned int tempx, cnt; | |
55e303ae | 91 | unsigned int xTraceCurr, xTraceStart, xTraceEnd, cxltr; |
1c79356b A |
92 | db_addr_t next_addr; |
93 | LowTraceRecord xltr; | |
94 | unsigned char cmark; | |
55e303ae | 95 | addr64_t xxltr; |
1c79356b A |
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 | ||
55e303ae A |
115 | if((unsigned int)addr&0x0000007F) { /* Proper alignment? */ |
116 | db_printf("address not aligned on trace entry boundary (0x80)\n"); /* Tell 'em */ | |
1c79356b A |
117 | return; /* Leave... */ |
118 | } | |
119 | ||
55e303ae A |
120 | xxltr = addr; /* Set the start */ |
121 | cxltr = ((xTraceCurr == xTraceStart ? xTraceEnd : xTraceCurr) - sizeof(LowTraceRecord)); /* Get address of newest entry */ | |
1c79356b A |
122 | |
123 | db_low_trace_prev = addr; /* Starting point */ | |
124 | ||
125 | for(i=0; i < cnt; i++) { /* Dump the 16 (or all) entries */ | |
126 | ||
55e303ae A |
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 */ | |
1c79356b | 131 | |
a3d08fcd | 132 | db_printf("\n%s%08llX %1X %08X %08X - %04X", (xxltr != cxltr ? " " : "*"), |
1c79356b | 133 | xxltr, |
a3d08fcd | 134 | (xltr.LTR_cpu & 0xFF), xltr.LTR_timeHi, xltr.LTR_timeLo, |
55e303ae | 135 | (xltr.LTR_excpt & 0x8000 ? 0xFFFF : xltr.LTR_excpt * 64)); /* Print the first line */ |
a3d08fcd A |
136 | |
137 | if(xltr.LTR_cpu & 0xFF00) db_printf(", sflgs = %02X\n", ((xltr.LTR_cpu >> 8) & 0xFF)); | |
138 | else db_printf("\n"); | |
55e303ae A |
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); | |
1c79356b A |
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); | |
1c79356b A |
157 | } |
158 | ||
159 | ||
160 | /* | |
161 | * Print out 256 bytes | |
162 | * | |
163 | * | |
164 | * dl [entaddr] | |
165 | */ | |
2d21ac55 A |
166 | void |
167 | db_display_long(db_expr_t addr, __unused boolean_t have_addr, | |
168 | db_expr_t count, char * modif) | |
169 | { | |
1c79356b A |
170 | int i; |
171 | ||
172 | for(i=0; i<8; i++) { /* Print 256 bytes */ | |
55e303ae | 173 | db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */ |
1c79356b A |
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]); | |
55e303ae | 176 | addr=(db_expr_t)(addr+0x00000020); /* Point to next address */ |
1c79356b A |
177 | } |
178 | db_next = addr; | |
179 | ||
180 | ||
55e303ae A |
181 | } |
182 | ||
183 | unsigned 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 | */ | |
2d21ac55 A |
209 | void |
210 | db_display_char(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
211 | char * modif) | |
212 | { | |
55e303ae A |
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 | ||
1c79356b A |
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 | */ | |
2d21ac55 A |
248 | void |
249 | db_display_real(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
250 | char *modif) | |
251 | { | |
1c79356b A |
252 | int i; |
253 | unsigned int xbuf[8]; | |
254 | ||
255 | for(i=0; i<8; i++) { /* Print 256 bytes */ | |
55e303ae A |
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 */ | |
1c79356b A |
258 | xbuf[0], xbuf[1], xbuf[2], xbuf[3], |
259 | xbuf[4], xbuf[5], xbuf[6], xbuf[7]); | |
55e303ae | 260 | addr = addr + 0x00000020; /* Point to next address */ |
1c79356b A |
261 | } |
262 | db_next = addr; | |
1c79356b A |
263 | } |
264 | ||
265 | unsigned int dvspace = 0; | |
266 | ||
267 | /* | |
268 | * Print out virtual to real translation information | |
269 | * | |
270 | * | |
271 | * dm vaddr [space] (defaults to last entered) | |
272 | */ | |
2d21ac55 A |
273 | void |
274 | db_display_mappings(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
275 | char *modif) | |
276 | { | |
55e303ae A |
277 | db_expr_t xspace; |
278 | pmap_t pmap; | |
279 | addr64_t lnextva; | |
1c79356b | 280 | |
91447636 | 281 | mapping_t *mp; |
55e303ae A |
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 | } | |
1c79356b | 290 | |
55e303ae A |
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 | } | |
1c79356b | 304 | |
1c79356b A |
305 | if(!mp) { /* Did we find one? */ |
306 | db_printf("Not mapped\n"); | |
307 | return; /* Didn't find any, return FALSE... */ | |
308 | } | |
55e303ae A |
309 | |
310 | mapping_drop_busy(mp); /* The mapping shouldn't be changing */ | |
311 | ||
312 | db_dumpmapping(mp); /* Dump it all out */ | |
313 | ||
2d21ac55 | 314 | /* Tell them we did it */ |
55e303ae A |
315 | } |
316 | ||
317 | /* | |
318 | * Print out hash table data | |
319 | * | |
320 | * | |
321 | * dh vaddr [space] (defaults to last entered) | |
322 | */ | |
2d21ac55 A |
323 | void |
324 | db_display_hash(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
325 | char *modif) | |
326 | { | |
55e303ae A |
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 | ||
91447636 | 336 | s4bit = !((PerProcTable[0].ppe_vaddr->pf.Available & pf64Bit) == 0); /* Are we a big guy? */ |
55e303ae A |
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 */ | |
1c79356b | 343 | } |
55e303ae A |
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; | |
1c79356b | 349 | } |
55e303ae A |
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 | ||
2d21ac55 | 363 | /* Tell them we did it */ |
1c79356b A |
364 | } |
365 | ||
366 | /* | |
367 | * Displays all of the in-use pmaps in the system. | |
368 | * | |
369 | * dp | |
370 | */ | |
2d21ac55 A |
371 | void |
372 | db_display_pmap(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
373 | char *modif) | |
374 | { | |
1c79356b | 375 | pmap_t pmap; |
55e303ae A |
376 | int i; |
377 | unsigned int v0, v1, st0, st1; | |
1c79356b | 378 | |
55e303ae A |
379 | pmap = (pmap_t)addr; |
380 | if(!have_addr) pmap = kernel_pmap; /* Start at the beginning */ | |
1c79356b | 381 | |
55e303ae A |
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 | |
1c79356b | 384 | while(1) { /* Do them all */ |
55e303ae A |
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, | |
1c79356b A |
389 | pmap->stats.resident_count, |
390 | pmap->stats.wired_count); | |
391 | ||
55e303ae A |
392 | db_printf("lists = %d, rand = %08X, visits = %016llX, searches = %08X\n", |
393 | pmap->pmapCurLists, pmap->pmapRandNum, | |
394 | pmap->pmapSearchVisits, pmap->pmapSearchCnt); | |
1c79356b | 395 | |
55e303ae A |
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 | } | |
1c79356b | 409 | |
de355530 | 410 | db_printf("\n"); |
55e303ae A |
411 | if(have_addr) break; /* Do only one if address supplied */ |
412 | pmap = (pmap_t)pmap->pmap_link.next; /* Skip to the next */ | |
1c79356b A |
413 | if(pmap == kernel_pmap) break; /* We've wrapped, we're done */ |
414 | } | |
1c79356b A |
415 | } |
416 | ||
1c79356b | 417 | |
55e303ae A |
418 | /* |
419 | * Checks the pmap skip lists | |
420 | * | |
421 | * | |
422 | * cp pmap | |
423 | */ | |
2d21ac55 A |
424 | void |
425 | db_check_pmaps(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
426 | char *modif) | |
427 | { | |
55e303ae A |
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 | } | |
1c79356b A |
450 | } |
451 | ||
55e303ae | 452 | |
1c79356b | 453 | /* |
55e303ae | 454 | * Displays iokit junk |
1c79356b | 455 | * |
3a60a9f5 | 456 | * di |
1c79356b | 457 | */ |
1c79356b | 458 | |
55e303ae A |
459 | void db_piokjunk(void); |
460 | ||
2d21ac55 A |
461 | void |
462 | db_display_iokit(__unused db_expr_t addr, __unused boolean_t have_addr, | |
463 | __unused db_expr_t count, __unused char *modif) | |
464 | { | |
55e303ae | 465 | db_piokjunk(); |
1c79356b A |
466 | } |
467 | ||
468 | /* | |
55e303ae | 469 | * Prints out a mapping control block |
1c79356b A |
470 | * |
471 | */ | |
472 | ||
55e303ae A |
473 | void 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); | |
91447636 | 482 | db_printf(" mpBSize: %04X\n", mp->u.mpBSize); |
55e303ae A |
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 | } | |
1c79356b A |
492 | } |
493 | ||
494 | /* | |
55e303ae A |
495 | * Prints out a PTEG and PCA |
496 | * | |
1c79356b A |
497 | */ |
498 | ||
55e303ae A |
499 | void 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 | ||
91447636 | 506 | s4bit = !((PerProcTable[0].ppe_vaddr->pf.Available & pf64Bit) == 0); /* Are we a big guy? */ |
55e303ae A |
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); | |
de355530 | 512 | |
55e303ae A |
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 */ | |
a3d08fcd | 550 | llhash = llhash & 0x0000001FFFFFFFFFULL; /* Make sure we stay within supported ranges */ |
55e303ae A |
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 | } | |
1c79356b A |
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 | */ | |
2d21ac55 A |
568 | void |
569 | db_display_virtual(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
570 | char *modif) | |
571 | { | |
1c79356b | 572 | |
55e303ae | 573 | int i, size, lines, rlines; |
1c79356b | 574 | unsigned int xbuf[8]; |
55e303ae A |
575 | db_expr_t xspace; |
576 | pmap_t pmap; | |
1c79356b | 577 | |
91447636 | 578 | mapping_t *mp, *mpv; |
55e303ae A |
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 | } | |
1c79356b | 589 | |
55e303ae A |
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 | } | |
1c79356b | 595 | |
55e303ae | 596 | addr &= -32; |
1c79356b A |
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 | ||
55e303ae A |
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? */ | |
1c79356b A |
608 | db_printf("Not mapped\n"); |
609 | return; /* Didn't find any, return FALSE... */ | |
610 | } | |
55e303ae A |
611 | |
612 | pa = (addr64_t)(pnum << 12) | (addr64_t)(addr & 0xFFF); /* Get the physical address */ | |
613 | db_printf("phys = %016llX\n", pa); | |
614 | ||
1c79356b | 615 | for(i=0; i<lines; i++) { /* Print n bytes */ |
55e303ae A |
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 */ | |
1c79356b A |
618 | xbuf[0], xbuf[1], xbuf[2], xbuf[3], |
619 | xbuf[4], xbuf[5], xbuf[6], xbuf[7]); | |
91447636 | 620 | addr = (db_expr_t)(addr + 0x00000020); /* Point to next address */ |
55e303ae | 621 | pa = pa + 0x00000020; /* Point to next address */ |
1c79356b A |
622 | } |
623 | db_next = addr; | |
624 | ||
625 | if(!rlines) return; | |
626 | ||
55e303ae A |
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? */ | |
1c79356b A |
631 | db_printf("Not mapped\n"); |
632 | return; /* Didn't find any, return FALSE... */ | |
633 | } | |
55e303ae A |
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 | ||
1c79356b | 638 | for(i=0; i<rlines; i++) { /* Print n bytes */ |
55e303ae A |
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 */ | |
1c79356b A |
641 | xbuf[0], xbuf[1], xbuf[2], xbuf[3], |
642 | xbuf[4], xbuf[5], xbuf[6], xbuf[7]); | |
55e303ae A |
643 | addr = (db_expr_t)(addr + 0x00000020); /* Point to next address */ |
644 | pa = pa + 0x00000020; /* Point to next address */ | |
1c79356b A |
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 | ||
2d21ac55 A |
661 | void |
662 | db_display_save(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
663 | char *modif) | |
664 | { | |
9bccf70c | 665 | int i, j, totsaves, tottasks, taskact, chainsize, vmid, didvmhead; |
1c79356b A |
666 | task_t task; |
667 | thread_act_t act; | |
2d21ac55 | 668 | struct savearea *save; |
9bccf70c | 669 | vmmCntrlTable *CTable; |
1c79356b A |
670 | |
671 | tottasks = 0; | |
672 | totsaves = 0; | |
673 | ||
2d21ac55 | 674 | for(task = (task_t)tasks.next; task != (task_t)&tasks.next; task = (task_t)task->tasks.next) { /* Go through the tasks */ |
1c79356b A |
675 | taskact = 0; /* Reset activation count */ |
676 | db_printf("\nTask %4d @%08X:\n", tottasks, task); /* Show where we're at */ | |
55e303ae | 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 */ |
9bccf70c | 678 | db_printf(" Act %4d @%08X - p: %08X current context: %08X\n", |
91447636 | 679 | taskact, act, act->machine.pcb, act->machine.curctx); |
1c79356b | 680 | |
2d21ac55 | 681 | save = (struct savearea *)act->machine.pcb; /* Set the start of the normal chain */ |
1c79356b | 682 | chainsize = 0; |
9bccf70c A |
683 | |
684 | db_printf(" General context - fp: %08X fl: %08X fc: %d vp: %08X vl: %08X vp: %d\n", | |
91447636 A |
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); | |
9bccf70c | 687 | |
1c79356b A |
688 | while(save) { /* Do them all */ |
689 | totsaves++; /* Count savearea */ | |
55e303ae | 690 | db_printf(" Norm %08X: %016llX %016llX - tot = %d\n", save, save->save_srr0, save->save_srr1, totsaves); |
2d21ac55 | 691 | save = (struct savearea *)save->save_hdr.save_prev; /* Next one */ |
1c79356b | 692 | if(chainsize++ > chainmax) { /* See if we might be in a loop */ |
9bccf70c | 693 | db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save); |
1c79356b A |
694 | break; |
695 | } | |
696 | } | |
697 | ||
2d21ac55 | 698 | save = (struct savearea *)act->machine.facctx.FPUsave; /* Set the start of the floating point chain */ |
1c79356b A |
699 | chainsize = 0; |
700 | while(save) { /* Do them all */ | |
9bccf70c A |
701 | totsaves++; /* Count savearea */ |
702 | db_printf(" FPU %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves); | |
2d21ac55 | 703 | save = (struct savearea *)save->save_hdr.save_prev; /* Next one */ |
1c79356b | 704 | if(chainsize++ > chainmax) { /* See if we might be in a loop */ |
9bccf70c | 705 | db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save); |
1c79356b A |
706 | break; |
707 | } | |
708 | } | |
709 | ||
2d21ac55 | 710 | save = (struct savearea *)act->machine.facctx.VMXsave; /* Set the start of the floating point chain */ |
1c79356b A |
711 | chainsize = 0; |
712 | while(save) { /* Do them all */ | |
9bccf70c A |
713 | totsaves++; /* Count savearea */ |
714 | db_printf(" Vec %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves); | |
2d21ac55 | 715 | save = (struct savearea *)save->save_hdr.save_prev; /* Next one */ |
1c79356b | 716 | if(chainsize++ > chainmax) { /* See if we might be in a loop */ |
9bccf70c | 717 | db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save); |
1c79356b A |
718 | break; |
719 | } | |
720 | } | |
9bccf70c | 721 | |
91447636 | 722 | if(CTable = act->machine.vmmControl) { /* Are there virtual machines? */ |
9bccf70c | 723 | |
55e303ae | 724 | for(vmid = 0; vmid < kVmmMaxContexts; vmid++) { |
9bccf70c A |
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 | ||
2d21ac55 | 735 | save = (struct savearea *)CTable->vmmc[vmid].vmmFacCtx.FPUsave; /* Set the start of the floating point chain */ |
9bccf70c A |
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); | |
2d21ac55 | 740 | save = (struct savearea *)save->save_hdr.save_prev; /* Next one */ |
9bccf70c A |
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 | ||
2d21ac55 | 747 | save = (struct savearea *)CTable->vmmc[vmid].vmmFacCtx.VMXsave; /* Set the start of the floating point chain */ |
9bccf70c A |
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); | |
2d21ac55 | 752 | save = (struct savearea *)save->save_hdr.save_prev; /* Next one */ |
9bccf70c A |
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 | } | |
1c79356b A |
760 | taskact++; |
761 | } | |
762 | tottasks++; | |
763 | } | |
764 | ||
765 | db_printf("Total saveareas accounted for: %d\n", totsaves); | |
1c79356b A |
766 | } |
767 | ||
768 | /* | |
769 | * Print out extra registers | |
770 | * | |
771 | * | |
772 | * dx | |
773 | */ | |
774 | ||
775 | extern unsigned int dbfloats[33][2]; | |
776 | extern unsigned int dbvecs[33][4]; | |
91447636 | 777 | extern unsigned int dbspecrs[336]; |
1c79356b | 778 | |
2d21ac55 A |
779 | void |
780 | db_display_xregs(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
781 | char *modif) | |
782 | { | |
1c79356b A |
783 | int i, j, pents; |
784 | ||
785 | stSpecrs(dbspecrs); /* Save special registers */ | |
91447636 | 786 | if(PerProcTable[0].ppe_vaddr->pf.Available & pf64Bit) { |
a3d08fcd A |
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 | } | |
1c79356b A |
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 | ||
2d21ac55 | 851 | /* Tell them we did it */ |
1c79356b A |
852 | } |
853 | ||
55e303ae A |
854 | /* |
855 | * Check check mappings and hash table for consistency | |
856 | * | |
857 | * cm | |
858 | */ | |
2d21ac55 A |
859 | void |
860 | db_check_mappings(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
861 | char *modif) | |
862 | { | |
55e303ae A |
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; | |
91447636 | 867 | mapping_t *mp; |
55e303ae A |
868 | ppnum_t ppn, pa, aoff; |
869 | unsigned long long llslot, llseg, llhash; | |
870 | ||
871 | s4bit = 0; /* Assume dinky? */ | |
91447636 | 872 | if(PerProcTable[0].ppe_vaddr->pf.Available & pf64Bit) s4bit = 1; /* Are we a big guy? */ |
55e303ae A |
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 */ | |
a3d08fcd | 954 | llhash = llhash & 0x0000001FFFFFFFFFULL; /* Make sure we stay within supported ranges */ |
55e303ae A |
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 | } | |
91447636 A |
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; | |
55e303ae | 981 | } |
91447636 A |
982 | |
983 | if(!mp) { /* Did we find one? */ | |
984 | db_printf("Not mapped, slot = %d, va = %08X\n", j, (unsigned int)llva); | |
55e303ae | 985 | fnderr = 1; |
91447636 | 986 | goto dcmout; |
55e303ae | 987 | } |
91447636 A |
988 | |
989 | if((mp->mpFlags & 0xFF000000) > 0x01000000) { /* Is busy count too high? */ | |
990 | db_printf("Busy count too high, slot = %d\n", j); | |
55e303ae A |
991 | fnderr = 1; |
992 | } | |
91447636 A |
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 | } | |
55e303ae | 1010 | |
91447636 A |
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 */ | |
55e303ae | 1026 | } |
55e303ae A |
1027 | } |
1028 | ||
1029 | } | |
1030 | dcmout: | |
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 | } | |
55e303ae A |
1044 | } |
1045 | ||
1c79356b A |
1046 | /* |
1047 | * Displays all of the kmods in the system. | |
1048 | * | |
1049 | * dp | |
1050 | */ | |
2d21ac55 A |
1051 | void |
1052 | db_display_kmod(db_expr_t addr, boolean_t have_addr, db_expr_t count, | |
1053 | char *modif) | |
1054 | { | |
1c79356b A |
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 | } | |
1c79356b A |
1069 | } |
1070 | ||
1071 | /* | |
1072 | * Displays stuff | |
1073 | * | |
1074 | * gs | |
1075 | */ | |
1076 | 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}; | |
1077 | ||
2d21ac55 A |
1078 | void |
1079 | db_gsnoop(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif) | |
1080 | { | |
1c79356b A |
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 */ | |
1c79356b A |
1101 | } |
1102 | ||
1103 | ||
1104 | void Dumbo(void); | |
1105 | void Dumbo(void){ | |
1106 | } |