]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
23 | * @OSF_FREE_COPYRIGHT@ | |
24 | */ | |
25 | /* | |
26 | * @APPLE_FREE_COPYRIGHT@ | |
27 | */ | |
28 | ||
29 | /* | |
30 | * Author: Bill Angell, Apple | |
31 | * Date: 6/97 | |
32 | * | |
33 | * exceptions and certain C functions write into a trace table which | |
34 | * can be examined via the machine 'lt' command under kdb | |
35 | */ | |
36 | ||
37 | ||
38 | #include <string.h> /* For strcpy() */ | |
39 | #include <mach/boolean.h> | |
40 | #include <machine/db_machdep.h> | |
41 | ||
42 | #include <ddb/db_access.h> | |
43 | #include <ddb/db_lex.h> | |
44 | #include <ddb/db_output.h> | |
45 | #include <ddb/db_command.h> | |
46 | #include <ddb/db_sym.h> | |
47 | #include <ddb/db_task_thread.h> | |
48 | #include <ddb/db_command.h> /* For db_option() */ | |
49 | #include <ddb/db_examine.h> | |
50 | #include <ddb/db_expr.h> | |
51 | #include <kern/thread.h> | |
52 | #include <kern/task.h> | |
53 | #include <mach/vm_param.h> | |
54 | #include <mach/kmod.h> | |
55 | #include <ppc/Firmware.h> | |
56 | #include <ppc/low_trace.h> | |
57 | #include <ppc/db_low_trace.h> | |
58 | #include <ppc/mappings.h> | |
59 | #include <ppc/pmap.h> | |
60 | #include <ppc/mem.h> | |
61 | #include <ppc/pmap_internals.h> | |
62 | #include <ppc/savearea.h> | |
63 | ||
64 | void db_dumpphys(struct phys_entry *pp); /* Dump from physent */ | |
65 | void db_dumppca(struct mapping *mp); /* PCA */ | |
66 | void db_dumpmapping(struct mapping *mp); /* Dump out a mapping */ | |
67 | void db_dumppmap(pmap_t pmap); /* Dump out a pmap */ | |
68 | extern kmod_info_t *kmod; /* Find the kmods */ | |
69 | ||
70 | db_addr_t db_low_trace_prev = 0; | |
71 | ||
72 | /* | |
73 | * Print out the low level trace table: | |
74 | * | |
75 | * Displays the entry and 15 before it in newest to oldest order | |
76 | * | |
77 | * lt [entaddr] | |
78 | ||
79 | * If entaddr is omitted, it starts with the most current | |
80 | * If entaddr = 0, it starts with the most current and does the whole table | |
81 | */ | |
82 | void db_low_trace(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
83 | ||
84 | int c, i; | |
85 | unsigned int tempx, cnt; | |
86 | unsigned int xbuf[8]; | |
87 | unsigned int xTraceCurr, xTraceStart, xTraceEnd, cxltr, xxltr; | |
88 | db_addr_t next_addr; | |
89 | LowTraceRecord xltr; | |
90 | unsigned char cmark; | |
91 | ||
92 | cnt = 16; /* Default to 16 entries */ | |
93 | ||
94 | xTraceCurr = trcWork.traceCurr; /* Transfer current pointer */ | |
95 | xTraceStart = trcWork.traceStart; /* Transfer start of table */ | |
96 | xTraceEnd = trcWork.traceEnd; /* Transfer end of table */ | |
97 | ||
98 | if(addr == -1) cnt = 0x7FFFFFFF; /* Max the count */ | |
99 | ||
100 | if(!addr || (addr == -1)) { | |
101 | addr=xTraceCurr-sizeof(LowTraceRecord); /* Start at the newest */ | |
102 | if((unsigned int)addr<xTraceStart) addr=xTraceEnd-sizeof(LowTraceRecord); /* Wrap low back to high */ | |
103 | } | |
104 | ||
105 | if((unsigned int)addr<xTraceStart||(unsigned int)addr>=xTraceEnd) { /* In the table? */ | |
106 | db_printf("address not in low memory trace table\n"); /* Tell the fool */ | |
107 | return; /* Leave... */ | |
108 | } | |
109 | ||
110 | if((unsigned int)addr&0x0000003F) { /* Proper alignment? */ | |
111 | db_printf("address not aligned on trace entry boundary (0x40)\n"); /* Tell 'em */ | |
112 | return; /* Leave... */ | |
113 | } | |
114 | ||
115 | xxltr=(unsigned int)addr; /* Set the start */ | |
116 | cxltr=((xTraceCurr==xTraceStart ? xTraceEnd : xTraceCurr)-sizeof(LowTraceRecord)); /* Get address of newest entry */ | |
117 | ||
118 | db_low_trace_prev = addr; /* Starting point */ | |
119 | ||
120 | for(i=0; i < cnt; i++) { /* Dump the 16 (or all) entries */ | |
121 | ||
122 | ReadReal(xxltr, (unsigned int *)&xltr); /* Get the first half */ | |
123 | ReadReal(xxltr+32, &(((unsigned int *)&xltr)[8])); /* Get the second half */ | |
124 | ||
125 | db_printf("\n%s%08X %1X %08X %08X - %04X\n", (xxltr!=cxltr ? " " : "*"), | |
126 | xxltr, | |
127 | xltr.LTR_cpu, xltr.LTR_timeHi, xltr.LTR_timeLo, | |
128 | (xltr.LTR_excpt&0x8000 ? 0xFFFF : xltr.LTR_excpt*64)); /* Print the first line */ | |
129 | db_printf(" %08X %08X %08X %08X %08X %08X %08X\n", | |
130 | xltr.LTR_cr, xltr.LTR_srr0, xltr.LTR_srr1, xltr.LTR_dar, xltr.LTR_save, xltr.LTR_lr, xltr.LTR_ctr); | |
131 | db_printf(" %08X %08X %08X %08X %08X %08X\n", | |
132 | xltr.LTR_r0, xltr.LTR_r1, xltr.LTR_r2, xltr.LTR_r3, xltr.LTR_r4, xltr.LTR_r5); | |
133 | ||
134 | if((cnt != 16) && (xxltr == xTraceCurr)) break; /* If whole table dump, exit when we hit start again... */ | |
135 | ||
136 | xxltr-=sizeof(LowTraceRecord); /* Back it on up */ | |
137 | if(xxltr<xTraceStart) | |
138 | xxltr=(xTraceEnd-sizeof(LowTraceRecord)); /* Wrap low back to high */ | |
139 | ||
140 | } | |
141 | db_next = (db_expr_t)(xxltr); | |
142 | return; | |
143 | } | |
144 | ||
145 | ||
146 | /* | |
147 | * Print out 256 bytes | |
148 | * | |
149 | * | |
150 | * dl [entaddr] | |
151 | */ | |
152 | void db_display_long(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
153 | ||
154 | int i; | |
155 | ||
156 | for(i=0; i<8; i++) { /* Print 256 bytes */ | |
157 | db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */ | |
158 | ((unsigned long *)addr)[0], ((unsigned long *)addr)[1], ((unsigned long *)addr)[2], ((unsigned long *)addr)[3], | |
159 | ((unsigned long *)addr)[4], ((unsigned long *)addr)[5], ((unsigned long *)addr)[6], ((unsigned long *)addr)[7]); | |
160 | addr=(db_expr_t)((unsigned int)addr+0x00000020); /* Point to next address */ | |
161 | } | |
162 | db_next = addr; | |
163 | ||
164 | ||
165 | } | |
166 | ||
167 | /* | |
168 | * Print out 256 bytes of real storage | |
169 | * | |
170 | * Displays the entry and 15 before it in newest to oldest order | |
171 | * | |
172 | * dr [entaddr] | |
173 | */ | |
174 | void db_display_real(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
175 | ||
176 | int i; | |
177 | unsigned int xbuf[8]; | |
178 | ||
179 | for(i=0; i<8; i++) { /* Print 256 bytes */ | |
180 | ReadReal((unsigned int)addr, &xbuf[0]); /* Get the real storage data */ | |
181 | db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */ | |
182 | xbuf[0], xbuf[1], xbuf[2], xbuf[3], | |
183 | xbuf[4], xbuf[5], xbuf[6], xbuf[7]); | |
184 | addr=(db_expr_t)((unsigned int)addr+0x00000020); /* Point to next address */ | |
185 | } | |
186 | db_next = addr; | |
187 | ||
188 | ||
189 | } | |
190 | ||
191 | unsigned int dvspace = 0; | |
192 | ||
193 | /* | |
194 | * Print out virtual to real translation information | |
195 | * | |
196 | * | |
197 | * dm vaddr [space] (defaults to last entered) | |
198 | */ | |
199 | void db_display_mappings(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
200 | ||
201 | int i; | |
202 | unsigned int xspace; | |
203 | ||
204 | mapping *mp, *mpv; | |
205 | vm_offset_t pa; | |
206 | ||
207 | if (db_expression(&xspace)) dvspace = xspace; /* Get the space or set default */ | |
208 | ||
209 | db_printf("mapping information for %08X in space %08X:\n", addr, dvspace); | |
210 | mp = hw_lock_phys_vir(dvspace, addr); /* Lock the physical entry for this mapping */ | |
211 | if(!mp) { /* Did we find one? */ | |
212 | db_printf("Not mapped\n"); | |
213 | return; /* Didn't find any, return FALSE... */ | |
214 | } | |
215 | if((unsigned int)mp&1) { /* Did we timeout? */ | |
216 | db_printf("Timeout locking physical entry for virtual address (%08X)\n", addr); /* Yeah, scream about it! */ | |
217 | return; /* Bad hair day, return FALSE... */ | |
218 | } | |
219 | printf("dumpaddr: space=%08X; vaddr=%08X\n", dvspace, addr); /* Say what address were dumping */ | |
220 | mpv = hw_cpv(mp); /* Get virtual address of mapping */ | |
221 | dumpmapping(mpv); | |
222 | if(mpv->physent) { | |
223 | hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Unlock physical entry associated with mapping */ | |
224 | } | |
225 | return; /* Tell them we did it */ | |
226 | ||
227 | ||
228 | } | |
229 | ||
230 | /* | |
231 | * Displays all of the in-use pmaps in the system. | |
232 | * | |
233 | * dp | |
234 | */ | |
235 | void db_display_pmap(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
236 | ||
237 | pmap_t pmap; | |
238 | ||
239 | pmap = kernel_pmap; /* Start at the beginning */ | |
240 | ||
241 | db_printf("PMAP (real) Next Prev VRMask Space Bmaps Flags Ref spaceNum Resident Wired\n"); | |
242 | // xxxxxxxx rrrrrrrr xxxxxxxx pppppppp vvvvvvvv ssssssss bbbbbbbb cccccccc vvvvvvvv nnnnnnnn rrrrrrrr wwwwwwwww | |
243 | while(1) { /* Do them all */ | |
244 | db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X %08X %08X %08X\n", | |
245 | pmap, (unsigned int)pmap ^ pmap->pmapvr, | |
246 | pmap->pmap_link.next, pmap->pmap_link.prev, pmap->pmapvr, | |
247 | pmap->space, pmap->bmaps, pmap->vflags, pmap->ref_count, pmap->spaceNum, | |
248 | pmap->stats.resident_count, | |
249 | pmap->stats.wired_count); | |
250 | ||
251 | ||
252 | // xxxxxxxx rrrrrrrr xxxxxxxx pppppppp vvvvvvvv ssssssss bbbbbbbb cccccccc vvvvvvvv nnnnnnnn rrrrrrrr wwwwwwwww | |
253 | db_printf(" SRs: %08X %08X %08X %08X %08X %08X %08X %08X\n", pmap->pmapSegs[0], pmap->pmapSegs[1], pmap->pmapSegs[2], pmap->pmapSegs[3], | |
254 | pmap->pmapSegs[4], pmap->pmapSegs[5], pmap->pmapSegs[6], pmap->pmapSegs[7]); | |
255 | db_printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", pmap->pmapSegs[8], pmap->pmapSegs[9], pmap->pmapSegs[10], pmap->pmapSegs[11], | |
256 | pmap->pmapSegs[12], pmap->pmapSegs[13], pmap->pmapSegs[14], pmap->pmapSegs[15]); | |
257 | ||
258 | db_printf(" spmaps: %08X %08X %08X %08X %08X %08X %08X %08X\n", pmap->pmapPmaps[0], pmap->pmapPmaps[1], pmap->pmapPmaps[2], pmap->pmapPmaps[3], | |
259 | pmap->pmapPmaps[4], pmap->pmapPmaps[5], pmap->pmapPmaps[6], pmap->pmapPmaps[7]); | |
260 | db_printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", pmap->pmapPmaps[8], pmap->pmapPmaps[9], pmap->pmapPmaps[10], pmap->pmapPmaps[11], | |
261 | pmap->pmapPmaps[12], pmap->pmapPmaps[13], pmap->pmapPmaps[14], pmap->pmapPmaps[15]); | |
262 | ||
263 | pmap = (pmap_t)pmap->pmap_link.next; /* Skip to the next */ | |
264 | db_printf("\n"); | |
265 | if(pmap == kernel_pmap) break; /* We've wrapped, we're done */ | |
266 | } | |
267 | return; | |
268 | } | |
269 | ||
270 | /* | |
271 | * print information about the passed in pmap block | |
272 | */ | |
273 | ||
274 | void db_dumppmap(pmap_t pmap) { | |
275 | ||
276 | db_printf("Dump of pmap block: %08X\n", pmap); | |
277 | db_printf(" pmap_link: %08X %08X\n", pmap->pmap_link.next, pmap->pmap_link.prev); | |
278 | db_printf(" pmapvr: %08X\n", pmap->pmapvr); | |
279 | db_printf(" space: %08X\n", pmap->space); | |
280 | db_printf(" bmaps: %08X\n", pmap->bmaps); | |
281 | db_printf(" ref_count: %08X\n", pmap->ref_count); | |
282 | db_printf(" spaceNum: %08X\n", pmap->spaceNum); | |
283 | db_printf(" resident_count: %08X\n", pmap->stats.resident_count); | |
284 | db_printf(" wired_count: %08X\n", pmap->stats.wired_count); | |
285 | db_printf("\n"); | |
286 | ||
287 | return; | |
288 | ||
289 | } | |
290 | ||
291 | /* | |
292 | * Prints out a mapping control block | |
293 | * | |
294 | */ | |
295 | ||
296 | void db_dumpmapping(struct mapping *mp) { /* Dump out a mapping */ | |
297 | ||
298 | db_printf("Dump of mapping block: %08X\n", mp); /* Header */ | |
299 | db_printf(" next: %08X\n", mp->next); | |
300 | db_printf(" hashnext: %08X\n", mp->hashnext); | |
301 | db_printf(" PTEhash: %08X\n", mp->PTEhash); | |
302 | db_printf(" PTEent: %08X\n", mp->PTEent); | |
303 | db_printf(" physent: %08X\n", mp->physent); | |
304 | db_printf(" PTEv: %08X\n", mp->PTEv); | |
305 | db_printf(" PTEr: %08X\n", mp->PTEr); | |
306 | db_printf(" pmap: %08X\n", mp->pmap); | |
307 | ||
308 | if(mp->physent) { /* Print physent if it exists */ | |
309 | db_printf("Associated physical entry: %08X %08X\n", mp->physent->phys_link, mp->physent->pte1); | |
310 | } | |
311 | else { | |
312 | db_printf("Associated physical entry: none\n"); | |
313 | } | |
314 | ||
315 | db_dumppca(mp); /* Dump out the PCA information */ | |
316 | ||
317 | return; | |
318 | } | |
319 | ||
320 | /* | |
321 | * Prints out a PTEG control area | |
322 | * | |
323 | */ | |
324 | ||
325 | void db_dumppca(struct mapping *mp) { /* PCA */ | |
326 | ||
327 | PCA *pca; | |
328 | unsigned int *pteg, sdr; | |
329 | ||
330 | pca = (PCA *)((unsigned int)mp->PTEhash&-64); /* Back up to the start of the PCA */ | |
331 | __asm__ volatile("mfsdr1 %0" : "=r" (sdr)); | |
332 | db_printf(" SDR1: %08X\n", sdr); | |
333 | pteg=(unsigned int *)((unsigned int)pca-(((sdr&0x0000FFFF)+1)<<16)); | |
334 | db_printf(" Dump of PCA: %08X\n", pca); /* Header */ | |
335 | db_printf(" PCAlock: %08X\n", pca->PCAlock); | |
336 | db_printf(" PCAallo: %08X\n", pca->flgs.PCAallo); | |
337 | db_printf(" PCAhash: %08X %08X %08X %08X\n", pca->PCAhash[0], pca->PCAhash[1], pca->PCAhash[2], pca->PCAhash[3]); | |
338 | db_printf(" %08X %08X %08X %08X\n", pca->PCAhash[4], pca->PCAhash[5], pca->PCAhash[6], pca->PCAhash[7]); | |
339 | db_printf("Dump of PTEG: %08X\n", pteg); /* Header */ | |
340 | db_printf(" %08X %08X %08X %08X\n", pteg[0], pteg[1], pteg[2], pteg[3]); | |
341 | db_printf(" %08X %08X %08X %08X\n", pteg[4], pteg[5], pteg[6], pteg[7]); | |
342 | db_printf(" %08X %08X %08X %08X\n", pteg[8], pteg[9], pteg[10], pteg[11]); | |
343 | db_printf(" %08X %08X %08X %08X\n", pteg[12], pteg[13], pteg[14], pteg[15]); | |
344 | return; | |
345 | } | |
346 | ||
347 | /* | |
348 | * Dumps starting with a physical entry | |
349 | */ | |
350 | ||
351 | void db_dumpphys(struct phys_entry *pp) { /* Dump from physent */ | |
352 | ||
353 | mapping *mp; | |
354 | PCA *pca; | |
355 | unsigned int *pteg; | |
356 | ||
357 | db_printf("Dump from physical entry %08X: %08X %08X\n", pp, pp->phys_link, pp->pte1); | |
358 | mp = hw_cpv(pp->phys_link); | |
359 | while(mp) { | |
360 | db_dumpmapping(mp); | |
361 | db_dumppca(mp); | |
362 | mp = hw_cpv(mp->next); | |
363 | } | |
364 | ||
365 | return; | |
366 | } | |
367 | ||
368 | ||
369 | /* | |
370 | * Print out 256 bytes of virtual storage | |
371 | * | |
372 | * | |
373 | * dv [entaddr] [space] | |
374 | * address must be on 32-byte boundary. It will be rounded down if not | |
375 | */ | |
376 | void db_display_virtual(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
377 | ||
378 | int i, size, lines, rlines; | |
379 | unsigned int xbuf[8]; | |
380 | unsigned int xspace; | |
381 | ||
382 | mapping *mp, *mpv; | |
383 | vm_offset_t pa; | |
384 | ||
385 | if (db_expression(&xspace)) dvspace = xspace; /* Get the space or set default */ | |
386 | ||
387 | addr&=-32; | |
388 | ||
389 | size = 4096 - (addr & 0x00000FFF); /* Bytes left on page */ | |
390 | lines = size / 32; /* Number of lines in first or only part */ | |
391 | if(lines > 8) lines = 8; | |
392 | rlines = 8 - lines; | |
393 | if(rlines < 0) lines = 0; | |
394 | ||
395 | db_printf("Dumping %08X (space=%08X); ", addr, dvspace); | |
396 | mp = hw_lock_phys_vir(dvspace, addr); /* Lock the physical entry for this mapping */ | |
397 | if(!mp) { /* Did we find one? */ | |
398 | db_printf("Not mapped\n"); | |
399 | return; /* Didn't find any, return FALSE... */ | |
400 | } | |
401 | if((unsigned int)mp&1) { /* Did we timeout? */ | |
402 | db_printf("Timeout locking physical entry for virtual address (%08X)\n", addr); /* Yeah, scream about it! */ | |
403 | return; /* Bad hair day, return FALSE... */ | |
404 | } | |
405 | mpv = hw_cpv(mp); /* Get virtual address of mapping */ | |
406 | if(!mpv->physent) { /* Was there a physical entry? */ | |
407 | pa = (vm_offset_t)((mpv->PTEr & -PAGE_SIZE) | ((unsigned int)addr & (PAGE_SIZE-1))); /* Get physical address from physent */ | |
408 | } | |
409 | else { | |
410 | pa = (vm_offset_t)((mpv->physent->pte1 & -PAGE_SIZE) | ((unsigned int)addr & (PAGE_SIZE-1))); /* Get physical address from physent */ | |
411 | hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Unlock the physical entry */ | |
412 | } | |
413 | db_printf("phys=%08X\n", pa); | |
414 | for(i=0; i<lines; i++) { /* Print n bytes */ | |
415 | ReadReal((unsigned int)pa, &xbuf[0]); /* Get the real storage data */ | |
416 | db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */ | |
417 | xbuf[0], xbuf[1], xbuf[2], xbuf[3], | |
418 | xbuf[4], xbuf[5], xbuf[6], xbuf[7]); | |
419 | addr=(db_expr_t)((unsigned int)addr+0x00000020); /* Point to next address */ | |
420 | pa=(unsigned int)pa+0x00000020; /* Point to next address */ | |
421 | } | |
422 | db_next = addr; | |
423 | ||
424 | if(!rlines) return; | |
425 | ||
426 | db_printf("Dumping %08X (space=%08X); ", addr, dvspace); | |
427 | mp = hw_lock_phys_vir(dvspace, addr); /* Lock the physical entry for this mapping */ | |
428 | if(!mp) { /* Did we find one? */ | |
429 | db_printf("Not mapped\n"); | |
430 | return; /* Didn't find any, return FALSE... */ | |
431 | } | |
432 | if((unsigned int)mp&1) { /* Did we timeout? */ | |
433 | db_printf("Timeout locking physical entry for virtual address (%08X)\n", addr); /* Yeah, scream about it! */ | |
434 | return; /* Bad hair day, return FALSE... */ | |
435 | } | |
436 | mpv = hw_cpv(mp); /* Get virtual address of mapping */ | |
437 | if(!mpv->physent) { /* Was there a physical entry? */ | |
438 | pa = (vm_offset_t)((mpv->PTEr & -PAGE_SIZE) | ((unsigned int)addr & (PAGE_SIZE-1))); /* Get physical address from physent */ | |
439 | } | |
440 | else { | |
441 | pa = (vm_offset_t)((mpv->physent->pte1 & -PAGE_SIZE) | ((unsigned int)addr & (PAGE_SIZE-1))); /* Get physical address from physent */ | |
442 | hw_unlock_bit((unsigned int *)&mp->physent->phys_link, PHYS_LOCK); /* Unlock the physical entry */ | |
443 | } | |
444 | db_printf("phys=%08X\n", pa); | |
445 | for(i=0; i<rlines; i++) { /* Print n bytes */ | |
446 | ReadReal((unsigned int)pa, &xbuf[0]); /* Get the real storage data */ | |
447 | db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */ | |
448 | xbuf[0], xbuf[1], xbuf[2], xbuf[3], | |
449 | xbuf[4], xbuf[5], xbuf[6], xbuf[7]); | |
450 | addr=(db_expr_t)((unsigned int)addr+0x00000020); /* Point to next address */ | |
451 | pa=(unsigned int)pa+0x00000020; /* Point to next address */ | |
452 | } | |
453 | db_next = addr; | |
454 | ||
455 | ||
456 | } | |
457 | ||
458 | ||
459 | /* | |
460 | * Print out savearea stuff | |
461 | * | |
462 | * | |
463 | * ds | |
464 | */ | |
465 | ||
466 | #define chainmax 32 | |
467 | ||
468 | void db_display_save(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
469 | ||
470 | int i, j, totsaves, tottasks, taskact, chainsize; | |
471 | processor_set_t pset = &default_pset; | |
472 | task_t task; | |
473 | thread_act_t act; | |
474 | savearea *save; | |
475 | ||
476 | tottasks = 0; | |
477 | totsaves = 0; | |
478 | ||
479 | for(task = (task_t)pset->tasks.next; task != (task_t)&pset->tasks.next; task = (task_t)task->pset_tasks.next) { /* Go through the tasks */ | |
480 | taskact = 0; /* Reset activation count */ | |
481 | db_printf("\nTask %4d @%08X:\n", tottasks, task); /* Show where we're at */ | |
482 | for(act = (thread_act_t)task->thr_acts.next; act != (thread_act_t)&task->thr_acts; act = (thread_act_t)act->thr_acts.next) { /* Go through activations */ | |
483 | db_printf(" Act %4d @%08X - p: %08X fp: %08X fl: %08X fc: %d vp: %08X vl: %08X vp: %d\n", | |
484 | taskact, act, act->mact.pcb, act->mact.FPU_pcb, act->mact.FPU_lvl, act->mact.FPU_cpu, | |
485 | act->mact.VMX_pcb, act->mact.VMX_lvl, act->mact.VMX_cpu); | |
486 | ||
487 | ||
488 | save = (savearea *)act->mact.pcb; /* Set the start of the normal chain */ | |
489 | chainsize = 0; | |
490 | while(save) { /* Do them all */ | |
491 | totsaves++; /* Count savearea */ | |
492 | db_printf(" Norm %08X: %08X %08X - tot = %d\n", save, save->save_srr0, save->save_srr1, totsaves); | |
493 | save = save->save_prev; /* Next one */ | |
494 | if(chainsize++ > chainmax) { /* See if we might be in a loop */ | |
495 | db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save); | |
496 | break; | |
497 | } | |
498 | } | |
499 | ||
500 | save = (savearea *)act->mact.FPU_pcb; /* Set the start of the floating point chain */ | |
501 | chainsize = 0; | |
502 | while(save) { /* Do them all */ | |
503 | if(!(save->save_flags & SAVattach)) totsaves++; /* Count savearea only if not a normal one also */ | |
504 | db_printf(" FPU %08X: %08X - tot = %d\n", save, save->save_level_fp, totsaves); | |
505 | save = save->save_prev_float; /* Next one */ | |
506 | if(chainsize++ > chainmax) { /* See if we might be in a loop */ | |
507 | db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save); | |
508 | break; | |
509 | } | |
510 | } | |
511 | ||
512 | save = (savearea *)act->mact.VMX_pcb; /* Set the start of the floating point chain */ | |
513 | chainsize = 0; | |
514 | while(save) { /* Do them all */ | |
515 | if(!(save->save_flags & (SAVattach | SAVfpuvalid))) totsaves++; /* Count savearea only if not a normal one also */ | |
516 | db_printf(" Vec %08X: %08X - tot = %d\n", save, save->save_level_vec, totsaves); | |
517 | save = save->save_prev_vector; /* Next one */ | |
518 | if(chainsize++ > chainmax) { /* See if we might be in a loop */ | |
519 | db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save); | |
520 | break; | |
521 | } | |
522 | } | |
523 | taskact++; | |
524 | } | |
525 | tottasks++; | |
526 | } | |
527 | ||
528 | db_printf("Total saveareas accounted for: %d\n", totsaves); | |
529 | return; | |
530 | } | |
531 | ||
532 | /* | |
533 | * Print out extra registers | |
534 | * | |
535 | * | |
536 | * dx | |
537 | */ | |
538 | ||
539 | extern unsigned int dbfloats[33][2]; | |
540 | extern unsigned int dbvecs[33][4]; | |
541 | extern unsigned int dbspecrs[80]; | |
542 | ||
543 | void db_display_xregs(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
544 | ||
545 | int i, j, pents; | |
546 | ||
547 | stSpecrs(dbspecrs); /* Save special registers */ | |
548 | db_printf("PIR: %08X\n", dbspecrs[0]); | |
549 | db_printf("PVR: %08X\n", dbspecrs[1]); | |
550 | db_printf("SDR1: %08X\n", dbspecrs[22]); | |
551 | db_printf("HID0: %08X\n", dbspecrs[39]); | |
552 | db_printf("HID1: %08X\n", dbspecrs[40]); | |
553 | db_printf("L2CR: %08X\n", dbspecrs[41]); | |
554 | db_printf("MSSCR0: %08X\n", dbspecrs[42]); | |
555 | db_printf("MSSCR1: %08X\n", dbspecrs[43]); | |
556 | db_printf("THRM1: %08X\n", dbspecrs[44]); | |
557 | db_printf("THRM2: %08X\n", dbspecrs[45]); | |
558 | db_printf("THRM3: %08X\n", dbspecrs[46]); | |
559 | db_printf("ICTC: %08X\n", dbspecrs[47]); | |
560 | db_printf("\n"); | |
561 | ||
562 | db_printf("DBAT: %08X %08X %08X %08X\n", dbspecrs[2], dbspecrs[3], dbspecrs[4], dbspecrs[5]); | |
563 | db_printf(" %08X %08X %08X %08X\n", dbspecrs[6], dbspecrs[7], dbspecrs[8], dbspecrs[9]); | |
564 | db_printf("IBAT: %08X %08X %08X %08X\n", dbspecrs[10], dbspecrs[11], dbspecrs[12], dbspecrs[13]); | |
565 | db_printf(" %08X %08X %08X %08X\n", dbspecrs[14], dbspecrs[15], dbspecrs[16], dbspecrs[17]); | |
566 | db_printf("SPRG: %08X %08X %08X %08X\n", dbspecrs[18], dbspecrs[19], dbspecrs[20], dbspecrs[21]); | |
567 | db_printf("\n"); | |
568 | for(i = 0; i < 16; i += 8) { /* Print 8 at a time */ | |
569 | db_printf("SR%02d: %08X %08X %08X %08X %08X %08X %08X %08X\n", i, | |
570 | dbspecrs[23+i], dbspecrs[24+i], dbspecrs[25+i], dbspecrs[26+i], | |
571 | dbspecrs[27+i], dbspecrs[28+i], dbspecrs[29+i], dbspecrs[30+i]); | |
572 | } | |
573 | ||
574 | db_printf("\n"); | |
575 | ||
576 | stFloat(dbfloats); /* Save floating point registers */ | |
577 | for(i = 0; i < 32; i += 4) { /* Print 4 at a time */ | |
578 | db_printf("F%02d: %08X %08X %08X %08X %08X %08X %08X %08X\n", i, | |
579 | dbfloats[i][0], dbfloats[i][1], dbfloats[i+1][0], dbfloats[i+1][1], | |
580 | dbfloats[i+2][0], dbfloats[i+2][1], dbfloats[i+3][0], dbfloats[i+3][1]); | |
581 | } | |
582 | db_printf("FCR: %08X %08X\n", dbfloats[32][0], dbfloats[32][1]); /* Print FSCR */ | |
583 | ||
584 | if(!stVectors(dbvecs)) return; /* Return if not Altivec capable */ | |
585 | ||
586 | db_printf("\n"); | |
587 | ||
588 | for(i = 0; i < 32; i += 2) { /* Print 2 at a time */ | |
589 | db_printf("V%02d: %08X %08X %08X %08X %08X %08X %08X %08X\n", i, | |
590 | dbvecs[i][0], dbvecs[i][1], dbvecs[i][2], dbvecs[i][3], | |
591 | dbvecs[i+1][0], dbvecs[i+1][1], dbvecs[i+1][2], dbvecs[i+1][3]); | |
592 | } | |
593 | db_printf("VCR: %08X %08X %08X %08X\n", dbvecs[32][0], dbvecs[32][1], dbvecs[32][2], dbvecs[32][3]); /* Print VSCR */ | |
594 | ||
595 | return; /* Tell them we did it */ | |
596 | ||
597 | ||
598 | } | |
599 | ||
600 | /* | |
601 | * Displays all of the kmods in the system. | |
602 | * | |
603 | * dp | |
604 | */ | |
605 | void db_display_kmod(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
606 | ||
607 | kmod_info_t *kmd; | |
608 | unsigned int strt, end; | |
609 | ||
610 | kmd = kmod; /* Start at the start */ | |
611 | ||
612 | db_printf("info addr start - end name ver\n"); | |
613 | ||
614 | while(kmd) { /* Dump 'em all */ | |
615 | strt = (unsigned int)kmd->address + kmd->hdr_size; /* Get start of kmod text */ | |
616 | end = (unsigned int)kmd->address + kmd->size; /* Get end of kmod */ | |
617 | db_printf("%08X %08X %08X - %08X: %s, %s\n", kmd, kmd->address, strt, end, | |
618 | kmd->name, kmd->version); | |
619 | kmd = kmd->next; /* Step to it */ | |
620 | } | |
621 | ||
622 | return; | |
623 | } | |
624 | ||
625 | /* | |
626 | * Displays stuff | |
627 | * | |
628 | * gs | |
629 | */ | |
630 | 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}; | |
631 | ||
632 | void db_gsnoop(db_expr_t addr, int have_addr, db_expr_t count, char * modif) { | |
633 | ||
634 | int i, j; | |
635 | unsigned char *gp, gpn[36]; | |
636 | #define ngpr 34 | |
637 | ||
638 | gp = (unsigned char *)0x8000005C; | |
639 | ||
640 | for(i = 0; i < ngpr; i++) gpn[i] = gp[i]; /* Copy 'em */ | |
641 | ||
642 | for(i = 0; i < ngpr; i++) { | |
643 | db_printf("%02X ", gpn[i]); | |
644 | } | |
645 | db_printf("\n"); | |
646 | ||
647 | for(i = 0; i < ngpr; i++) { | |
648 | if(gpn[i] != xxgpo[i]) db_printf("^^ "); | |
649 | else db_printf(" "); | |
650 | } | |
651 | db_printf("\n"); | |
652 | ||
653 | for(i = 0; i < ngpr; i++) xxgpo[i] = gpn[i]; /* Save 'em */ | |
654 | ||
655 | return; | |
656 | } | |
657 | ||
658 | ||
659 | void Dumbo(void); | |
660 | void Dumbo(void){ | |
661 | } |