74
74
cb = RT_ALIGN_32(cb, _4M);
75
75
RTGCPTR GCPtrLast = GCPtr + cb - 1;
76
if (GCPtrLast < GCPtr)
78
AssertMsgFailed(("Range wraps! GCPtr=%x GCPtrLast=%x\n", GCPtr, GCPtrLast));
79
return VERR_INVALID_PARAMETER;
81
if (pVM->pgm.s.fMappingsFixed)
83
AssertMsgFailed(("Mappings are fixed! It's not possible to add new mappings at this time!\n"));
84
return VERR_PGM_MAPPINGS_FIXED;
88
AssertMsgFailed(("Callback is required\n"));
89
return VERR_INVALID_PARAMETER;
77
AssertMsgReturn(GCPtrLast >= GCPtr, ("Range wraps! GCPtr=%x GCPtrLast=%x\n", GCPtr, GCPtrLast),
78
VERR_INVALID_PARAMETER);
79
AssertMsgReturn(!pVM->pgm.s.fMappingsFixed, ("Mappings are fixed! It's not possible to add new mappings at this time!\n"),
80
VERR_PGM_MAPPINGS_FIXED);
81
AssertPtrReturn(pfnRelocate, VERR_INVALID_PARAMETER);
93
84
* Find list location.
267
258
* and free the page tables and node memory.
269
260
MMHyperFree(pVM, pCur->aPTs[0].pPTR3);
270
pgmR3MapClearPDEs(pVM, pCur, pCur->GCPtr >> X86_PD_SHIFT);
261
if (pCur->GCPtr != NIL_RTGCPTR)
262
pgmR3MapClearPDEs(pVM, pCur, pCur->GCPtr >> X86_PD_SHIFT);
271
263
MMHyperFree(pVM, pCur);
273
265
for (VMCPUID i = 0; i < pVM->cCpus; i++)
513
507
VMMR3DECL(int) PGMR3MappingsFix(PVM pVM, RTGCPTR GCPtrBase, uint32_t cb)
515
Log(("PGMR3MappingsFix: GCPtrBase=%#x cb=%#x\n", GCPtrBase, cb));
509
Log(("PGMR3MappingsFix: GCPtrBase=%RGv cb=%#x (fMappingsFixed=%RTbool fMappingsDisabled=%RTbool)\n",
510
GCPtrBase, cb, pVM->pgm.s.fMappingsFixed, pVM->pgm.s.fMappingsDisabled));
517
/* Ignore the additions mapping fix call in VT-x/AMD-V. */
518
if ( pVM->pgm.s.fMappingsFixed
519
&& HWACCMIsEnabled(pVM))
513
* Ignore the additions mapping fix call if disabled.
515
if (!pgmMapAreMappingsEnabled(&pVM->pgm.s))
517
Assert(HWACCMIsEnabled(pVM));
520
518
return VINF_SUCCESS;
522
/* Only applies to VCPU 0 as we don't support SMP guests with raw mode. */
522
* Only applies to VCPU 0 as we don't support SMP guests with raw mode.
523
524
Assert(pVM->cCpus == 1);
525
525
PVMCPU pVCpu = &pVM->aCpus[0];
528
* This is all or nothing at all. So, a tiny bit of paranoia first.
530
if (GCPtrBase & X86_PAGE_4M_OFFSET_MASK)
532
AssertMsgFailed(("GCPtrBase (%#x) has to be aligned on a 4MB address!\n", GCPtrBase));
533
return VERR_INVALID_PARAMETER;
535
if (!cb || (cb & X86_PAGE_4M_OFFSET_MASK))
537
AssertMsgFailed(("cb (%#x) is 0 or not aligned on a 4MB address!\n", cb));
538
return VERR_INVALID_PARAMETER;
542
528
* Before we do anything we'll do a forced PD sync to try make sure any
543
529
* pending relocations because of these mappings have been resolved.
545
531
PGMSyncCR3(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu), true);
533
return pgmR3MappingsFixInternal(pVM, GCPtrBase, cb);
538
* Internal worker for PGMR3MappingsFix and pgmR3Load.
540
* (This does not perform a SyncCR3 before the fixation like PGMR3MappingsFix.)
542
* @returns VBox status code.
544
* @param GCPtrBase The address of the reserved range of guest memory.
545
* @param cb The size of the range starting at GCPtrBase.
547
int pgmR3MappingsFixInternal(PVM pVM, RTGCPTR GCPtrBase, uint32_t cb)
550
* Check input arguments and pre-conditions.
552
AssertMsgReturn(!(GCPtrBase & X86_PAGE_4M_OFFSET_MASK), ("GCPtrBase (%#x) has to be aligned on a 4MB address!\n", GCPtrBase),
553
VERR_INVALID_PARAMETER);
554
AssertMsgReturn(cb && !(cb & X86_PAGE_4M_OFFSET_MASK), ("cb (%#x) is 0 or not aligned on a 4MB address!\n", cb),
555
VERR_INVALID_PARAMETER);
556
AssertReturn(pgmMapAreMappingsEnabled(&pVM->pgm.s), VERR_INTERNAL_ERROR_3);
557
AssertReturn(pVM->cCpus == 1, VERR_INTERNAL_ERROR_4);
548
560
* Check that it's not conflicting with a core code mapping in the intermediate page table.
618
631
pCur = pVM->pgm.s.pMappingsR3;
621
unsigned iPDOld = pCur->GCPtr >> X86_PD_SHIFT;
622
iPDNew = GCPtrCur >> X86_PD_SHIFT;
634
RTGCPTR const GCPtrOld = pCur->GCPtr;
625
637
* Relocate the page table(s).
627
pgmR3MapClearPDEs(pVM, pCur, iPDOld);
628
pgmR3MapSetPDEs(pVM, pCur, iPDNew);
639
if (pCur->GCPtr != NIL_RTGCPTR)
640
pgmR3MapClearPDEs(pVM, pCur, GCPtrOld >> X86_PD_SHIFT);
641
pgmR3MapSetPDEs(pVM, pCur, GCPtrCur >> X86_PD_SHIFT);
631
644
* Update the entry.
637
650
* Callback to execute the relocation.
639
pCur->pfnRelocate(pVM, iPDOld << X86_PD_SHIFT, iPDNew << X86_PD_SHIFT, PGMRELOCATECALL_RELOCATE, pCur->pvUser);
652
pCur->pfnRelocate(pVM, GCPtrOld, GCPtrCur, PGMRELOCATECALL_RELOCATE, pCur->pvUser);
649
* Mark the mappings as fixed and return.
662
* Mark the mappings as fixed at this new location and return.
651
pVM->pgm.s.fMappingsFixed = true;
652
pVM->pgm.s.GCPtrMappingFixed = GCPtrBase;
653
pVM->pgm.s.cbMappingFixed = cb;
664
pVM->pgm.s.fMappingsFixed = true;
665
pVM->pgm.s.fMappingsFixedRestored = false;
666
pVM->pgm.s.GCPtrMappingFixed = GCPtrBase;
667
pVM->pgm.s.cbMappingFixed = cb;
655
669
for (VMCPUID i = 0; i < pVM->cCpus; i++)
661
675
return VINF_SUCCESS;
665
* Disable the hypervisor mappings in the shadow page tables (doesn't touch the intermediate table!)
680
* Interface for disabling the guest mappings when switching to HWACCM mode
681
* during VM creation and VM reset.
683
* (This doesn't touch the intermediate table!)
667
685
* @returns VBox status code.
668
686
* @param pVM The VM.
670
688
VMMR3DECL(int) PGMR3MappingsDisable(PVM pVM)
673
int rc = PGMR3MappingsSize(pVM, &cb);
674
AssertRCReturn(rc, rc);
676
/* Only applies to VCPU 0. */
677
PVMCPU pVCpu = &pVM->aCpus[0];
679
pgmLock(pVM); /* to avoid assertions */
680
rc = pgmMapDeactivateCR3(pVM, pVCpu->pgm.s.pShwPageCR3R3);
682
AssertRCReturn(rc, rc);
685
* Mark the mappings as fixed (using fake values) and disabled.
687
pVM->pgm.s.fDisableMappings = true;
688
pVM->pgm.s.fMappingsFixed = true;
689
pVM->pgm.s.GCPtrMappingFixed = MM_HYPER_AREA_ADDRESS;
690
pVM->pgm.s.cbMappingFixed = cb;
690
AssertReturn(!pVM->pgm.s.fMappingsFixed, VERR_INTERNAL_ERROR_4);
691
AssertReturn(!pVM->pgm.s.fMappingsFixedRestored, VERR_INTERNAL_ERROR_4);
692
if (pVM->pgm.s.fMappingsDisabled)
696
* Deactivate (only applies to Virtual CPU #0).
698
if (pVM->aCpus[0].pgm.s.pShwPageCR3R3)
700
pgmLock(pVM); /* to avoid assertions */
701
int rc = pgmMapDeactivateCR3(pVM, pVM->aCpus[0].pgm.s.pShwPageCR3R3);
703
AssertRCReturn(rc, rc);
707
* Mark the mappings as disabled and trigger a CR3 re-sync.
709
pVM->pgm.s.fMappingsDisabled = true;
691
710
for (VMCPUID i = 0; i < pVM->cCpus; i++)
693
712
PVMCPU pVCpu = &pVM->aCpus[i];
702
721
* Unfixes the mappings.
703
* After calling this function mapping conflict detection will be enabled.
723
* Unless PGMR3MappingsDisable is in effect, mapping conflict detection will be
724
* enabled after this call. If the mappings are fixed, a full CR3 resync will
725
* take place afterwards.
705
727
* @returns VBox status code.
706
728
* @param pVM The VM.
708
730
VMMR3DECL(int) PGMR3MappingsUnfix(PVM pVM)
710
Log(("PGMR3MappingsUnfix: fMappingsFixed=%d\n", pVM->pgm.s.fMappingsFixed));
712
/* Ignore in VT-x/AMD-V mode. */
713
if (HWACCMIsEnabled(pVM))
716
pVM->pgm.s.fMappingsFixed = false;
717
pVM->pgm.s.GCPtrMappingFixed = 0;
718
pVM->pgm.s.cbMappingFixed = 0;
719
for (VMCPUID i = 0; i < pVM->cCpus; i++)
732
Log(("PGMR3MappingsUnfix: fMappingsFixed=%RTbool fMappingsDisabled=%RTbool\n", pVM->pgm.s.fMappingsFixed, pVM->pgm.s.fMappingsDisabled));
733
if ( pgmMapAreMappingsEnabled(&pVM->pgm.s)
734
&& ( pVM->pgm.s.fMappingsFixed
735
|| pVM->pgm.s.fMappingsFixedRestored)
721
PVMCPU pVCpu = &pVM->aCpus[i];
722
VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
738
bool const fResyncCR3 = pVM->pgm.s.fMappingsFixed;
740
pVM->pgm.s.fMappingsFixed = false;
741
pVM->pgm.s.fMappingsFixedRestored = false;
742
pVM->pgm.s.GCPtrMappingFixed = 0;
743
pVM->pgm.s.cbMappingFixed = 0;
746
for (VMCPUID i = 0; i < pVM->cCpus; i++)
747
VMCPU_FF_SET(&pVM->aCpus[i], VMCPU_FF_PGM_SYNC_CR3);
724
749
return VINF_SUCCESS;
754
* Checks if the mappings needs re-fixing after a restore.
756
* @returns true if they need, false if not.
757
* @param pVM The VM handle.
759
VMMR3DECL(bool) PGMR3MappingsNeedReFixing(PVM pVM)
761
VM_ASSERT_VALID_EXT_RETURN(pVM, false);
762
return pVM->pgm.s.fMappingsFixedRestored;
729
767
* Map pages into the intermediate context (switcher code).
730
* These pages are mapped at both the give virtual address and at
731
* the physical address (for identity mapping).
769
* These pages are mapped at both the give virtual address and at the physical
770
* address (for identity mapping).
733
772
* @returns VBox status code.
734
773
* @param pVM The virtual machine.
1029
1069
* @param pVM VM handle.
1030
1070
* @param pMapping The mapping to relocate.
1031
1071
* @param GCPtrOldMapping The address of the start of the old mapping.
1072
* NIL_RTGCPTR if not currently mapped.
1032
1073
* @param GCPtrNewMapping The address of the start of the new mapping.
1034
void pgmR3MapRelocate(PVM pVM, PPGMMAPPING pMapping, RTGCPTR GCPtrOldMapping, RTGCPTR GCPtrNewMapping)
1075
static void pgmR3MapRelocate(PVM pVM, PPGMMAPPING pMapping, RTGCPTR GCPtrOldMapping, RTGCPTR GCPtrNewMapping)
1036
unsigned iPDOld = GCPtrOldMapping >> X86_PD_SHIFT;
1037
unsigned iPDNew = GCPtrNewMapping >> X86_PD_SHIFT;
1039
1077
Log(("PGM: Relocating %s from %RGv to %RGv\n", pMapping->pszDesc, GCPtrOldMapping, GCPtrNewMapping));
1040
AssertMsg(((unsigned)iPDOld << X86_PD_SHIFT) == pMapping->GCPtr, ("%RGv vs %RGv\n", (RTGCPTR)((unsigned)iPDOld << X86_PD_SHIFT), pMapping->GCPtr));
1078
AssertMsg(GCPtrOldMapping == pMapping->GCPtr, ("%RGv vs %RGv\n", GCPtrOldMapping, pMapping->GCPtr));
1079
AssertMsg((GCPtrOldMapping >> X86_PD_SHIFT) < X86_PG_ENTRIES, ("%RGv\n", GCPtrOldMapping));
1080
AssertMsg((GCPtrNewMapping >> X86_PD_SHIFT) < X86_PG_ENTRIES, ("%RGv\n", GCPtrOldMapping));
1043
1083
* Relocate the page table(s).
1045
pgmR3MapClearPDEs(pVM, pMapping, iPDOld);
1046
pgmR3MapSetPDEs(pVM, pMapping, iPDNew);
1085
if (GCPtrOldMapping != NIL_RTGCPTR)
1086
pgmR3MapClearPDEs(pVM, pMapping, GCPtrOldMapping >> X86_PD_SHIFT);
1087
pgmR3MapSetPDEs(pVM, pMapping, GCPtrNewMapping >> X86_PD_SHIFT);
1049
1090
* Update and resort the mapping list.
1121
1162
* Callback to execute the relocation.
1123
pMapping->pfnRelocate(pVM, iPDOld << X86_PD_SHIFT, iPDNew << X86_PD_SHIFT, PGMRELOCATECALL_RELOCATE, pMapping->pvUser);
1164
pMapping->pfnRelocate(pVM, GCPtrOldMapping, GCPtrNewMapping, PGMRELOCATECALL_RELOCATE, pMapping->pvUser);
1402
1443
DECLCALLBACK(void) pgmR3MapInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
1404
pHlp->pfnPrintf(pHlp, pVM->pgm.s.fMappingsFixed
1405
? "\nThe mappings are FIXED.\n"
1406
: "\nThe mappings are FLOATING.\n");
1445
if (pVM->pgm.s.fMappingsDisabled)
1446
pHlp->pfnPrintf(pHlp, "\nThe mappings are DISABLED.\n");
1447
else if (pVM->pgm.s.fMappingsFixed)
1448
pHlp->pfnPrintf(pHlp, "\nThe mappings are FIXED: %RGv-%RGv\n",
1449
pVM->pgm.s.GCPtrMappingFixed, pVM->pgm.s.GCPtrMappingFixed + pVM->pgm.s.cbMappingFixed - 1);
1450
else if (pVM->pgm.s.fMappingsFixedRestored)
1451
pHlp->pfnPrintf(pHlp, "\nThe mappings are FLOATING-RESTORED-FIXED: %RGv-%RGv\n",
1452
pVM->pgm.s.GCPtrMappingFixed, pVM->pgm.s.GCPtrMappingFixed + pVM->pgm.s.cbMappingFixed - 1);
1454
pHlp->pfnPrintf(pHlp, "\nThe mappings are FLOATING.\n");
1407
1456
PPGMMAPPING pCur;
1408
1457
for (pCur = pVM->pgm.s.pMappingsR3; pCur; pCur = pCur->pNextR3)
1409
1459
pHlp->pfnPrintf(pHlp, "%RGv - %RGv %s\n", pCur->GCPtr, pCur->GCPtrLast, pCur->pszDesc);
1460
if (pCur->cConflicts > 0)
1462
pHlp->pfnPrintf(pHlp, " %u conflict%s: ", pCur->cConflicts, pCur->cConflicts == 1 ? "" : "s");
1463
uint32_t cLeft = RT_MIN(pCur->cConflicts, RT_ELEMENTS(pCur->aGCPtrConflicts));
1464
uint32_t i = pCur->cConflicts;
1467
i = (i - 1) & (PGMMAPPING_CONFLICT_MAX - 1);
1468
pHlp->pfnPrintf(pHlp, cLeft ? "%RGv, " : "%RGv\n", pCur->aGCPtrConflicts[i]);