Changeset 51643 in vbox for trunk/src/VBox/VMM/VMMR0
- Timestamp:
- Jun 18, 2014 11:06:06 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 94404
- Location:
- trunk/src/VBox/VMM/VMMR0
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/GIMR0.cpp
r51560 r51643 23 23 #include "GIMHvInternal.h" 24 24 25 #include < iprt/err.h>25 #include <VBox/err.h> 26 26 #include <VBox/vmm/vm.h> 27 27 … … 72 72 } 73 73 74 /** 75 * Updates the paravirtualized TSC supported by the GIM provider. 76 * 77 * @returns VBox status code. 78 * @retval VINF_SUCCESS if the paravirt. TSC is setup and in use. 79 * @retval VERR_GIM_NOT_ENABLED if no GIM provider is configured for this VM. 80 * @retval VERR_GIM_PVTSC_NOT_AVAILABLE if the GIM provider does not support any 81 * paravirt. TSC. 82 * @retval VERR_GIM_PVTSC_NOT_IN_USE if the GIM provider supports paravirt. TSC 83 * but the guest isn't currently using it. 84 * 85 * @param pVM Pointer to the VM. 86 * @param u64Offset The computed TSC offset. 87 * 88 * @thread EMT(pVCpu) 89 */ 90 VMMR0_INT_DECL(int) GIMR0UpdateParavirtTsc(PVM pVM, uint64_t u64Offset) 91 { 92 if (!pVM->gim.s.fEnabled) 93 return VERR_GIM_NOT_ENABLED; 94 95 switch (pVM->gim.s.enmProviderId) 96 { 97 case GIMPROVIDERID_HYPERV: 98 return GIMR0HvUpdateParavirtTsc(pVM, u64Offset); 99 100 default: 101 break; 102 } 103 return VERR_GIM_PVTSC_NOT_AVAILABLE; 104 } 105 -
trunk/src/VBox/VMM/VMMR0/GIMR0Hv.cpp
r51560 r51643 23 23 #include "GIMHvInternal.h" 24 24 25 #include <iprt/err.h> 26 #include <iprt/asm.h> 27 #include <iprt/memobj.h> 25 #include <VBox/err.h> 28 26 #include <VBox/vmm/gim.h> 29 27 #include <VBox/vmm/vm.h> 30 28 29 #include <iprt/spinlock.h> 31 30 31 32 #if 0 32 33 /** 33 34 * Allocates and maps one physically contiguous page. The allocated page is … … 80 81 } 81 82 } 83 #endif 84 85 /** 86 * Updates Hyper-V's reference TSC page. 87 * 88 * @returns VBox status code. 89 * @param pVM Pointer to the VM. 90 * @param u64Offset The computed TSC offset. 91 * @thread EMT. 92 */ 93 VMM_INT_DECL(int) GIMR0HvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset) 94 { 95 Assert(GIMIsEnabled(pVM)); 96 bool fHvTscEnabled = MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr); 97 if (RT_UNLIKELY(!fHvTscEnabled)) 98 return VERR_GIM_PVTSC_NOT_ENABLED; 99 100 PCGIMHV pcHv = &pVM->gim.s.u.Hv; 101 PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; 102 PGIMHVREFTSC pRefTsc = (PGIMHVREFTSC)pcRegion->CTX_SUFF(pvPage); 103 Assert(pRefTsc); 104 105 RTSpinlockAcquire(pcHv->hSpinlockR0); 106 pRefTsc->i64TscOffset = u64Offset; 107 if (pRefTsc->u32TscSequence < UINT32_C(0xfffffffe)) 108 ASMAtomicIncU32(&pRefTsc->u32TscSequence); 109 else 110 ASMAtomicWriteU32(&pRefTsc->u32TscSequence, 1); 111 RTSpinlockRelease(pcHv->hSpinlockR0); 112 113 Assert(pRefTsc->u32TscSequence != 0); 114 Assert(pRefTsc->u32TscSequence != UINT32_C(0xffffffff)); 115 return VINF_SUCCESS; 116 } 82 117 83 118 … … 90 125 VMMR0_INT_DECL(int) GIMR0HvInitVM(PVM pVM) 91 126 { 92 #if 093 127 AssertPtr(pVM); 94 128 Assert(GIMIsEnabled(pVM)); 95 129 96 130 PGIMHV pHv = &pVM->gim.s.u.Hv; 97 Assert(pHv->h MemObjTscPage == NIL_RTR0MEMOBJ);131 Assert(pHv->hSpinlockR0 == NIL_RTSPINLOCK); 98 132 99 /* 100 * Allocate the TSC page. 101 */ 102 int rc = gimR0HvPageAllocZ(&pHv->hMemObjTscPage, &pHv->pvTscPageR0, &pHv->HCPhysTscPage); 103 if (RT_FAILURE(rc)) 104 goto cleanup; 105 #endif 106 107 return VINF_SUCCESS; 108 109 #if 0 110 cleanup: 111 gimR0HvPageFree(&pHv->hMemObjTscPage, &pHv->pvTscPageR0, &pHv->HCPhysTscPage); 133 int rc = RTSpinlockCreate(&pHv->hSpinlockR0, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "Hyper-V"); 112 134 return rc; 113 #endif114 135 } 115 136 … … 125 146 AssertPtr(pVM); 126 147 Assert(GIMIsEnabled(pVM)); 127 #if 0 148 128 149 PGIMHV pHv = &pVM->gim.s.u.Hv; 129 gimR0HvPageFree(&pHv->hMemObjTscPage, &pHv->pvTscPageR0, &pHv->HCPhysTscPage); 130 #endif 150 RTSpinlockDestroy(pHv->hSpinlockR0); 151 pHv->hSpinlockR0 = NIL_RTSPINLOCK; 152 131 153 return VINF_SUCCESS; 132 154 } -
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r51421 r51643 30 30 #include <VBox/vmm/iom.h> 31 31 #include <VBox/vmm/tm.h> 32 #include <VBox/vmm/gim.h> 32 33 33 34 #ifdef DEBUG_ramshankar … … 2234 2235 static void hmR0SvmUpdateTscOffsetting(PVMCPU pVCpu) 2235 2236 { 2237 bool fParavirtTsc = false; 2236 2238 PSVMVMCB pVmcb = (PSVMVMCB)pVCpu->hm.s.svm.pvVmcb; 2237 if (TMCpuTickCanUseRealTSC(pVCpu, &pVmcb->ctrl.u64TSCOffset)) 2238 { 2239 uint64_t u64CurTSC = ASMReadTSC(); 2240 if (u64CurTSC + pVmcb->ctrl.u64TSCOffset > TMCpuTickGetLastSeen(pVCpu)) 2239 if (TMCpuTickCanUseRealTSC(pVCpu, &pVmcb->ctrl.u64TSCOffset, &fParavirtTsc)) 2240 { 2241 uint64_t u64CurTSC = ASMReadTSC(); 2242 uint64_t u64LastTick = TMCpuTickGetLastSeen(pVCpu); 2243 if (fParavirtTsc) 2244 { 2245 if (u64CurTSC + pVmcb->ctrl.u64TSCOffset > u64LastTick) 2246 { 2247 pVmcb->ctrl.u64TSCOffset = u64LastTick - u64CurTSC; 2248 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffsetAdjusted); 2249 } 2250 int rc = GIMR0UpdateParavirtTsc(pVCpu->CTX_SUFF(pVM), pVmcb->ctrl.u64TSCOffset); 2251 AssertRC(rc); 2252 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt); 2253 } 2254 2255 if (u64CurTSC + pVmcb->ctrl.u64TSCOffset >= TMCpuTickGetLastSeen(pVCpu)) 2241 2256 { 2242 2257 pVmcb->ctrl.u32InterceptCtrl1 &= ~SVM_CTRL1_INTERCEPT_RDTSC; … … 2253 2268 else 2254 2269 { 2270 Assert(!fParavirtTsc); 2255 2271 pVmcb->ctrl.u32InterceptCtrl1 |= SVM_CTRL1_INTERCEPT_RDTSC; 2256 2272 pVmcb->ctrl.u32InterceptCtrl2 |= SVM_CTRL2_INTERCEPT_RDTSCP; -
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r51244 r51643 34 34 #include <VBox/vmm/selm.h> 35 35 #include <VBox/vmm/tm.h> 36 #include <VBox/vmm/gim.h> 36 37 #ifdef VBOX_WITH_REM 37 38 # include <VBox/vmm/rem.h> … … 336 337 * Internal Functions * 337 338 *******************************************************************************/ 338 static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMX _FLUSH_EPT enmFlush);339 static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX _FLUSH_VPID enmFlush, RTGCPTR GCPtr);339 static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMXFLUSHEPT enmFlush); 340 static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMXFLUSHVPID enmFlush, RTGCPTR GCPtr); 340 341 static int hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntInfo, uint32_t cbInstr, 341 342 uint32_t u32ErrCode, RTGCUINTREG GCPtrFaultAddress, uint32_t *puIntState); … … 1067 1068 if (pMsrs->u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS) 1068 1069 { 1069 hmR0VmxFlushEpt(NULL /* pVCpu */, VMX _FLUSH_EPT_ALL_CONTEXTS);1070 hmR0VmxFlushEpt(NULL /* pVCpu */, VMXFLUSHEPT_ALL_CONTEXTS); 1070 1071 pCpu->fFlushAsidBeforeUse = false; 1071 1072 } … … 1698 1699 * @remarks Can be called with interrupts disabled. 1699 1700 */ 1700 static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMX _FLUSH_EPT enmFlush)1701 static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMXFLUSHEPT enmFlush) 1701 1702 { 1702 1703 uint64_t au64Descriptor[2]; 1703 if (enmFlush == VMX _FLUSH_EPT_ALL_CONTEXTS)1704 if (enmFlush == VMXFLUSHEPT_ALL_CONTEXTS) 1704 1705 au64Descriptor[0] = 0; 1705 1706 else … … 1734 1735 * @remarks Can be called with interrupts disabled. 1735 1736 */ 1736 static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX _FLUSH_VPID enmFlush, RTGCPTR GCPtr)1737 static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMXFLUSHVPID enmFlush, RTGCPTR GCPtr) 1737 1738 { 1738 1739 NOREF(pVM); … … 1741 1742 1742 1743 uint64_t au64Descriptor[2]; 1743 if (enmFlush == VMX _FLUSH_VPID_ALL_CONTEXTS)1744 if (enmFlush == VMXFLUSHVPID_ALL_CONTEXTS) 1744 1745 { 1745 1746 au64Descriptor[0] = 0; … … 1795 1796 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR) 1796 1797 { 1797 hmR0VmxFlushVpid(pVM, pVCpu, VMX _FLUSH_VPID_INDIV_ADDR, GCVirt);1798 hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_INDIV_ADDR, GCVirt); 1798 1799 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt); 1799 1800 } … … 1961 1962 { 1962 1963 for (uint32_t i = 0; i < pVCpu->hm.s.TlbShootdown.cPages; i++) 1963 hmR0VmxFlushVpid(pVM, pVCpu, VMX _FLUSH_VPID_INDIV_ADDR, pVCpu->hm.s.TlbShootdown.aPages[i]);1964 hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_INDIV_ADDR, pVCpu->hm.s.TlbShootdown.aPages[i]); 1964 1965 } 1965 1966 else … … 2120 2121 if (pCpu->fFlushAsidBeforeUse) 2121 2122 { 2122 if (pVM->hm.s.vmx.enmFlushVpid == VMX _FLUSH_VPID_SINGLE_CONTEXT)2123 hmR0VmxFlushVpid(pVM, pVCpu, VMX _FLUSH_VPID_SINGLE_CONTEXT, 0 /* GCPtr */);2124 else if (pVM->hm.s.vmx.enmFlushVpid == VMX _FLUSH_VPID_ALL_CONTEXTS)2123 if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_SINGLE_CONTEXT) 2124 hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */); 2125 else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_ALL_CONTEXTS) 2125 2126 { 2126 hmR0VmxFlushVpid(pVM, pVCpu, VMX _FLUSH_VPID_ALL_CONTEXTS, 0 /* GCPtr */);2127 hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */); 2127 2128 pCpu->fFlushAsidBeforeUse = false; 2128 2129 } … … 2151 2152 { 2152 2153 for (uint32_t i = 0; i < pVCpu->hm.s.TlbShootdown.cPages; i++) 2153 hmR0VmxFlushVpid(pVM, pVCpu, VMX _FLUSH_VPID_INDIV_ADDR, pVCpu->hm.s.TlbShootdown.aPages[i]);2154 hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_INDIV_ADDR, pVCpu->hm.s.TlbShootdown.aPages[i]); 2154 2155 } 2155 2156 else … … 2226 2227 { 2227 2228 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT) 2228 pVM->hm.s.vmx.enmFlushEpt = VMX _FLUSH_EPT_SINGLE_CONTEXT;2229 pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_SINGLE_CONTEXT; 2229 2230 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS) 2230 pVM->hm.s.vmx.enmFlushEpt = VMX _FLUSH_EPT_ALL_CONTEXTS;2231 pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_ALL_CONTEXTS; 2231 2232 else 2232 2233 { 2233 2234 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */ 2234 pVM->hm.s.vmx.enmFlushEpt = VMX _FLUSH_EPT_NOT_SUPPORTED;2235 pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_NOT_SUPPORTED; 2235 2236 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO; 2236 2237 } … … 2240 2241 { 2241 2242 LogRel(("hmR0VmxSetupTaggedTlb: Unsupported EPTP memory type %#x.\n", pVM->hm.s.vmx.Msrs.u64EptVpidCaps)); 2242 pVM->hm.s.vmx.enmFlushEpt = VMX _FLUSH_EPT_NOT_SUPPORTED;2243 pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_NOT_SUPPORTED; 2243 2244 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO; 2244 2245 } … … 2247 2248 { 2248 2249 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */ 2249 pVM->hm.s.vmx.enmFlushEpt = VMX _FLUSH_EPT_NOT_SUPPORTED;2250 pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_NOT_SUPPORTED; 2250 2251 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO; 2251 2252 } … … 2260 2261 { 2261 2262 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT) 2262 pVM->hm.s.vmx.enmFlushVpid = VMX _FLUSH_VPID_SINGLE_CONTEXT;2263 pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_SINGLE_CONTEXT; 2263 2264 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS) 2264 pVM->hm.s.vmx.enmFlushVpid = VMX _FLUSH_VPID_ALL_CONTEXTS;2265 pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_ALL_CONTEXTS; 2265 2266 else 2266 2267 { … … 2270 2271 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS) 2271 2272 LogRel(("hmR0VmxSetupTaggedTlb: Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n")); 2272 pVM->hm.s.vmx.enmFlushVpid = VMX _FLUSH_VPID_NOT_SUPPORTED;2273 pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_NOT_SUPPORTED; 2273 2274 pVM->hm.s.vmx.fVpid = false; 2274 2275 } … … 2278 2279 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */ 2279 2280 Log4(("hmR0VmxSetupTaggedTlb: VPID supported without INVEPT support. Ignoring VPID.\n")); 2280 pVM->hm.s.vmx.enmFlushVpid = VMX _FLUSH_VPID_NOT_SUPPORTED;2281 pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_NOT_SUPPORTED; 2281 2282 pVM->hm.s.vmx.fVpid = false; 2282 2283 } … … 2728 2729 2729 2730 /* Initialize these always, see hmR3InitFinalizeR0().*/ 2730 pVM->hm.s.vmx.enmFlushEpt = VMX _FLUSH_EPT_NONE;2731 pVM->hm.s.vmx.enmFlushVpid = VMX _FLUSH_VPID_NONE;2731 pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_NONE; 2732 pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_NONE; 2732 2733 2733 2734 /* Setup the tagged-TLB flush handlers. */ … … 5565 5566 int rc = VERR_INTERNAL_ERROR_5; 5566 5567 bool fOffsettedTsc = false; 5568 bool fParavirtTsc = false; 5567 5569 PVM pVM = pVCpu->CTX_SUFF(pVM); 5568 5570 if (pVM->hm.s.vmx.fUsePreemptTimer) 5569 5571 { 5570 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &fOffsettedTsc, &pVCpu->hm.s.vmx.u64TSCOffset); 5572 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &fOffsettedTsc, &fParavirtTsc, 5573 &pVCpu->hm.s.vmx.u64TSCOffset); 5571 5574 5572 5575 /* Make sure the returned values have sane upper and lower boundaries. */ … … 5580 5583 } 5581 5584 else 5582 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset); 5585 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset, &fParavirtTsc); 5586 5587 if (fParavirtTsc) 5588 { 5589 uint64_t const u64CurTsc = ASMReadTSC(); 5590 uint64_t const u64LastTick = TMCpuTickGetLastSeen(pVCpu); 5591 if (u64CurTsc + pVCpu->hm.s.vmx.u64TSCOffset < u64LastTick) 5592 { 5593 pVCpu->hm.s.vmx.u64TSCOffset = (u64LastTick - u64CurTsc); 5594 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffsetAdjusted); 5595 } 5596 5597 Assert(u64CurTsc + pVCpu->hm.s.vmx.u64TSCOffset >= u64LastTick); 5598 rc = GIMR0UpdateParavirtTsc(pVM, pVCpu->hm.s.vmx.u64TSCOffset); 5599 if (RT_SUCCESS(rc)) 5600 { 5601 /* Note: VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT takes precedence over TSC_OFFSET, applies to RDTSCP too. */ 5602 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, 0); AssertRC(rc); 5603 5604 pVCpu->hm.s.vmx.u32ProcCtls &= ~VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT; 5605 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVCpu->hm.s.vmx.u32ProcCtls); AssertRC(rc); 5606 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt); 5607 return; 5608 } 5609 /* else: Shouldn't really fail. If it does, fallback to offsetted TSC mode. */ 5610 } 5583 5611 5584 5612 if (fOffsettedTsc) … … 10358 10386 ("hmR0VmxExitRdmsr: failed, invalid error code %Rrc\n", rc)); 10359 10387 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr); 10360 10361 10388 if (RT_LIKELY(rc == VINF_SUCCESS)) 10362 10389 { -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r49481 r51643 36 36 #include <VBox/vmm/gvmm.h> 37 37 #include <VBox/vmm/gmm.h> 38 #include <VBox/vmm/gim.h> 38 39 #include <VBox/intnet.h> 39 40 #include <VBox/vmm/hm.h> … … 379 380 if (RT_SUCCESS(rc)) 380 381 { 381 GVMMR0DoneInitVM(pVM); 382 return rc; 382 rc = GIMR0InitVM(pVM); 383 if (RT_SUCCESS(rc)) 384 { 385 GVMMR0DoneInitVM(pVM); 386 return rc; 387 } 388 389 /* bail out*/ 390 #ifdef VBOX_WITH_PCI_PASSTHROUGH 391 PciRawR0TermVM(pVM); 392 #endif 383 393 } 384 394 } 385 386 /* bail out */387 395 } 388 #ifdef VBOX_WITH_PCI_PASSTHROUGH389 PciRawR0TermVM(pVM);390 #endif391 396 HMR0TermVM(pVM); 392 397 } … … 423 428 if (GVMMR0DoingTermVM(pVM, pGVM)) 424 429 { 430 GIMR0TermVM(pVM); 431 425 432 /** @todo I wish to call PGMR0PhysFlushHandyPages(pVM, &pVM->aCpus[idCpu]) 426 433 * here to make sure we don't leak any shared pages if we crash... */
Note:
See TracChangeset
for help on using the changeset viewer.