VirtualBox

source: vbox/trunk/src/VBox/VMM/PGMMap.cpp@ 28

Last change on this file since 28 was 23, checked in by vboxsync, 18 years ago

string.h & stdio.h + header cleanups.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 39.1 KB
Line 
1/* $Id: PGMMap.cpp 23 2007-01-15 14:08:28Z vboxsync $ */
2/** @file
3 * PGM - Page Manager, Guest Context Mappings.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_PGM
27#include <VBox/dbgf.h>
28#include <VBox/pgm.h>
29#include "PGMInternal.h"
30#include <VBox/vm.h>
31
32#include <VBox/log.h>
33#include <VBox/err.h>
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/string.h>
37
38
39/*******************************************************************************
40* Internal Functions *
41*******************************************************************************/
42static void pgmR3MapClearPDEs(PPGM pPGM, PPGMMAPPING pMap, int iOldPDE);
43static void pgmR3MapSetPDEs(PVM pVM, PPGMMAPPING pMap, int iNewPDE);
44static DECLCALLBACK(int) pgmR3DumpMappingsPhysicalCB(PAVLROGCPHYSNODECORE pNode, void *pvUser);
45static int pgmR3MapIntermediateCheckOne(PVM pVM, uintptr_t uAddress, unsigned cPages, PX86PT pPTDefault, PX86PTPAE pPTPaeDefault);
46static void pgmR3MapIntermediateDoOne(PVM pVM, uintptr_t uAddress, RTHCPHYS HCPhys, unsigned cPages, PX86PT pPTDefault, PX86PTPAE pPTPaeDefault);
47
48
49
50/**
51 * Creates a page table based mapping in GC.
52 *
53 * @returns VBox status code.
54 * @param pVM VM Handle.
55 * @param GCPtr Virtual Address. (Page table aligned!)
56 * @param cb Size of the range. Must be a 4MB aligned!
57 * @param pfnRelocate Relocation callback function.
58 * @param pvUser User argument to the callback.
59 * @param pszDesc Pointer to description string. This must not be freed.
60 */
61PGMR3DECL(int) PGMR3MapPT(PVM pVM, RTGCPTR GCPtr, size_t cb, PFNPGMRELOCATE pfnRelocate, void *pvUser, const char *pszDesc)
62{
63 LogFlow(("PGMR3MapPT: GCPtr=%#x cb=%d pfnRelocate=%p pvUser=%p pszDesc=%s\n", GCPtr, cb, pfnRelocate, pvUser, pszDesc));
64 AssertMsg(pVM->pgm.s.pInterPD && pVM->pgm.s.pHC32BitPD, ("Paging isn't initialized, init order problems!\n"));
65
66 /*
67 * Validate input.
68 */
69 if (cb < _2M || cb > 64 * _1M)
70 {
71 AssertMsgFailed(("Serious? cb=%d\n", cb));
72 return VERR_INVALID_PARAMETER;
73 }
74 cb = RT_ALIGN_Z(cb, _4M);
75 RTGCPTR GCPtrLast = GCPtr + cb - 1;
76 if (GCPtrLast < GCPtr)
77 {
78 AssertMsgFailed(("Range wraps! GCPtr=%x GCPtrLast=%x\n", GCPtr, GCPtrLast));
79 return VERR_INVALID_PARAMETER;
80 }
81 if (pVM->pgm.s.fMappingsFixed)
82 {
83 AssertMsgFailed(("Mappings are fixed! It's not possible to add new mappings at this time!\n"));
84 return VERR_PGM_MAPPINGS_FIXED;
85 }
86 if (!pfnRelocate)
87 {
88 AssertMsgFailed(("Callback is required\n"));
89 return VERR_INVALID_PARAMETER;
90 }
91
92 /*
93 * Find list location.
94 */
95 PPGMMAPPING pPrev = NULL;
96 PPGMMAPPING pCur = pVM->pgm.s.pMappingsHC;
97 while (pCur)
98 {
99 if (pCur->GCPtrLast >= GCPtr && pCur->GCPtr <= GCPtrLast)
100 {
101 AssertMsgFailed(("Address is already in use by %s. req %#x-%#x take %#x-%#x\n",
102 pCur->pszDesc, GCPtr, GCPtrLast, pCur->GCPtr, pCur->GCPtrLast));
103 return VERR_PGM_MAPPING_CONFLICT;
104 }
105 if (pCur->GCPtr > GCPtr)
106 break;
107 pPrev = pCur;
108 pCur = pCur->pNextHC;
109 }
110/** @todo this needs fixing, the function must relocate on conflict, not fail! */
111
112 /*
113 * Check for conflicts with intermediate mappings.
114 */
115 const unsigned iPageDir = GCPtr >> PGDIR_SHIFT;
116 const unsigned cPTs = cb >> PGDIR_SHIFT;
117 unsigned i;
118 for (i = 0; i < cPTs; i++)
119 {
120 if (pVM->pgm.s.pInterPD->a[iPageDir + i].n.u1Present)
121 {
122 AssertMsgFailed(("Address %#x is already in use by an intermediate mapping.\n", GCPtr + (i << PAGE_SHIFT)));
123 return VERR_PGM_MAPPING_CONFLICT;
124 }
125 }
126 /** @todo AMD64: add check in PAE structures too, so we can remove all the 32-Bit paging stuff there. */
127
128 /*
129 * Allocate and initialize the new list node.
130 */
131 PPGMMAPPING pNew;
132 int rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMMAPPING, aPTs[cPTs]), 0, MM_TAG_PGM, (void **)&pNew);
133 if (VBOX_FAILURE(rc))
134 return rc;
135 pNew->GCPtr = GCPtr;
136 pNew->GCPtrLast = GCPtrLast;
137 pNew->cb = cb;
138 pNew->pszDesc = pszDesc;
139 pNew->pfnRelocate = pfnRelocate;
140 pNew->pvUser = pvUser;
141 pNew->cPTs = cPTs;
142
143 /*
144 * Allocate page tables and insert them into the page directories.
145 * (One 32-bit PT and two PAE PTs.)
146 */
147 uint8_t *pbPTs;
148 rc = MMHyperAlloc(pVM, PAGE_SIZE * 3 * cPTs, PAGE_SIZE, MM_TAG_PGM, (void **)&pbPTs);
149 if (VBOX_FAILURE(rc))
150 {
151 MMHyperFree(pVM, pNew);
152 return VERR_NO_MEMORY;
153 }
154
155 /*
156 * Init the page tables and insert them into the page directories.
157 */
158 Log4(("PGMR3MapPT: GCPtr=%VGv cPTs=%u pbPTs=%p\n", GCPtr, cPTs, pbPTs));
159 for (i = 0; i < cPTs; i++)
160 {
161 /*
162 * 32-bit.
163 */
164 pNew->aPTs[i].pPTHC = (PVBOXPT)pbPTs;
165 pNew->aPTs[i].pPTGC = MMHyperHC2GC(pVM, pNew->aPTs[i].pPTHC);
166 pNew->aPTs[i].HCPhysPT = MMR3HyperHCVirt2HCPhys(pVM, pNew->aPTs[i].pPTHC);
167 pbPTs += PAGE_SIZE;
168 Log4(("PGMR3MapPT: i=%d: pPTHC=%p pPTGC=%p HCPhysPT=%RHp\n",
169 i, pNew->aPTs[i].pPTHC, pNew->aPTs[i].pPTGC, pNew->aPTs[i].HCPhysPT));
170
171 /*
172 * PAE.
173 */
174 pNew->aPTs[i].HCPhysPaePT0 = MMR3HyperHCVirt2HCPhys(pVM, pbPTs);
175 pNew->aPTs[i].HCPhysPaePT1 = MMR3HyperHCVirt2HCPhys(pVM, pbPTs + PAGE_SIZE);
176 pNew->aPTs[i].paPaePTsHC = (PX86PTPAE)pbPTs;
177 pNew->aPTs[i].paPaePTsGC = MMHyperHC2GC(pVM, pbPTs);
178 pbPTs += PAGE_SIZE * 2;
179 Log4(("PGMR3MapPT: i=%d: paPaePTsHC=%p paPaePTsGC=%p HCPhysPaePT0=%RHp HCPhysPaePT1=%RHp\n",
180 i, pNew->aPTs[i].paPaePTsHC, pNew->aPTs[i].paPaePTsGC, pNew->aPTs[i].HCPhysPaePT0, pNew->aPTs[i].HCPhysPaePT1));
181 }
182 pgmR3MapSetPDEs(pVM, pNew, iPageDir);
183
184 /*
185 * Insert the new mapping.
186 */
187 pNew->pNextHC = pCur;
188 pNew->pNextGC = pCur ? MMHyperHC2GC(pVM, pCur) : 0;
189 if (pPrev)
190 {
191 pPrev->pNextHC = pNew;
192 pPrev->pNextGC = MMHyperHC2GC(pVM, pNew);
193 }
194 else
195 {
196 pVM->pgm.s.pMappingsHC = pNew;
197 pVM->pgm.s.pMappingsGC = MMHyperHC2GC(pVM, pNew);
198 }
199
200 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
201 return VINF_SUCCESS;
202}
203
204
205/**
206 * Removes a page table based mapping.
207 *
208 * @returns VBox status code.
209 * @param pVM VM Handle.
210 * @param GCPtr Virtual Address. (Page table aligned!)
211 */
212PGMR3DECL(int) PGMR3UnmapPT(PVM pVM, RTGCPTR GCPtr)
213{
214 LogFlow(("PGMR3UnmapPT: GCPtr=%#x\n", GCPtr));
215
216 /*
217 * Find it.
218 */
219 PPGMMAPPING pPrev = NULL;
220 PPGMMAPPING pCur = pVM->pgm.s.pMappingsHC;
221 while (pCur)
222 {
223 if (pCur->GCPtr == GCPtr)
224 {
225 /*
226 * Unlink it.
227 */
228 if (pPrev)
229 {
230 pPrev->pNextHC = pCur->pNextHC;
231 pPrev->pNextGC = pCur->pNextGC;
232 }
233 else
234 {
235 pVM->pgm.s.pMappingsHC = pCur->pNextHC;
236 pVM->pgm.s.pMappingsGC = pCur->pNextGC;
237 }
238
239 /*
240 * Free the page table memory, clear page directory entries
241 * and free the page tables and node memory.
242 */
243 MMHyperFree(pVM, pCur->aPTs[0].pPTHC);
244 pgmR3MapClearPDEs(&pVM->pgm.s, pCur, pCur->GCPtr >> PGDIR_SHIFT);
245 MMHyperFree(pVM, pCur);
246
247 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
248 return VINF_SUCCESS;
249 }
250
251 /* done? */
252 if (pCur->GCPtr > GCPtr)
253 break;
254
255 /* next */
256 pPrev = pCur;
257 pCur = pCur->pNextHC;
258 }
259
260 AssertMsgFailed(("No mapping for %#x found!\n", GCPtr));
261 return VERR_INVALID_PARAMETER;
262}
263
264
265/**
266 * Gets the size of the current guest mappings if they were to be
267 * put next to oneanother.
268 *
269 * @returns VBox status code.
270 * @param pVM The VM.
271 * @param pcb Where to store the size.
272 */
273PGMR3DECL(int) PGMR3MappingsSize(PVM pVM, size_t *pcb)
274{
275 size_t cb = 0;
276 for (PPGMMAPPING pCur = pVM->pgm.s.pMappingsHC; pCur; pCur = pCur->pNextHC)
277 cb += pCur->cb;
278
279 *pcb = cb;
280 Log(("PGMR3MappingsSize: return %d (%#x) bytes\n", cb, cb));
281 return VINF_SUCCESS;
282}
283
284
285/**
286 * Fixes the guest context mappings in a range reserved from the Guest OS.
287 *
288 * @returns VBox status code.
289 * @param pVM The VM.
290 * @param GCPtrBase The address of the reserved range of guest memory.
291 * @param cb The size of the range starting at GCPtrBase.
292 */
293PGMR3DECL(int) PGMR3MappingsFix(PVM pVM, RTGCPTR GCPtrBase, size_t cb)
294{
295 Log(("PGMR3MappingsFix: GCPtrBase=%#x cb=%#x\n", GCPtrBase, cb));
296
297 /*
298 * This is all or nothing at all. So, a tiny bit of paranoia first.
299 */
300 if (GCPtrBase & PAGE_OFFSET_MASK_BIG)
301 {
302 AssertMsgFailed(("GCPtrBase (%#x) has to be aligned on a 4MB address!\n", GCPtrBase));
303 return VERR_INVALID_PARAMETER;
304 }
305 if (!cb || (cb & PAGE_OFFSET_MASK_BIG))
306 {
307 AssertMsgFailed(("cb (%#x) is 0 or not aligned on a 4MB address!\n", cb));
308 return VERR_INVALID_PARAMETER;
309 }
310
311 /*
312 * Before we do anything we'll do a forced PD sync to try make sure any
313 * pending relocations because of these mappings have been resolved.
314 */
315 PGMSyncCR3(pVM, CPUMGetGuestCR0(pVM), CPUMGetGuestCR3(pVM), CPUMGetGuestCR4(pVM), true);
316
317 /*
318 * Check that it's not conflicting with a core code mapping in the intermediate page table.
319 */
320 unsigned iPDNew = GCPtrBase >> PGDIR_SHIFT;
321 unsigned i = cb >> PGDIR_SHIFT;
322 while (i-- > 0)
323 {
324 if (pVM->pgm.s.pInterPD->a[iPDNew + i].n.u1Present)
325 {
326 /* Check that it's not one or our mappings. */
327 PPGMMAPPING pCur = pVM->pgm.s.pMappingsHC;
328 while (pCur)
329 {
330 if (iPDNew + i - (pCur->GCPtr >> PGDIR_SHIFT) < (pCur->cb >> PGDIR_SHIFT))
331 break;
332 pCur = pCur->pNextHC;
333 }
334 if (!pCur)
335 {
336 LogRel(("PGMR3MappingsFix: Conflicts with intermediate PDE %#x (GCPtrBase=%VGv cb=%#zx). The guest should retry.\n",
337 iPDNew + i, GCPtrBase, cb));
338 return VERR_PGM_MAPPINGS_FIX_CONFLICT;
339 }
340 }
341 }
342
343 /*
344 * Loop the mappings and check that they all agree on their new locations.
345 */
346 RTGCPTR GCPtrCur = GCPtrBase;
347 PPGMMAPPING pCur = pVM->pgm.s.pMappingsHC;
348 while (pCur)
349 {
350 if (!pCur->pfnRelocate(pVM, pCur->GCPtr, GCPtrCur, PGMRELOCATECALL_SUGGEST, pCur->pvUser))
351 {
352 AssertMsgFailed(("The suggested fixed address %#x was rejected by '%s'!\n", GCPtrCur, pCur->pszDesc));
353 return VERR_PGM_MAPPINGS_FIX_REJECTED;
354 }
355 /* next */
356 GCPtrCur += pCur->cb;
357 pCur = pCur->pNextHC;
358 }
359 if (GCPtrCur > GCPtrBase + cb)
360 {
361 AssertMsgFailed(("cb (%#x) is less than the required range %#x!\n", cb, GCPtrCur - GCPtrBase));
362 return VERR_PGM_MAPPINGS_FIX_TOO_SMALL;
363 }
364
365 /*
366 * Loop the table assigning the mappings to the passed in memory
367 * and call their relocator callback.
368 */
369 GCPtrCur = GCPtrBase;
370 pCur = pVM->pgm.s.pMappingsHC;
371 while (pCur)
372 {
373 unsigned iPDOld = pCur->GCPtr >> PGDIR_SHIFT;
374 iPDNew = GCPtrCur >> PGDIR_SHIFT;
375
376 /*
377 * Relocate the page table(s).
378 */
379 pgmR3MapClearPDEs(&pVM->pgm.s, pCur, iPDOld);
380 pgmR3MapSetPDEs(pVM, pCur, iPDNew);
381
382 /*
383 * Update the entry.
384 */
385 pCur->GCPtr = GCPtrCur;
386 pCur->GCPtrLast = GCPtrCur + pCur->cb - 1;
387
388 /*
389 * Callback to execute the relocation.
390 */
391 pCur->pfnRelocate(pVM, iPDOld << PGDIR_SHIFT, iPDNew << PGDIR_SHIFT, PGMRELOCATECALL_RELOCATE, pCur->pvUser);
392
393 /*
394 * Advance.
395 */
396 GCPtrCur += pCur->cb;
397 pCur = pCur->pNextHC;
398 }
399
400 /*
401 * Turn off CR3 updating monitoring.
402 */
403 int rc2 = PGM_GST_PFN(UnmonitorCR3, pVM)(pVM);
404 AssertRC(rc2);
405
406 /*
407 * Mark the mappings as fixed and return.
408 */
409 pVM->pgm.s.fMappingsFixed = true;
410 pVM->pgm.s.GCPtrMappingFixed = GCPtrBase;
411 pVM->pgm.s.cbMappingFixed = cb;
412 pVM->pgm.s.fSyncFlags &= ~PGM_SYNC_MONITOR_CR3;
413 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
414 return VINF_SUCCESS;
415}
416
417
418/**
419 * Unfixes the mappings.
420 * After calling this function mapping conflict detection will be enabled.
421 *
422 * @returns VBox status code.
423 * @param pVM The VM.
424 */
425PGMR3DECL(int) PGMR3MappingsUnfix(PVM pVM)
426{
427 Log(("PGMR3MappingsUnfix: fMappingsFixed=%d\n", pVM->pgm.s.fMappingsFixed));
428 pVM->pgm.s.fMappingsFixed = false;
429 pVM->pgm.s.GCPtrMappingFixed = 0;
430 pVM->pgm.s.cbMappingFixed = 0;
431 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
432
433 /*
434 * Re-enable the CR3 monitoring.
435 *
436 * Paranoia: We flush the page pool before doing that because Windows
437 * is using the CR3 page both as a PD and a PT, e.g. the pool may
438 * be monitoring it.
439 */
440#ifdef PGMPOOL_WITH_MONITORING
441 pgmPoolFlushAll(pVM);
442#endif
443 int rc = PGM_GST_PFN(MonitorCR3, pVM)(pVM, pVM->pgm.s.GCPhysCR3);
444 AssertRC(rc);
445
446 return VINF_SUCCESS;
447}
448
449
450/**
451 * Map pages into the intermediate context (switcher code).
452 * These pages are mapped at both the give virtual address and at
453 * the physical address (for identity mapping).
454 *
455 * @returns VBox status code.
456 * @param pVM The virtual machine.
457 * @param pvAddr Intermediate context address of the mapping. This must be entriely below 4GB!
458 * @param HCPhys Start of the range of physical pages. This must be entriely below 4GB!
459 * @param cbPages Number of bytes to map.
460 *
461 * @remark This API shall not be used to anything but mapping the switcher code.
462 * @todo pvAddr must be a RTUINTPTR!
463 */
464PGMR3DECL(int) PGMR3MapIntermediate(PVM pVM, void *pvAddr, RTHCPHYS HCPhys, unsigned cbPages)
465{
466 LogFlow(("PGMR3MapIntermediate: pvAddr=%p HCPhys=%VHp cbPages=%#x\n", pvAddr, HCPhys, cbPages));
467
468 /*
469 * Adjust input.
470 */
471 cbPages += (uint32_t)HCPhys & PAGE_OFFSET_MASK;
472 cbPages = RT_ALIGN(cbPages, PAGE_SIZE);
473 HCPhys &= X86_PTE_PAE_PG_MASK;
474 pvAddr = (void *)((RTUINTPTR)pvAddr & PAGE_BASE_MASK);
475 /* We only care about the first 4GB, because on AMD64 we'll be repeating them all over the address space. */
476 uint32_t uAddress = (uint32_t)(uintptr_t)pvAddr;
477
478 /*
479 * Assert input and state.
480 */
481 AssertMsg(pVM->pgm.s.offVM, ("Bad init order\n"));
482 AssertMsg(pVM->pgm.s.pInterPD, ("Bad init order, paging.\n"));
483 AssertMsg(cbPages <= (512 << PAGE_SHIFT), ("The mapping is too big %d bytes\n", cbPages));
484 AssertMsg(HCPhys < _4G && HCPhys + cbPages < _4G, ("pvAddr=%p HCPhys=%VHp cbPages=%d\n", pvAddr, HCPhys, cbPages));
485
486 /*
487 * Check for internal conflicts between the virtual address and the physical address.
488 */
489 if ( uAddress != HCPhys
490 && ( uAddress < HCPhys
491 ? HCPhys - uAddress < cbPages
492 : uAddress - HCPhys < cbPages
493 )
494 )
495 {
496 AssertMsgFailed(("pvAddr=%p HCPhys=%VHp cbPages=%d\n", pvAddr, HCPhys, cbPages));
497 LogRel(("pvAddr=%p HCPhys=%VHp cbPages=%d\n", pvAddr, HCPhys, cbPages));
498 return VERR_PGM_MAPPINGS_FIX_CONFLICT; /** @todo new error code */
499 }
500
501 const unsigned cPages = cbPages >> PAGE_SHIFT;
502 int rc = pgmR3MapIntermediateCheckOne(pVM, uAddress, cPages, pVM->pgm.s.apInterPTs[0], pVM->pgm.s.apInterPaePTs[0]);
503 if (VBOX_FAILURE(rc))
504 return rc;
505 rc = pgmR3MapIntermediateCheckOne(pVM, (uintptr_t)HCPhys, cPages, pVM->pgm.s.apInterPTs[1], pVM->pgm.s.apInterPaePTs[1]);
506 if (VBOX_FAILURE(rc))
507 return rc;
508
509 /*
510 * Everythings fine, do the mapping.
511 */
512 pgmR3MapIntermediateDoOne(pVM, uAddress, HCPhys, cPages, pVM->pgm.s.apInterPTs[0], pVM->pgm.s.apInterPaePTs[0]);
513 pgmR3MapIntermediateDoOne(pVM, (uintptr_t)HCPhys, HCPhys, cPages, pVM->pgm.s.apInterPTs[1], pVM->pgm.s.apInterPaePTs[1]);
514
515 return VINF_SUCCESS;
516}
517
518
519/**
520 * Validates that there are no conflicts for this mapping into the intermediate context.
521 *
522 * @returns VBox status code.
523 * @param pVM VM handle.
524 * @param uAddress Address of the mapping.
525 * @param cPages Number of pages.
526 * @param pPTDefault Pointer to the default page table for this mapping.
527 * @param pPTPaeDefault Pointer to the default page table for this mapping.
528 */
529static int pgmR3MapIntermediateCheckOne(PVM pVM, uintptr_t uAddress, unsigned cPages, PX86PT pPTDefault, PX86PTPAE pPTPaeDefault)
530{
531 AssertMsg((uAddress >> X86_PD_SHIFT) + cPages <= 1024, ("64-bit fixme\n"));
532
533 /*
534 * Check that the ranges are available.
535 * (This codes doesn't have to be fast.)
536 */
537 while (cPages > 0)
538 {
539 /*
540 * 32-Bit.
541 */
542 unsigned iPDE = (uAddress >> X86_PD_SHIFT) & X86_PD_MASK;
543 unsigned iPTE = (uAddress >> X86_PT_SHIFT) & X86_PT_MASK;
544 PX86PT pPT = pPTDefault;
545 if (pVM->pgm.s.pInterPD->a[iPDE].u)
546 {
547 RTHCPHYS HCPhysPT = pVM->pgm.s.pInterPD->a[iPDE].u & X86_PDE_PG_MASK;
548 if (HCPhysPT == MMPage2Phys(pVM, pVM->pgm.s.apInterPTs[0]))
549 pPT = pVM->pgm.s.apInterPTs[0];
550 else if (HCPhysPT == MMPage2Phys(pVM, pVM->pgm.s.apInterPTs[1]))
551 pPT = pVM->pgm.s.apInterPTs[1];
552 else
553 {
554 /** @todo this must be handled with a relocation of the conflicting mapping!
555 * Which of course cannot be done because we're in the middle of the initialization. bad design! */
556 AssertMsgFailed(("Conflict between core code and PGMR3Mapping(). uAddress=%VHv\n", uAddress));
557 LogRel(("Conflict between core code and PGMR3Mapping(). uAddress=%VHv\n", uAddress));
558 return VERR_PGM_MAPPINGS_FIX_CONFLICT; /** @todo error codes! */
559 }
560 }
561 if (pPT->a[iPTE].u)
562 {
563 AssertMsgFailed(("Conflict iPTE=%#x iPDE=%#x uAddress=%VHv pPT->a[iPTE].u=%RX32\n", iPTE, iPDE, uAddress, pPT->a[iPTE].u));
564 LogRel(("Conflict iPTE=%#x iPDE=%#x uAddress=%VHv pPT->a[iPTE].u=%RX32\n",
565 iPTE, iPDE, uAddress, pPT->a[iPTE].u));
566 return VERR_PGM_MAPPINGS_FIX_CONFLICT; /** @todo error codes! */
567 }
568
569 /*
570 * PAE.
571 */
572 const unsigned iPDPE= (uAddress >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK;
573 iPDE = (uAddress >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
574 iPTE = (uAddress >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK;
575 Assert(iPDPE < 4);
576 Assert(pVM->pgm.s.apInterPaePDs[iPDPE]);
577 PX86PTPAE pPTPae = pPTPaeDefault;
578 if (pVM->pgm.s.apInterPaePDs[iPDPE]->a[iPDE].u)
579 {
580 RTHCPHYS HCPhysPT = pVM->pgm.s.apInterPaePDs[iPDPE]->a[iPDE].u & X86_PDE_PAE_PG_MASK;
581 if (HCPhysPT == MMPage2Phys(pVM, pVM->pgm.s.apInterPaePTs[0]))
582 pPTPae = pVM->pgm.s.apInterPaePTs[0];
583 else if (HCPhysPT == MMPage2Phys(pVM, pVM->pgm.s.apInterPaePTs[0]))
584 pPTPae = pVM->pgm.s.apInterPaePTs[1];
585 else
586 {
587 /** @todo this must be handled with a relocation of the conflicting mapping!
588 * Which of course cannot be done because we're in the middle of the initialization. bad design! */
589 AssertMsgFailed(("Conflict between core code and PGMR3Mapping(). uAddress=%VHv\n", uAddress));
590 LogRel(("Conflict between core code and PGMR3Mapping(). uAddress=%VHv\n", uAddress));
591 return VERR_PGM_MAPPINGS_FIX_CONFLICT; /** @todo error codes! */
592 }
593 }
594 if (pPTPae->a[iPTE].u)
595 {
596 AssertMsgFailed(("Conflict iPTE=%#x iPDE=%#x uAddress=%VHv pPTPae->a[iPTE].u=%#RX64\n", iPTE, iPDE, uAddress, pPTPae->a[iPTE].u));
597 LogRel(("Conflict iPTE=%#x iPDE=%#x uAddress=%VHv pPTPae->a[iPTE].u=%#RX64\n",
598 iPTE, iPDE, uAddress, pPTPae->a[iPTE].u));
599 return VERR_PGM_MAPPINGS_FIX_CONFLICT; /** @todo error codes! */
600 }
601
602 /* next */
603 uAddress += PAGE_SIZE;
604 cPages--;
605 }
606
607 return VINF_SUCCESS;
608}
609
610
611
612/**
613 * Sets up the intermediate page tables for a verified mapping.
614 *
615 * @param pVM VM handle.
616 * @param uAddress Address of the mapping.
617 * @param HCPhys The physical address of the page range.
618 * @param cPages Number of pages.
619 * @param pPTDefault Pointer to the default page table for this mapping.
620 * @param pPTPaeDefault Pointer to the default page table for this mapping.
621 */
622static void pgmR3MapIntermediateDoOne(PVM pVM, uintptr_t uAddress, RTHCPHYS HCPhys, unsigned cPages, PX86PT pPTDefault, PX86PTPAE pPTPaeDefault)
623{
624 while (cPages > 0)
625 {
626 /*
627 * 32-Bit.
628 */
629 unsigned iPDE = (uAddress >> X86_PD_SHIFT) & X86_PD_MASK;
630 unsigned iPTE = (uAddress >> X86_PT_SHIFT) & X86_PT_MASK;
631 PX86PT pPT;
632 if (pVM->pgm.s.pInterPD->a[iPDE].u)
633 pPT = (PX86PT)MMPagePhys2Page(pVM, pVM->pgm.s.pInterPD->a[iPDE].u & X86_PDE_PG_MASK);
634 else
635 {
636 pVM->pgm.s.pInterPD->a[iPDE].u = X86_PDE_P | X86_PDE_A | X86_PDE_RW
637 | (uint32_t)MMPage2Phys(pVM, pPTDefault);
638 pPT = pPTDefault;
639 }
640 pPT->a[iPTE].u = X86_PTE_P | X86_PTE_RW | X86_PTE_A | X86_PTE_D | (uint32_t)HCPhys;
641
642 /*
643 * PAE
644 */
645 const unsigned iPDPE= (uAddress >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK;
646 iPDE = (uAddress >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
647 iPTE = (uAddress >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK;
648 Assert(iPDPE < 4);
649 Assert(pVM->pgm.s.apInterPaePDs[iPDPE]);
650 PX86PTPAE pPTPae;
651 if (pVM->pgm.s.apInterPaePDs[iPDPE]->a[iPDE].u)
652 pPTPae = (PX86PTPAE)MMPagePhys2Page(pVM, pVM->pgm.s.apInterPaePDs[iPDPE]->a[iPDE].u & X86_PDE_PAE_PG_MASK);
653 else
654 {
655 pPTPae = pPTPaeDefault;
656 pVM->pgm.s.apInterPaePDs[iPDPE]->a[iPDE].u = X86_PDE_P | X86_PDE_A | X86_PDE_RW
657 | MMPage2Phys(pVM, pPTPaeDefault);
658 }
659 pPTPae->a[iPTE].u = X86_PTE_P | X86_PTE_RW | X86_PTE_A | X86_PTE_D | HCPhys;
660
661 /* next */
662 cPages--;
663 HCPhys += PAGE_SIZE;
664 uAddress += PAGE_SIZE;
665 }
666}
667
668
669/**
670 * Clears all PDEs involved with the mapping.
671 *
672 * @param pPGM Pointer to the PGM instance data.
673 * @param pMap Pointer to the mapping in question.
674 * @param iOldPDE The index of the 32-bit PDE corresponding to the base of the mapping.
675 */
676static void pgmR3MapClearPDEs(PPGM pPGM, PPGMMAPPING pMap, int iOldPDE)
677{
678 unsigned i = pMap->cPTs;
679 iOldPDE += i;
680 while (i-- > 0)
681 {
682 iOldPDE--;
683
684 /*
685 * 32-bit.
686 */
687 pPGM->pInterPD->a[iOldPDE].u = 0;
688 pPGM->pHC32BitPD->a[iOldPDE].u = 0;
689
690 /*
691 * PAE.
692 */
693 const int iPD = iOldPDE / 256;
694 int iPDE = iOldPDE * 2 % 512;
695 pPGM->apInterPaePDs[iPD]->a[iPDE].u = 0;
696 pPGM->apHCPaePDs[iPD]->a[iPDE].u = 0;
697 iPDE++;
698 pPGM->apInterPaePDs[iPD]->a[iPDE].u = 0;
699 pPGM->apHCPaePDs[iPD]->a[iPDE].u = 0;
700 }
701}
702
703
704/**
705 * Sets all PDEs involved with the mapping.
706 *
707 * @param pVM The VM handle.
708 * @param pMap Pointer to the mapping in question.
709 * @param iNewPDE The index of the 32-bit PDE corresponding to the base of the mapping.
710 */
711static void pgmR3MapSetPDEs(PVM pVM, PPGMMAPPING pMap, int iNewPDE)
712{
713 PPGM pPGM = &pVM->pgm.s;
714
715 /* If mappings are not supposed to be put in the shadow page table, then this function is a nop. */
716 if (!pgmMapAreMappingsEnabled(&pVM->pgm.s))
717 return;
718
719 /*
720 * Init the page tables and insert them into the page directories.
721 */
722 unsigned i = pMap->cPTs;
723 iNewPDE += i;
724 while (i-- > 0)
725 {
726 iNewPDE--;
727
728 /*
729 * 32-bit.
730 */
731 if (pPGM->pHC32BitPD->a[iNewPDE].n.u1Present)
732 pgmPoolFree(pVM, pPGM->pHC32BitPD->a[iNewPDE].n.u1Present & X86_PDE_PG_MASK, PGMPOOL_IDX_PD, iNewPDE);
733 X86PDE Pde;
734 /* Default mapping page directory flags are read/write and supervisor; individual page attributes determine the final flags */
735 Pde.u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | (uint32_t)pMap->aPTs[i].HCPhysPT;
736 pPGM->pInterPD->a[iNewPDE] = Pde;
737 pPGM->pHC32BitPD->a[iNewPDE] = Pde;
738
739 /*
740 * PAE.
741 */
742 const int iPD = iNewPDE / 256;
743 int iPDE = iNewPDE * 2 % 512;
744 if (pPGM->apHCPaePDs[iPD]->a[iPDE].n.u1Present)
745 pgmPoolFree(pVM, pPGM->apHCPaePDs[iPD]->a[iPDE].n.u1Present & X86_PDE_PAE_PG_MASK, PGMPOOL_IDX_PAE_PD, iNewPDE * 2);
746 X86PDEPAE PdePae0;
747 PdePae0.u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | pMap->aPTs[i].HCPhysPaePT0;
748 pPGM->apInterPaePDs[iPD]->a[iPDE] = PdePae0;
749 pPGM->apHCPaePDs[iPD]->a[iPDE] = PdePae0;
750
751 iPDE++;
752 if (pPGM->apHCPaePDs[iPD]->a[iPDE].n.u1Present)
753 pgmPoolFree(pVM, pPGM->apHCPaePDs[iPD]->a[iPDE].n.u1Present & X86_PDE_PAE_PG_MASK, PGMPOOL_IDX_PAE_PD, iNewPDE * 2 + 1);
754 X86PDEPAE PdePae1;
755 PdePae1.u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | pMap->aPTs[i].HCPhysPaePT1;
756 pPGM->apInterPaePDs[iPD]->a[iPDE] = PdePae1;
757 pPGM->apHCPaePDs[iPD]->a[iPDE] = PdePae1;
758 }
759}
760
761/**
762 * Relocates a mapping to a new address.
763 *
764 * @param pVM VM handle.
765 * @param pMapping The mapping to relocate.
766 * @param iPDOld Old page directory index.
767 * @param iPDNew New page directory index.
768 */
769void pgmR3MapRelocate(PVM pVM, PPGMMAPPING pMapping, int iPDOld, int iPDNew)
770{
771 Log(("PGM: Relocating %s from %#x to %#x\n", pMapping->pszDesc, iPDOld << PGDIR_SHIFT, iPDNew << PGDIR_SHIFT));
772 Assert(((unsigned)iPDOld << PGDIR_SHIFT) == pMapping->GCPtr);
773
774 /*
775 * Relocate the page table(s).
776 */
777 pgmR3MapClearPDEs(&pVM->pgm.s, pMapping, iPDOld);
778 pgmR3MapSetPDEs(pVM, pMapping, iPDNew);
779
780 /*
781 * Update and resort the mapping list.
782 */
783
784 /* Find previous mapping for pMapping, put result into pPrevMap. */
785 PPGMMAPPING pPrevMap = NULL;
786 PPGMMAPPING pCur = pVM->pgm.s.pMappingsHC;
787 while (pCur && pCur != pMapping)
788 {
789 /* next */
790 pPrevMap = pCur;
791 pCur = pCur->pNextHC;
792 }
793 Assert(pCur);
794
795 /* Find mapping which >= than pMapping. */
796 RTGCPTR GCPtrNew = iPDNew << PGDIR_SHIFT;
797 PPGMMAPPING pPrev = NULL;
798 pCur = pVM->pgm.s.pMappingsHC;
799 while (pCur && pCur->GCPtr < GCPtrNew)
800 {
801 /* next */
802 pPrev = pCur;
803 pCur = pCur->pNextHC;
804 }
805
806 if (pCur != pMapping && pPrev != pMapping)
807 {
808 /*
809 * Unlink.
810 */
811 if (pPrevMap)
812 {
813 pPrevMap->pNextHC = pMapping->pNextHC;
814 pPrevMap->pNextGC = pMapping->pNextGC;
815 }
816 else
817 {
818 pVM->pgm.s.pMappingsHC = pMapping->pNextHC;
819 pVM->pgm.s.pMappingsGC = pMapping->pNextGC;
820 }
821
822 /*
823 * Link
824 */
825 pMapping->pNextHC = pCur;
826 if (pPrev)
827 {
828 pMapping->pNextGC = pPrev->pNextGC;
829 pPrev->pNextHC = pMapping;
830 pPrev->pNextGC = MMHyperHC2GC(pVM, pMapping);
831 }
832 else
833 {
834 pMapping->pNextGC = pVM->pgm.s.pMappingsGC;
835 pVM->pgm.s.pMappingsHC = pMapping;
836 pVM->pgm.s.pMappingsGC = MMHyperHC2GC(pVM, pMapping);
837 }
838 }
839
840 /*
841 * Update the entry.
842 */
843 pMapping->GCPtr = GCPtrNew;
844 pMapping->GCPtrLast = GCPtrNew + pMapping->cb - 1;
845
846 /*
847 * Callback to execute the relocation.
848 */
849 pMapping->pfnRelocate(pVM, iPDOld << PGDIR_SHIFT, iPDNew << PGDIR_SHIFT, PGMRELOCATECALL_RELOCATE, pMapping->pvUser);
850}
851
852
853/**
854 * Resolves a conflict between a page table based GC mapping and
855 * the Guest OS page tables.
856 *
857 * @returns VBox status code.
858 * @param pVM VM Handle.
859 * @param pMapping The mapping which conflicts.
860 * @param pPDSrc The page directory of the guest OS.
861 * @param iPDOld The index to the start of the current mapping.
862 */
863int pgmR3SyncPTResolveConflict(PVM pVM, PPGMMAPPING pMapping, PVBOXPD pPDSrc, int iPDOld)
864{
865 STAM_PROFILE_START(&pVM->pgm.s.StatHCResolveConflict, a);
866
867 /*
868 * Scan for free page directory entries.
869 *
870 * Note that we do not support mappings at the very end of the
871 * address space since that will break our GCPtrEnd assumptions.
872 */
873 const unsigned cPTs = pMapping->cPTs;
874 unsigned iPDNew = ELEMENTS(pPDSrc->a) - cPTs; /* (+ 1 - 1) */
875 while (iPDNew-- > 0)
876 {
877 if (pPDSrc->a[iPDNew].n.u1Present)
878 continue;
879 if (cPTs > 1)
880 {
881 bool fOk = true;
882 for (unsigned i = 1; fOk && i < cPTs; i++)
883 if (pPDSrc->a[iPDNew + i].n.u1Present)
884 fOk = false;
885 if (!fOk)
886 continue;
887 }
888
889 /*
890 * Check that it's not conflicting with an intermediate page table mapping.
891 */
892 bool fOk = true;
893 unsigned i = cPTs;
894 while (fOk && i-- > 0)
895 fOk = !pVM->pgm.s.pInterPD->a[iPDNew + i].n.u1Present;
896 if (!fOk)
897 continue;
898 /** @todo AMD64 should check the PAE directories and skip the 32bit stuff. */
899
900 /*
901 * Ask the mapping.
902 */
903 if (pMapping->pfnRelocate(pVM, iPDOld << PGDIR_SHIFT, iPDNew << PGDIR_SHIFT, PGMRELOCATECALL_SUGGEST, pMapping->pvUser))
904 {
905 pgmR3MapRelocate(pVM, pMapping, iPDOld, iPDNew);
906 STAM_PROFILE_STOP(&pVM->pgm.s.StatHCResolveConflict, a);
907 return VINF_SUCCESS;
908 }
909 }
910
911 STAM_PROFILE_STOP(&pVM->pgm.s.StatHCResolveConflict, a);
912 AssertMsgFailed(("Failed to relocate page table mapping '%s' from %#x! (cPTs=%d)\n", pMapping->pszDesc, iPDOld << PGDIR_SHIFT, cPTs));
913 return VERR_PGM_NO_HYPERVISOR_ADDRESS;
914}
915
916
917
918/**
919 * Checks guest PD for conflicts with VMM GC mappings.
920 *
921 * @returns true if conflict detected.
922 * @returns false if not.
923 * @param pVM The virtual machine.
924 * @param cr3 Guest context CR3 register.
925 * @param fRawR0 Whether RawR0 is enabled or not.
926 */
927PGMR3DECL(bool) PGMR3MapHasConflicts(PVM pVM, uint32_t cr3, bool fRawR0) /** @todo how many HasConflict constructs do we really need? */
928{
929 /*
930 * Can skip this if mappings are safely fixed.
931 */
932 if (pVM->pgm.s.fMappingsFixed)
933 return false;
934
935 /*
936 * Resolve the page directory.
937 */
938 PVBOXPD pPD = pVM->pgm.s.pGuestPDHC; /** @todo Fix PAE! */
939 Assert(pPD);
940 Assert(pPD == (PVBOXPD)MMPhysGCPhys2HCVirt(pVM, cr3 & X86_CR3_PAGE_MASK));
941
942 /*
943 * Iterate mappings.
944 */
945 for (PPGMMAPPING pCur = pVM->pgm.s.pMappingsHC; pCur; pCur = pCur->pNextHC)
946 {
947 unsigned iPDE = pCur->GCPtr >> PGDIR_SHIFT;
948 unsigned iPT = pCur->cPTs;
949 while (iPT-- > 0)
950 if ( pPD->a[iPDE + iPT].n.u1Present /** @todo PGMGstGetPDE. */
951 && (fRawR0 || pPD->a[iPDE + iPT].n.u1User))
952 {
953 STAM_COUNTER_INC(&pVM->pgm.s.StatHCDetectedConflicts);
954 #if 1
955 Log(("PGMR3HasMappingConflicts: Conflict was detected at %VGv for mapping %s\n"
956 " iPDE=%#x iPT=%#x PDE=%VGp.\n",
957 (iPT + iPDE) << PGDIR_SHIFT, pCur->pszDesc,
958 iPDE, iPT, pPD->a[iPDE + iPT].au32[0]));
959 #else
960 AssertMsgFailed(("PGMR3HasMappingConflicts: Conflict was detected at %VGv for mapping %s\n"
961 " iPDE=%#x iPT=%#x PDE=%VGp.\n",
962 (iPT + iPDE) << PGDIR_SHIFT, pCur->pszDesc,
963 iPDE, iPT, pPD->a[iPDE + iPT].au32[0]));
964 #endif
965 return true;
966 }
967 }
968
969 return false;
970}
971
972
973/**
974 * Read memory from the guest mappings.
975 *
976 * This will use the page tables associated with the mappings to
977 * read the memory. This means that not all kind of memory is readable
978 * since we don't necessarily know how to convert that physical address
979 * to a HC virtual one.
980 *
981 * @returns VBox status.
982 * @param pVM VM handle.
983 * @param pvDst The destination address (HC of course).
984 * @param GCPtrSrc The source address (GC virtual address).
985 * @param cb Number of bytes to read.
986 */
987PGMR3DECL(int) PGMR3MapRead(PVM pVM, void *pvDst, RTGCPTR GCPtrSrc, size_t cb)
988{
989/** @todo remove this simplicity hack */
990 /*
991 * Simplicity over speed... Chop the request up into chunks
992 * which don't cross pages.
993 */
994 if (cb + (GCPtrSrc & PAGE_OFFSET_MASK) > PAGE_SIZE)
995 {
996 for (;;)
997 {
998 unsigned cbRead = RT_MIN(cb, PAGE_SIZE - (GCPtrSrc & PAGE_OFFSET_MASK));
999 int rc = PGMR3MapRead(pVM, pvDst, GCPtrSrc, cbRead);
1000 if (VBOX_FAILURE(rc))
1001 return rc;
1002 cb -= cbRead;
1003 if (!cb)
1004 break;
1005 pvDst = (char *)pvDst + cbRead;
1006 GCPtrSrc += cbRead;
1007 }
1008 return VINF_SUCCESS;
1009 }
1010
1011 /*
1012 * Find the mapping.
1013 */
1014 PPGMMAPPING pCur = CTXSUFF(pVM->pgm.s.pMappings);
1015 while (pCur)
1016 {
1017 RTGCUINTPTR off = (RTGCUINTPTR)GCPtrSrc - (RTGCUINTPTR)pCur->GCPtr;
1018 if (off < pCur->cb)
1019 {
1020 if (off + cb > pCur->cb)
1021 {
1022 AssertMsgFailed(("Invalid page range %VGv LB%#x. mapping '%s' %VGv to %VGv\n",
1023 GCPtrSrc, cb, pCur->pszDesc, pCur->GCPtr, pCur->GCPtrLast));
1024 return VERR_INVALID_PARAMETER;
1025 }
1026
1027 unsigned iPT = off >> PGDIR_SHIFT;
1028 unsigned iPTE = (off >> PAGE_SHIFT) & PTE_MASK;
1029 while (cb > 0 && iPTE < ELEMENTS(CTXSUFF(pCur->aPTs[iPT].pPT)->a))
1030 {
1031 if (!CTXSUFF(pCur->aPTs[iPT].paPaePTs)[iPTE / 512].a[iPTE % 512].n.u1Present)
1032 return VERR_PAGE_NOT_PRESENT;
1033 RTHCPHYS HCPhys = CTXSUFF(pCur->aPTs[iPT].paPaePTs)[iPTE / 512].a[iPTE % 512].u & X86_PTE_PAE_PG_MASK;
1034
1035 /*
1036 * Get the virtual page from the physical one.
1037 */
1038 void *pvPage;
1039 int rc = MMR3HCPhys2HCVirt(pVM, HCPhys, &pvPage);
1040 if (VBOX_FAILURE(rc))
1041 return rc;
1042
1043 memcpy(pvDst, (char *)pvPage + (GCPtrSrc & PAGE_OFFSET_MASK), cb);
1044 return VINF_SUCCESS;
1045 }
1046 }
1047
1048 /* next */
1049 pCur = CTXSUFF(pCur->pNext);
1050 }
1051
1052 return VERR_INVALID_POINTER;
1053}
1054
1055
1056/**
1057 * Dumps one virtual handler range.
1058 *
1059 * @returns 0
1060 * @param pNode Pointer to a PGMVIRTHANDLER.
1061 * @param pvUser Pointer to command helper functions.
1062 */
1063static DECLCALLBACK(int) pgmVirtHandlerDump(PAVLROGCPTRNODECORE pNode, void *pvUser)
1064{
1065 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
1066
1067 switch (pCur->enmType)
1068 {
1069 case PGMVIRTHANDLERTYPE_EIP:
1070 RTLogPrintf("EIP %RGv-%RGv size %RGv %s\n", pCur->GCPtr, pCur->GCPtrLast, pCur->cb, pCur->pszDesc);
1071 break;
1072 case PGMVIRTHANDLERTYPE_NORMAL:
1073 RTLogPrintf("NORMAL %RGv-%RGv size %RGv %s\n", pCur->GCPtr, pCur->GCPtrLast, pCur->cb, pCur->pszDesc);
1074 break;
1075 case PGMVIRTHANDLERTYPE_WRITE:
1076 RTLogPrintf("WRITE %RGv-%RGv size %RGv %s\n", pCur->GCPtr, pCur->GCPtrLast, pCur->cb, pCur->pszDesc);
1077 break;
1078 case PGMVIRTHANDLERTYPE_HYPERVISOR:
1079 RTLogPrintf("WRITEHYP %RGv-%RGv size %RGv %s\n", pCur->GCPtr, pCur->GCPtrLast, pCur->cb, pCur->pszDesc);
1080 break;
1081 case PGMVIRTHANDLERTYPE_ALL:
1082 RTLogPrintf("ALL %RGv-%RGv size %RGv %s\n", pCur->GCPtr, pCur->GCPtrLast, pCur->cb, pCur->pszDesc);
1083 break;
1084 }
1085 if (pCur->enmType != PGMVIRTHANDLERTYPE_HYPERVISOR)
1086 for (unsigned i = 0; i < pCur->cPages; i++)
1087 RTLogPrintf("Physical page %#05d %VGp\n", i, pCur->aPhysToVirt[i].Core.Key);
1088 return 0;
1089}
1090
1091/**
1092 * Dumps the current mappings to the log
1093 *
1094 * @returns VBox status.
1095 * @param pVM Pointer to the current VM (if any).
1096 *
1097 */
1098PGMR3DECL(void) PGMR3DumpMappings(PVM pVM)
1099{
1100 /*
1101 * Print message about the fixedness of the mappings and dump them.
1102 */
1103 RTLogPrintf(pVM->pgm.s.fMappingsFixed ? "\nThe mappings are FIXED.\n" : "\nThe mappings are FLOATING.\n");
1104
1105 PPGMMAPPING pCur;
1106 for (pCur = pVM->pgm.s.pMappingsHC; pCur; pCur = pCur->pNextHC)
1107 RTLogPrintf("%VGv - %VGv %s\n", pCur->GCPtr, pCur->GCPtrLast, pCur->pszDesc);
1108
1109/** @todo The handler stuff is totally alien here. This should be converted into a 'info' function. */
1110 RTLogPrintf("\nVirtual handlers:\n");
1111 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesHC->VirtHandlers, true, pgmVirtHandlerDump, pVM);
1112
1113 RTLogPrintf("\n"
1114 "Physical handlers: (PhysHandlers=%d (%#x))\n"
1115 "From - To (incl) HandlerHC UserHC HandlerHC UserHC HandlerGC UserGC Type Description\n",
1116 pVM->pgm.s.pTreesHC->PhysHandlers, pVM->pgm.s.pTreesHC->PhysHandlers);
1117 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesHC->PhysHandlers, true, pgmR3DumpMappingsPhysicalCB, NULL);
1118}
1119
1120
1121/**
1122 * Dumps one physical handler range.
1123 *
1124 * @returns 0
1125 * @param pNode Pointer to a PGMPHYSHANDLER.
1126 * @param pvUser Ignored.
1127 */
1128static DECLCALLBACK(int) pgmR3DumpMappingsPhysicalCB(PAVLROGCPHYSNODECORE pNode, void *pvUser)
1129{
1130 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode; NOREF(pvUser);
1131 const char *pszType;
1132 switch (pCur->enmType)
1133 {
1134 case PGMPHYSHANDLERTYPE_MMIO: pszType = "MMIO "; break;
1135 case PGMPHYSHANDLERTYPE_PHYSICAL: pszType = "Natural"; break;
1136 case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE: pszType = "Write "; break;
1137 case PGMPHYSHANDLERTYPE_PHYSICAL_ALL: pszType = "All "; break;
1138 default: pszType = "????"; break;
1139 }
1140 RTLogPrintf("%VGp - %VGp %VHv %VHv %VHv %VHv %VGv %VGv %s %s\n",
1141 pCur->Core.Key, pCur->Core.KeyLast, pCur->pfnHandlerR3, pCur->pvUserR3, pCur->pfnHandlerR0, pCur->pvUserR0,
1142 pCur->pfnHandlerGC, pCur->pvUserGC, pszType, pCur->pszDesc);
1143 return 0;
1144}
1145
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette