VirtualBox

Changeset 51643 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
Jun 18, 2014 11:06:06 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
94404
Message:

VMM/GIM: More bits for Hyper-V implementation.

Location:
trunk/src/VBox/VMM/VMMR0
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/GIMR0.cpp

    r51560 r51643  
    2323#include "GIMHvInternal.h"
    2424
    25 #include <iprt/err.h>
     25#include <VBox/err.h>
    2626#include <VBox/vmm/vm.h>
    2727
     
    7272}
    7373
     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 */
     90VMMR0_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  
    2323#include "GIMHvInternal.h"
    2424
    25 #include <iprt/err.h>
    26 #include <iprt/asm.h>
    27 #include <iprt/memobj.h>
     25#include <VBox/err.h>
    2826#include <VBox/vmm/gim.h>
    2927#include <VBox/vmm/vm.h>
    3028
     29#include <iprt/spinlock.h>
    3130
     31
     32#if 0
    3233/**
    3334 * Allocates and maps one physically contiguous page. The allocated page is
     
    8081    }
    8182}
     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 */
     93VMM_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}
    82117
    83118
     
    90125VMMR0_INT_DECL(int) GIMR0HvInitVM(PVM pVM)
    91126{
    92 #if 0
    93127    AssertPtr(pVM);
    94128    Assert(GIMIsEnabled(pVM));
    95129
    96130    PGIMHV pHv = &pVM->gim.s.u.Hv;
    97     Assert(pHv->hMemObjTscPage == NIL_RTR0MEMOBJ);
     131    Assert(pHv->hSpinlockR0 == NIL_RTSPINLOCK);
    98132
    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");
    112134    return rc;
    113 #endif
    114135}
    115136
     
    125146    AssertPtr(pVM);
    126147    Assert(GIMIsEnabled(pVM));
    127 #if 0
     148
    128149    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
    131153    return VINF_SUCCESS;
    132154}
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r51421 r51643  
    3030#include <VBox/vmm/iom.h>
    3131#include <VBox/vmm/tm.h>
     32#include <VBox/vmm/gim.h>
    3233
    3334#ifdef DEBUG_ramshankar
     
    22342235static void hmR0SvmUpdateTscOffsetting(PVMCPU pVCpu)
    22352236{
     2237    bool     fParavirtTsc = false;
    22362238    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))
    22412256        {
    22422257            pVmcb->ctrl.u32InterceptCtrl1 &= ~SVM_CTRL1_INTERCEPT_RDTSC;
     
    22532268    else
    22542269    {
     2270        Assert(!fParavirtTsc);
    22552271        pVmcb->ctrl.u32InterceptCtrl1 |= SVM_CTRL1_INTERCEPT_RDTSC;
    22562272        pVmcb->ctrl.u32InterceptCtrl2 |= SVM_CTRL2_INTERCEPT_RDTSCP;
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r51244 r51643  
    3434#include <VBox/vmm/selm.h>
    3535#include <VBox/vmm/tm.h>
     36#include <VBox/vmm/gim.h>
    3637#ifdef VBOX_WITH_REM
    3738# include <VBox/vmm/rem.h>
     
    336337*   Internal Functions                                                         *
    337338*******************************************************************************/
    338 static void               hmR0VmxFlushEpt(PVMCPU pVCpu, VMX_FLUSH_EPT enmFlush);
    339 static void               hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_VPID enmFlush, RTGCPTR GCPtr);
     339static void               hmR0VmxFlushEpt(PVMCPU pVCpu, VMXFLUSHEPT enmFlush);
     340static void               hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMXFLUSHVPID enmFlush, RTGCPTR GCPtr);
    340341static int                hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntInfo, uint32_t cbInstr,
    341342                                                 uint32_t u32ErrCode, RTGCUINTREG GCPtrFaultAddress, uint32_t *puIntState);
     
    10671068    if (pMsrs->u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
    10681069    {
    1069         hmR0VmxFlushEpt(NULL /* pVCpu */, VMX_FLUSH_EPT_ALL_CONTEXTS);
     1070        hmR0VmxFlushEpt(NULL /* pVCpu */, VMXFLUSHEPT_ALL_CONTEXTS);
    10701071        pCpu->fFlushAsidBeforeUse = false;
    10711072    }
     
    16981699 * @remarks Can be called with interrupts disabled.
    16991700 */
    1700 static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMX_FLUSH_EPT enmFlush)
     1701static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMXFLUSHEPT enmFlush)
    17011702{
    17021703    uint64_t au64Descriptor[2];
    1703     if (enmFlush == VMX_FLUSH_EPT_ALL_CONTEXTS)
     1704    if (enmFlush == VMXFLUSHEPT_ALL_CONTEXTS)
    17041705        au64Descriptor[0] = 0;
    17051706    else
     
    17341735 * @remarks Can be called with interrupts disabled.
    17351736 */
    1736 static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_VPID enmFlush, RTGCPTR GCPtr)
     1737static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMXFLUSHVPID enmFlush, RTGCPTR GCPtr)
    17371738{
    17381739    NOREF(pVM);
     
    17411742
    17421743    uint64_t au64Descriptor[2];
    1743     if (enmFlush == VMX_FLUSH_VPID_ALL_CONTEXTS)
     1744    if (enmFlush == VMXFLUSHVPID_ALL_CONTEXTS)
    17441745    {
    17451746        au64Descriptor[0] = 0;
     
    17951796            if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
    17961797            {
    1797                 hmR0VmxFlushVpid(pVM, pVCpu, VMX_FLUSH_VPID_INDIV_ADDR, GCVirt);
     1798                hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_INDIV_ADDR, GCVirt);
    17981799                STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
    17991800            }
     
    19611962        {
    19621963            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]);
    19641965        }
    19651966        else
     
    21202121        if (pCpu->fFlushAsidBeforeUse)
    21212122        {
    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)
    21252126            {
    2126                 hmR0VmxFlushVpid(pVM, pVCpu, VMX_FLUSH_VPID_ALL_CONTEXTS, 0 /* GCPtr */);
     2127                hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
    21272128                pCpu->fFlushAsidBeforeUse = false;
    21282129            }
     
    21512152            {
    21522153                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]);
    21542155            }
    21552156            else
     
    22262227        {
    22272228            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;
    22292230            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;
    22312232            else
    22322233            {
    22332234                /* 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;
    22352236                return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
    22362237            }
     
    22402241            {
    22412242                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;
    22432244                return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
    22442245            }
     
    22472248        {
    22482249            /* 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;
    22502251            return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
    22512252        }
     
    22602261        {
    22612262            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;
    22632264            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;
    22652266            else
    22662267            {
     
    22702271                if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
    22712272                    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;
    22732274                pVM->hm.s.vmx.fVpid = false;
    22742275            }
     
    22782279            /*  Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
    22792280            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;
    22812282            pVM->hm.s.vmx.fVpid = false;
    22822283        }
     
    27282729
    27292730    /* 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;
    27322733
    27332734    /* Setup the tagged-TLB flush handlers. */
     
    55655566    int  rc            = VERR_INTERNAL_ERROR_5;
    55665567    bool fOffsettedTsc = false;
     5568    bool fParavirtTsc  = false;
    55675569    PVM pVM            = pVCpu->CTX_SUFF(pVM);
    55685570    if (pVM->hm.s.vmx.fUsePreemptTimer)
    55695571    {
    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);
    55715574
    55725575        /* Make sure the returned values have sane upper and lower boundaries. */
     
    55805583    }
    55815584    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    }
    55835611
    55845612    if (fOffsettedTsc)
     
    1035810386              ("hmR0VmxExitRdmsr: failed, invalid error code %Rrc\n", rc));
    1035910387    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
    10360 
    1036110388    if (RT_LIKELY(rc == VINF_SUCCESS))
    1036210389    {
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r49481 r51643  
    3636#include <VBox/vmm/gvmm.h>
    3737#include <VBox/vmm/gmm.h>
     38#include <VBox/vmm/gim.h>
    3839#include <VBox/intnet.h>
    3940#include <VBox/vmm/hm.h>
     
    379380                    if (RT_SUCCESS(rc))
    380381                    {
    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
    383393                    }
    384394                }
    385 
    386                 /* bail out */
    387395            }
    388 #ifdef VBOX_WITH_PCI_PASSTHROUGH
    389             PciRawR0TermVM(pVM);
    390 #endif
    391396            HMR0TermVM(pVM);
    392397        }
     
    423428    if (GVMMR0DoingTermVM(pVM, pGVM))
    424429    {
     430        GIMR0TermVM(pVM);
     431
    425432        /** @todo I wish to call PGMR0PhysFlushHandyPages(pVM, &pVM->aCpus[idCpu])
    426433         *        here to make sure we don't leak any shared pages if we crash... */
Note: See TracChangeset for help on using the changeset viewer.

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