VirtualBox

Changeset 74421 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Sep 22, 2018 2:38:39 PM (6 years ago)
Author:
vboxsync
Message:

VMM/CPUM, IEM: Nested VMX: bugref:9180 VM-exit bits.

Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp

    r74399 r74421  
    337337    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_VmxRoot                  , "VmxRoot"                   ),
    338338    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_Vpid                     , "Vpid"                      ),
     339    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpteCr3ReadPhys      , "HostPdpteCr3ReadPhys"      ),
     340    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte0Rsvd            , "HostPdpte0Rsvd"            ),
     341    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte1Rsvd            , "HostPdpte1Rsvd"            ),
     342    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte2Rsvd            , "HostPdpte2Rsvd"            ),
     343    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte3Rsvd            , "HostPdpte3Rsvd"            ),
    339344    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_MsrStore                  , "MsrStore"                  ),
    340345    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_MsrStoreCount             , "MsrStoreCount"             ),
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r74420 r74421  
    23462346
    23472347/**
    2348  * Gets the instruction diagnostic for CR3 referenced PDPTE reserved bits failure
    2349  * during VM-entry of a nested-guest.
     2348 * Gets the instruction diagnostic for guest CR3 referenced PDPTE reserved bits
     2349 * failure during VM-entry of a nested-guest.
    23502350 *
    23512351 * @param   iSegReg     The PDPTE entry index.
     
    23612361        case 3: return kVmxVDiag_Vmentry_GuestPdpte3Rsvd;
    23622362        IEM_NOT_REACHED_DEFAULT_CASE_RET2(kVmxVDiag_Ipe_11);
     2363    }
     2364}
     2365
     2366
     2367/**
     2368 * Gets the instruction diagnostic for host CR3 referenced PDPTE reserved bits
     2369 * failure during VM-exit of a nested-guest.
     2370 *
     2371 * @param   iSegReg     The PDPTE entry index.
     2372 */
     2373IEM_STATIC VMXVDIAG iemVmxGetDiagVmexitPdpteRsvd(unsigned iPdpte)
     2374{
     2375    Assert(iPdpte < X86_PG_PAE_PDPE_ENTRIES);
     2376    switch (iPdpte)
     2377    {
     2378        case 0: return kVmxVDiag_Vmexit_HostPdpte0Rsvd;
     2379        case 1: return kVmxVDiag_Vmexit_HostPdpte1Rsvd;
     2380        case 2: return kVmxVDiag_Vmexit_HostPdpte2Rsvd;
     2381        case 3: return kVmxVDiag_Vmexit_HostPdpte3Rsvd;
     2382        IEM_NOT_REACHED_DEFAULT_CASE_RET2(kVmxVDiag_Ipe_12);
    23632383    }
    23642384}
     
    42444264     * nested-guest (or the guest).
    42454265     *
    4246      *   - VMCPU_FF_INHIBIT_INTERRUPTS and RIP needs be preserved as there is no
    4247      *     implicit Global Interrupt Flag (GIF) handling as with AMD-V's VMRUN
    4248      *     instruction and the interrupt inhibition is in effect until the
    4249      *     completion of this VMLAUNCH/VMRESUME instruction.
     4266     *   - VMCPU_FF_INHIBIT_INTERRUPTS need not be preserved as VM-exit explicitly
     4267     *     clears interrupt-inhibition and on VM-entry the guest-interruptibility
     4268     *     state provides the inhibition if any.
    42504269     *
    4251      *   - VMCPU_FF_BLOCK_NMIS needs to be preserved as it blocks NMI until the
    4252      *     execution of a subsequent IRET instruction in the guest.
     4270     *   - VMCPU_FF_BLOCK_NMIS needs not be preserved as VM-entry does not discard
     4271     *     any NMI blocking. VM-exits caused directly by NMIs (intercepted by the
     4272     *     exception bitmap) do block subsequent NMIs.
    42534273     *
    4254      *   - MTF needs to be preserved as it's for a single instruction boundary
    4255      *     which follows the return from VMLAUNCH/VMRESUME instruction.
     4274     *   - MTF needs to be preserved as it's for a single instruction boundary which
     4275     *     follows the return from VMLAUNCH/VMRESUME instruction.
    42564276     *
    42574277     * The remaining FFs (e.g. timers) can stay in place so that we will be able to
    42584278     * generate interrupts that should cause #VMEXITs for the nested-guest.
    42594279     */
    4260     if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    4261         pVCpu->cpum.GstCtx.hwvirt.uInhibitRip = EMGetInhibitInterruptsPC(pVCpu);
    4262 
    4263     uint32_t const fGuestFFMask = VMCPU_FF_INHIBIT_INTERRUPTS | VMCPU_FF_BLOCK_NMIS | VMCPU_FF_MTF;
    4264     pVCpu->cpum.GstCtx.hwvirt.fLocalForcedActions = pVCpu->fLocalForcedActions & fGuestFFMask;
    4265     VMCPU_FF_CLEAR(pVCpu, fGuestFFMask);
    4266 }
    4267 
    4268 
    4269 #if 0
     4280    uint32_t const fNstGstDiscardMask = VMCPU_FF_MTF;
     4281    pVCpu->cpum.GstCtx.hwvirt.fLocalForcedActions = pVCpu->fLocalForcedActions & fNstGstDiscardMask;
     4282    VMCPU_FF_CLEAR(pVCpu, fNstGstDiscardMask);
     4283}
     4284
     4285
    42704286/**
    42714287 * Restores the guest force-flags in prepartion of exiting the nested-guest.
     
    42814297    }
    42824298}
    4283 #endif
    42844299
    42854300
     
    49634978        uint64_t const uHostCr0    = pVmcs->u64HostCr0.u;
    49644979        uint64_t const uGuestCr0   = pVCpu->cpum.GstCtx.cr0;
    4965         pVCpu->cpum.GstCtx.cr0     = (uHostCr0 & ~fCr0IgnMask) | (uGuestCr0 & fCr0IgnMask);
     4980        uint64_t const uValidCr0   = (uHostCr0 & ~fCr0IgnMask) | (uGuestCr0 & fCr0IgnMask);
     4981        CPUMSetGuestCR0(pVCpu, uValidCr0);
    49664982    }
    49674983
     
    49724988        uint64_t const uHostCr4    = pVmcs->u64HostCr4.u;
    49734989        uint64_t const uGuestCr4   = pVCpu->cpum.GstCtx.cr4;
    4974         pVCpu->cpum.GstCtx.cr4     = (uHostCr4 & ~fCr4IgnMask) | (uGuestCr4 & fCr4IgnMask);
    4975 
     4990        uint64_t       uValidCr4   = (uHostCr4 & ~fCr4IgnMask) | (uGuestCr4 & fCr4IgnMask);
    49764991        if (fHostInLongMode)
    4977             pVCpu->cpum.GstCtx.cr4 |= X86_CR4_PAE;
     4992            uValidCr4 |= X86_CR4_PAE;
    49784993        else
    4979             pVCpu->cpum.GstCtx.cr4 &= ~X86_CR4_PCIDE;
     4994            uValidCr4 &= ~X86_CR4_PCIDE;
     4995        CPUMSetGuestCR4(pVCpu, uValidCr4);
    49804996    }
    49814997
     
    51465162
    51475163/**
     5164 * Checks host PDPTes as part of VM-exit.
     5165 *
     5166 * @param   pVCpu           The cross context virtual CPU structure.
     5167 * @param   uExitReason     The VM-exit reason (for logging purposes).
     5168 */
     5169IEM_STATIC int iemVmxVmexitCheckHostPdptes(PVMCPU pVCpu, uint32_t uExitReason)
     5170{
     5171    /*
     5172     * Check host PDPTEs.
     5173     * See Intel spec. 27.5.4 "Checking and Loading Host Page-Directory-Pointer-Table Entries".
     5174     */
     5175    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     5176    const char *const pszFailure = "VMX-abort";
     5177    bool const fHostInLongMode = RT_BOOL(pVmcs->u32ExitCtls & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE);
     5178
     5179    if (   (pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE)
     5180        && !fHostInLongMode)
     5181    {
     5182        uint64_t const uHostCr3 = pVCpu->cpum.GstCtx.cr3 & X86_CR3_PAE_PAGE_MASK;
     5183        X86PDPE aPdptes[X86_PG_PAE_PDPE_ENTRIES];
     5184        int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), (void *)&aPdptes[0], uHostCr3, sizeof(aPdptes));
     5185        if (RT_SUCCESS(rc))
     5186        {
     5187            for (unsigned iPdpte = 0; iPdpte < RT_ELEMENTS(aPdptes); iPdpte++)
     5188            {
     5189                if (   !(aPdptes[iPdpte].u & X86_PDPE_P)
     5190                    || !(aPdptes[iPdpte].u & X86_PDPE_PAE_MBZ_MASK))
     5191                { /* likely */ }
     5192                else
     5193                {
     5194                    VMXVDIAG const enmDiag = iemVmxGetDiagVmexitPdpteRsvd(iPdpte);
     5195                    IEM_VMX_VMEXIT_FAILED_RET(pVCpu, uExitReason, pszFailure, enmDiag);
     5196                }
     5197            }
     5198        }
     5199        else
     5200            IEM_VMX_VMEXIT_FAILED_RET(pVCpu, uExitReason, pszFailure, kVmxVDiag_Vmexit_HostPdpteCr3ReadPhys);
     5201    }
     5202
     5203    NOREF(pszFailure);
     5204    NOREF(uExitReason);
     5205    return VINF_SUCCESS;
     5206}
     5207
     5208
     5209/**
    51485210 * Loads the host state as part of VM-exit.
    51495211 *
    5150  * @param   pVCpu   The cross context virtual CPU structure.
    5151  */
    5152 IEM_STATIC int iemVmxVmexitLoadHostState(PVMCPU pVCpu)
     5212 * @param   pVCpu           The cross context virtual CPU structure.
     5213 * @param   uExitReason     The VM-exit reason (for logging purposes).
     5214 */
     5215IEM_STATIC int iemVmxVmexitLoadHostState(PVMCPU pVCpu, uint32_t uExitReason)
    51535216{
    51545217    /*
     
    51815244    pVCpu->cpum.GstCtx.rflags.u = X86_EFL_1;
    51825245
    5183     /** @todo NSTVMX: rest of host state loading.  */
     5246    /* Update non-register state. */
     5247    iemVmxVmexitRestoreForceFlags(pVCpu);
     5248
     5249    /* Clear address range monitoring. */
     5250    EMMonitorWaitClear(pVCpu);
     5251
     5252    /* Perform the VMX transition (PGM updates). */
     5253    VBOXSTRICTRC rcStrict = iemVmxWorldSwitch(pVCpu);
     5254    if (rcStrict == VINF_SUCCESS)
     5255    {
     5256        /* Check host PDPTEs. */
     5257        /** @todo r=ramshankar: I don't know if PGM does this for us already or not... */
     5258        int rc = iemVmxVmexitCheckHostPdptes(pVCpu, uExitReason);
     5259        if (RT_FAILURE(rc))
     5260        {
     5261            Log(("VM-exit failed while restoring host PDPTEs -> VMX-Abort\n"));
     5262            return iemVmxAbort(pVCpu, VMXBOART_HOST_PDPTE);
     5263        }
     5264    }
     5265    else if (RT_SUCCESS(rcStrict))
     5266    {
     5267        Log3(("VM-exit: iemVmxWorldSwitch returns %Rrc (uExitReason=%u) -> Setting passup status\n", VBOXSTRICTRC_VAL(rcStrict),
     5268              uExitReason));
     5269        rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
     5270    }
     5271    else
     5272    {
     5273        Log3(("VM-exit: iemVmxWorldSwitch failed! rc=%Rrc (uExitReason=%u)\n", VBOXSTRICTRC_VAL(rcStrict), uExitReason));
     5274        return rcStrict;
     5275    }
     5276
     5277    /** @todo NSTVMX: rest of host state loading (loading MSRs). */
    51845278
    51855279    return VINF_SUCCESS;
     
    52225316    }
    52235317
    5224     int rc = iemVmxVmexitLoadHostState(pVCpu);
     5318    int rc = iemVmxVmexitLoadHostState(pVCpu, uExitReason);
    52255319    if (RT_FAILURE(rc))
    52265320        return rc;
  • trunk/src/VBox/VMM/include/CPUMInternal.mac

    r74303 r74421  
    253253    alignb 8
    254254    .Guest.hwvirt.svm.HCPhysVmcb             RTHCPHYS_RES 1
    255     .Guest.hwvirt.uInhibitRip                resq         1
    256255    .Guest.hwvirt.fLocalForcedActions        resd         1
    257256    .Guest.hwvirt.fGif                       resb         1
     
    541540    alignb 8
    542541    .Hyper.hwvirt.svm.HCPhysVmcb             RTHCPHYS_RES 1
    543     .Hyper.hwvirt.uInhibitRip                resq         1
    544542    .Hyper.hwvirt.fLocalForcedActions        resd         1
    545543    .Hyper.hwvirt.fGif                       resb         1
  • trunk/src/VBox/VMM/testcase/tstVMStruct.h

    r74303 r74421  
    149149    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.GCPhysVmcs);
    150150    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.enmDiag);
     151    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.enmAbort);
     152    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.uAbortAux);
    151153    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxRootMode);
    152154    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxNonRootMode);
     
    164166    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pAutoMsrAreaR0);
    165167    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pAutoMsrAreaR3);
    166     GEN_CHECK_OFF(CPUMCTX, hwvirt.uInhibitRip);
    167168    GEN_CHECK_OFF(CPUMCTX, hwvirt.fLocalForcedActions);
    168169    GEN_CHECK_OFF(CPUMCTX, hwvirt.fGif);
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