VirtualBox

Changeset 92685 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 2, 2021 5:59:39 AM (3 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref:10092 Started with constructing EPT-violation VM-exit for iemInitDecoderAndPrefetchOpcodes.

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

Legend:

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

    r92626 r92685  
    439439
    440440/**
     441 * Invokes the VMX VM-exit handler for EPT faults.
     442 */
     443# define IEM_VMX_VMEXIT_EPT_RET(a_pVCpu, a_pPtWalk, a_fAccess, a_fSlatFail, a_cbInstr) \
     444    do { return iemVmxVmexitEpt(a_pVCpu, a_pPtWalk, a_fAccess, a_fSlatFail, a_cbInstr); } while (0)
     445
     446/**
    441447 * Invokes the VMX VM-exit handler.
    442448 */
     
    454460# define IEM_VMX_VMEXIT_TASK_SWITCH_RET(a_pVCpu, a_enmTaskSwitch, a_SelNewTss, a_cbInstr)    do { return VERR_VMX_IPE_1; } while (0)
    455461# define IEM_VMX_VMEXIT_MWAIT_RET(a_pVCpu, a_fMonitorArmed, a_cbInstr)          do { return VERR_VMX_IPE_1; } while (0)
     462# define IEM_VMX_VMEXIT_EPT_RET(a_pVCpu, a_pPtWalk, a_fAccess, a_fSlatFail, a_cbInstr)       do { return VERR_VMX_IPE_1; } while (0)
    456463# define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu, a_uExitReason, a_uExitQual)   do { return VERR_VMX_IPE_1; } while (0)
    457464
     
    980987IEM_STATIC VBOXSTRICTRC     iemVmxVirtApicAccessMsrRead(PVMCPUCC pVCpu, uint32_t idMsr, uint64_t *pu64Value);
    981988IEM_STATIC VBOXSTRICTRC     iemVmxVirtApicAccessMsrWrite(PVMCPUCC pVCpu, uint32_t idMsr, uint64_t u64Value);
     989IEM_STATIC VBOXSTRICTRC     iemVmxVmexitEpt(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint32_t fAccess, uint32_t fSlatFail, uint8_t cbInstr);
    982990#endif
    983991
     
    14331441    {
    14341442        Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - rc=%Rrc\n", GCPtrPC, rc));
     1443#ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
     1444        if (Walk.fFailed & PGM_WALKFAIL_EPT)
     1445        {
     1446            Assert(IEM_VMX_IS_NON_ROOT_MODE(pVCpu));
     1447            IEM_VMX_VMEXIT_EPT_RET(pVCpu, &Walk, IEM_ACCESS_INSTRUCTION, IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR, 0 /* cbInstr */);
     1448        }
     1449#endif
    14351450        return iemRaisePageFault(pVCpu, GCPtrPC, IEM_ACCESS_INSTRUCTION, rc);
    14361451    }
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r92626 r92685  
    36853685
    36863686
    3687 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
    36883687/**
    36893688 * VMX VM-exit handler for EPT violation.
    36903689 *
    3691  * @param   pVCpu       The cross context virtual CPU structure.
    3692  * @param   fAccess     The access causing the EPT violation, IEM_ACCESS_XXX.
    3693  * @param   fEptAccess  The EPT paging structure bits.
    3694  * @param   GCPhysAddr  The physical address causing the EPT violation.
    3695  * @param   GCPtrAddr   The linear address causing the EPT violation.
    3696  * @param   cbInstr     The VM-exit instruction length.
    3697  */
    3698 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptViolation(PVMCPUCC pVCpu, uint32_t fAccess, uint64_t fEptAccess, RTGCPHYS GCPhysAddr,
    3699                                                  uint64_t GCPtrAddr, bool fLinearAddrValid, uint8_t cbInstr)
     3690 * @param   pVCpu               The cross context virtual CPU structure.
     3691 * @param   fAccess             The access causing the EPT violation, IEM_ACCESS_XXX.
     3692 * @param   fSlatFail           The SLAT failure info, IEM_SLAT_FAIL_XXX.
     3693 * @param   fEptAccess          The EPT paging structure bits.
     3694 * @param   GCPhysAddr          The physical address causing the EPT violation.
     3695 * @param   fIsLinearAddrValid  Whether translation of a linear address caused this
     3696 *                              EPT violation. If @c false, GCPtrAddr must be 0.
     3697 * @param   GCPtrAddr           The linear address causing the EPT violation.
     3698 * @param   cbInstr             The VM-exit instruction length.
     3699 */
     3700IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptViolation(PVMCPUCC pVCpu, uint32_t fAccess, uint32_t fSlatFail, uint64_t fEptAccess,
     3701                                                 RTGCPHYS GCPhysAddr, bool fLinearAddrValid, uint64_t GCPtrAddr, uint8_t cbInstr)
    37003702{
    37013703    /*
     
    37093711    uint8_t const fSupportsAccessDirty = fCaps & MSR_IA32_VMX_EPT_VPID_CAP_ACCESS_DIRTY;
    37103712
    3711     uint8_t const fDataRead    = ((fAccess & IEM_ACCESS_DATA_R)  == IEM_ACCESS_DATA_R)  | fSupportsAccessDirty;
    3712     uint8_t const fDataWrite   = ((fAccess & IEM_ACCESS_DATA_RW) == IEM_ACCESS_DATA_RW) | fSupportsAccessDirty;
    3713     uint8_t const fInstrFetch  = (fAccess & IEM_ACCESS_INSTRUCTION) == IEM_ACCESS_INSTRUCTION;
    3714     bool const fEptRead        = RT_BOOL(fEptAccess & EPT_E_READ);
    3715     bool const fEptWrite       = RT_BOOL(fEptAccess & EPT_E_WRITE);
    3716     bool const fEptExec        = RT_BOOL(fEptAccess & EPT_E_EXECUTE);
    3717     bool const fNmiUnblocking  = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
    3718 
    3719     uint64_t const u64ExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_READ,        fDataRead)
    3720                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_WRITE,       fDataWrite)
    3721                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH, fInstrFetch)
    3722                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_READ,         fEptRead)
    3723                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_WRITE,        fEptWrite)
    3724                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE,      fEptExec)
    3725                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID,  fLinearAddrValid)
    3726                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET,   fNmiUnblocking);
    3727 
    3728     /** @todo bit 8 of Exit Qualification!
    3729      *  If the access causing the EPT violation is to a guest-physical address that is
    3730      *  the translation of a linear address.
    3731      *   - OR -
    3732      *  if the access causing the EPT violation is to a paging-structure entry as part
    3733      *  of a page walk or the update of an accessed or dirty bit.
    3734      *
    3735      *  Caller needs to be able to distinguish this... */
     3713    uint8_t const fDataRead      = ((fAccess & IEM_ACCESS_DATA_R)  == IEM_ACCESS_DATA_R)  | fSupportsAccessDirty;
     3714    uint8_t const fDataWrite     = ((fAccess & IEM_ACCESS_DATA_RW) == IEM_ACCESS_DATA_RW) | fSupportsAccessDirty;
     3715    uint8_t const fInstrFetch    = (fAccess & IEM_ACCESS_INSTRUCTION) == IEM_ACCESS_INSTRUCTION;
     3716    bool const fEptRead          = RT_BOOL(fEptAccess & EPT_E_READ);
     3717    bool const fEptWrite         = RT_BOOL(fEptAccess & EPT_E_WRITE);
     3718    bool const fEptExec          = RT_BOOL(fEptAccess & EPT_E_EXECUTE);
     3719    bool const fNmiUnblocking    = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
     3720    bool const fLinearToPhysAddr = fLinearAddrValid & RT_BOOL(fSlatFail & IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR);
     3721
     3722    uint64_t const u64ExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_READ,         fDataRead)
     3723                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_WRITE,        fDataWrite)
     3724                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH,  fInstrFetch)
     3725                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_READ,          fEptRead)
     3726                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_WRITE,         fEptWrite)
     3727                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE,       fEptExec)
     3728                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID,   fLinearAddrValid)
     3729                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_TO_PHYS_ADDR, fLinearToPhysAddr)
     3730                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET,    fNmiUnblocking);
    37363731
    37373732#ifdef VBOX_STRICT
     
    37413736    Assert(!(fCaps & MSR_IA32_VMX_EPT_VPID_CAP_SUPER_SHW_STACK));             /* Supervisor shadow stack control not supported. */
    37423737    Assert(!(RT_BF_GET(fMiscCaps, VMX_BF_MISC_INTEL_PT)));                    /* Intel PT not supported. */
    3743     Assert(!(RT_BF_GET(fMiscCaps, VMX_BF_MISC_INTEL_PT)));                    /* Intel PT not supported. */
    37443738    Assert(!(fProcCtls2 & VMX_PROC_CTLS2_MODE_BASED_EPT_PERM));               /* Mode-based execute control not supported. */
    37453739#endif
     
    37513745    return iemVmxVmexit(pVCpu, VMX_EXIT_EPT_VIOLATION, u64ExitQual);
    37523746}
    3753 #endif
     3747
     3748
     3749/**
     3750 * VMX VM-exit handler for EPT-induced VM-exits.
     3751 *
     3752 * @param   pVCpu       The cross context virtual CPU structure.
     3753 * @param   pWalk       The page walk info.
     3754 * @param   fAccess     The access causing the EPT event, IEM_ACCESS_XXX.
     3755 * @param   fSlatFail   Additional SLAT info, IEM_SLAT_FAIL_XXX.
     3756 * @param   cbInstr     The VM-exit instruction length if applicable. Pass 0 if not
     3757 *                      applicable.
     3758 */
     3759IEM_STATIC VBOXSTRICTRC iemVmxVmexitEpt(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint32_t fAccess, uint32_t fSlatFail,
     3760                                        uint8_t cbInstr)
     3761{
     3762    Assert(pWalk->fIsSlat);
     3763    Assert(pWalk->fFailed & PGM_WALKFAIL_EPT);
     3764    Assert(!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVmxEptXcptVe);          /* #VE exceptions not supported. */
     3765    Assert(!(pWalk->fFailed & PGM_WALKFAIL_EPT_VIOLATION_CONVERTIBLE)); /* Without #VE, convertible violations not possible. */
     3766
     3767    if (pWalk->fFailed & PGM_WALKFAIL_EPT_VIOLATION)
     3768    {
     3769        uint64_t const fEptAccess = (pWalk->fEffective & PGM_PTATTRS_EPT_MASK) >> PGM_PTATTRS_EPT_SHIFT;
     3770        return iemVmxVmexitEptViolation(pVCpu, fAccess, fSlatFail, fEptAccess, pWalk->GCPhysNested, pWalk->fIsLinearAddrValid,
     3771                                        pWalk->GCPtr, cbInstr);
     3772    }
     3773    else
     3774    {
     3775        Assert(pWalk->fFailed & PGM_WALKFAIL_EPT_MISCONFIG);
     3776        /** @todo Do EPT misconfig. */
     3777        return VERR_NOT_IMPLEMENTED;
     3778    }
     3779}
    37543780
    37553781
  • trunk/src/VBox/VMM/VMMAll/PGMAllGstSlatEpt.cpp.h

    r92541 r92685  
    4747DECLINLINE(int) PGM_GST_SLAT_NAME_EPT(WalkReturnNotPresent)(PCVMCPUCC pVCpu, PPGMPTWALK pWalk, uint64_t uEntry, uint8_t uLevel)
    4848{
    49     static PGMSLATFAIL const s_aEptViolation[] = { PGMSLATFAIL_EPT_VIOLATION, PGMSLATFAIL_EPT_VIOLATION_CONVERTIBLE };
     49    static PGMWALKFAIL const s_afEptViolations[] = { PGM_WALKFAIL_EPT_VIOLATION, PGM_WALKFAIL_EPT_VIOLATION_CONVERTIBLE };
    5050    uint8_t const fEptVeSupported  = pVCpu->CTX_SUFF(pVM)->cpum.ro.GuestFeatures.fVmxEptXcptVe;
    5151    uint8_t const idxViolationType = fEptVeSupported & !RT_BF_GET(uEntry, VMX_BF_EPT_PT_SUPPRESS_VE);
     
    5353    pWalk->fNotPresent = true;
    5454    pWalk->uLevel      = uLevel;
    55     pWalk->enmSlatFail = s_aEptViolation[idxViolationType];
     55    pWalk->fFailed    |= s_afEptViolations[idxViolationType];
    5656    return VERR_PAGE_TABLE_NOT_PRESENT;
    5757}
     
    6363    pWalk->fBadPhysAddr = true;
    6464    pWalk->uLevel       = uLevel;
    65     pWalk->enmSlatFail  = PGMSLATFAIL_EPT_VIOLATION;
     65    pWalk->fFailed     |= PGM_WALKFAIL_EPT_VIOLATION;
    6666    return VERR_PAGE_TABLE_NOT_PRESENT;
    6767}
    6868
    6969
    70 DECLINLINE(int) PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint8_t uLevel)
    71 {
    72     NOREF(pVCpu);
     70DECLINLINE(int) PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint64_t uEntry, uint8_t uLevel)
     71{
     72    static PGMWALKFAIL const s_afEptViolations[] = { PGM_WALKFAIL_EPT_VIOLATION, PGM_WALKFAIL_EPT_VIOLATION_CONVERTIBLE };
     73    uint8_t const fEptVeSupported  = pVCpu->CTX_SUFF(pVM)->cpum.ro.GuestFeatures.fVmxEptXcptVe;
     74    uint8_t const fConvertible     = RT_BOOL(uLevel == 1 || (uEntry & EPT_E_BIT_LEAF));
     75    uint8_t const idxViolationType = fEptVeSupported & fConvertible & !RT_BF_GET(uEntry, VMX_BF_EPT_PT_SUPPRESS_VE);
     76
    7377    pWalk->fRsvdError  = true;
    7478    pWalk->uLevel      = uLevel;
    75     pWalk->enmSlatFail = PGMSLATFAIL_EPT_MISCONFIG;
     79    pWalk->fFailed    |= s_afEptViolations[idxViolationType];
    7680    return VERR_PAGE_TABLE_NOT_PRESENT;
    7781}
    7882
    7983
     84/**
     85 * Performs an EPT walk (second-level address translation).
     86 *
     87 * @returns VBox status code.
     88 * @retval  VINF_SUCCESS on success.
     89 * @retval  VERR_PAGE_TABLE_NOT_PRESENT on failure. Check pWalk for details.
     90 *
     91 * @param   pVCpu               The cross context virtual CPU structure of the calling EMT.
     92 * @param   GCPhysNested        The nested-guest physical address to walk.
     93 * @param   fIsLinearAddrValid  Whether the linear-address in @c GCPtrNested caused
     94 *                              this page walk. If this is false, @c GCPtrNested
     95 *                              must be 0.
     96 * @param   GCPtrNested         The nested-guest linear address that caused this
     97 *                              page walk.
     98 * @param   pWalk               The page walk info.
     99 * @param   pGstWalk            The guest mode specific page walk info.
     100 */
    80101DECLINLINE(int) PGM_GST_SLAT_NAME_EPT(Walk)(PVMCPUCC pVCpu, RTGCPHYS GCPhysNested, bool fIsLinearAddrValid, RTGCPTR GCPtrNested,
    81102                                            PPGMPTWALK pWalk, PGSTPTWALK pGstWalk)
    82103{
     104    Assert(fIsLinearAddrValid || GCPtrNested == 0);
     105
    83106    /*
    84107     * Init walk structures.
     
    143166
    144167        if (RT_LIKELY(GST_IS_PML4E_VALID(pVCpu, Pml4e))) { /* likely */ }
    145         else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, 4);
     168        else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, Pml4e.u, 4);
    146169
    147170        Assert(!pVCpu->CTX_SUFF(pVM)->cpum.ro.GuestFeatures.fVmxModeBasedExecuteEpt);
     
    212235            return VINF_SUCCESS;
    213236        }
    214         else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, 3);
     237        else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, Pdpte.u, 3);
    215238
    216239        int const rc = PGM_GCPHYS_2_PTR_BY_VMCPU(pVCpu, Pdpte.u & EPT_PDPTE_PG_MASK, &pGstWalk->pPd);
     
    270293            return VINF_SUCCESS;
    271294        }
    272         else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, 2);
     295        else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, Pde.u, 2);
    273296
    274297        int const rc = PGM_GCPHYS_2_PTR_BY_VMCPU(pVCpu, GST_GET_PDE_GCPHYS(Pde), &pGstWalk->pPt);
     
    292315        { /* likely*/  }
    293316        else
    294             return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, 1);
     317            return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, Pte.u, 1);
    295318
    296319        uint64_t const fEptAttrs     = Pte.u & EPT_PTE_ATTR_MASK;
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r91263 r92685  
    921921} IEMACCESSCRX;
    922922
    923 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     923#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     924/** @name IEM_SLAT_FAIL_XXX - Second-level address translation failure information.
     925 *
     926 * These flags provide further context to SLAT page-walk failures that could not be
     927 * determined by PGM (e.g, PGM is not privy to memory access permissions).
     928 *
     929 * @{
     930 */
     931/** Translating a nested-guest linear address failed accessing a nested-guest
     932 *  physical address. */
     933# define IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR          RT_BIT_32(0)
     934/** Translating a nested-guest linear address failed accessing a
     935 *  paging-structure entry. */
     936# define IEM_SLAT_FAIL_LINEAR_TO_PAGE_TABLE         RT_BIT_32(1)
     937/** @} */
     938
    924939PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iemVmxApicAccessPageHandler;
    925 # endif
     940#endif
    926941
    927942/**
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