VirtualBox

Changeset 75493 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Nov 15, 2018 5:06:55 PM (6 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref: 9180 Use PGM physical page handler for the APIC-access page.

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

Legend:

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

    r75387 r75493  
    12781278        && CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.s.Guest, VMX_PROC_CTLS2_VIRT_X2APIC_MODE))
    12791279    {
    1280         /** @todo NSTVMX: perhaps IEMExecVmxVirtApicAccessMsr should be moved to
    1281          *        HMVMXAll.cpp? */
    12821280        VBOXSTRICTRC rcStrict = IEMExecVmxVirtApicAccessMsr(pVCpu, idMsr, puValue, false /* fWrite */);
    1283         Assert(rcStrict == VINF_SUCCESS || rcStrict == VERR_OUT_OF_RANGE || rcStrict == VINF_VMX_INTERCEPT_NOT_ACTIVE);
    1284         if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
    1285         {
    1286             if (rcStrict == VERR_OUT_OF_RANGE)
    1287                 return VERR_CPUM_RAISE_GP_0;
    1288             Assert(rcStrict == VINF_SUCCESS);
     1281        if (rcStrict == VINF_VMX_MODIFIES_BEHAVIOR)
    12891282            return VINF_SUCCESS;
    1290         }
     1283        if (rcStrict == VERR_OUT_OF_RANGE)
     1284            return VERR_CPUM_RAISE_GP_0;
     1285        Assert(rcStrict == VINF_VMX_INTERCEPT_NOT_ACTIVE);
    12911286    }
    12921287#endif
     
    13031298        && CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.s.Guest, VMX_PROC_CTLS2_VIRT_X2APIC_MODE))
    13041299    {
    1305         /** @todo NSTVMX: perhaps IEMExecVmxVirtApicAccessMsr should be moved to
    1306          *        HMVMXAll.cpp? */
    13071300        VBOXSTRICTRC rcStrict = IEMExecVmxVirtApicAccessMsr(pVCpu, idMsr, &uValue, true /* fWrite */);
    1308         Assert(rcStrict == VINF_SUCCESS || rcStrict == VERR_OUT_OF_RANGE || rcStrict == VINF_VMX_INTERCEPT_NOT_ACTIVE);
    1309         if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
    1310         {
    1311             if (rcStrict == VERR_OUT_OF_RANGE)
    1312                 return VERR_CPUM_RAISE_GP_0;
    1313             Assert(rcStrict == VINF_SUCCESS);
     1301        if (rcStrict == VINF_VMX_MODIFIES_BEHAVIOR)
    13141302            return VINF_SUCCESS;
    1315         }
     1303        if (rcStrict == VERR_OUT_OF_RANGE)
     1304            return VERR_CPUM_RAISE_GP_0;
     1305        Assert(rcStrict == VINF_VMX_INTERCEPT_NOT_ACTIVE);
    13161306    }
    13171307#endif
  • trunk/src/VBox/VMM/VMMAll/CPUMAllVmx.cpp

    r75440 r75493  
    2121*********************************************************************************************************************************/
    2222#define LOG_GROUP LOG_GROUP_CPUM
     23#include <VBox/log.h>
    2324#include <VBox/vmm/cpum.h>
    24 #include <VBox/log.h>
     25#include "CPUMInternal.h"
     26#include <VBox/vmm/iem.h>
     27#include <VBox/vmm/pgm.h>
     28#include <VBox/vmm/vm.h>
    2529
    2630
     
    134138}
    135139
     140#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     141/**
     142 * @callback_method_impl{FNPGMPHYSHANDLER, VMX APIC-access page accesses}
     143 *
     144 * @remarks The @a pvUser argument is currently unused.
     145 */
     146PGM_ALL_CB2_DECL(VBOXSTRICTRC) cpumVmxApicAccessPageHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysFault, void *pvPhys,
     147                                                            void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType,
     148                                                            PGMACCESSORIGIN enmOrigin, void *pvUser)
     149{
     150    RT_NOREF4(pVM, pvPhys, enmOrigin, pvUser);
     151
     152    uint16_t const offAccess = (GCPhysFault & PAGE_OFFSET_MASK);
     153    bool const fWrite = RT_BOOL(enmAccessType == PGMACCESSTYPE_WRITE);
     154    VBOXSTRICTRC rcStrict = IEMExecVmxVirtApicAccessMem(pVCpu, offAccess, cbBuf, pvBuf, fWrite);
     155    if (rcStrict == VINF_VMX_MODIFIES_BEHAVIOR)
     156        rcStrict = VINF_SUCCESS;
     157    return rcStrict;
     158}
     159#endif
     160
     161
     162/**
     163 * Registers the PGM physical page handelr for teh VMX APIC-access page.
     164 *
     165 * @returns VBox status code.
     166 * @param   pVCpu               The cross context virtual CPU structure.
     167 * @param   GCPhysApicAccess    The guest-physical address of the APIC-access page.
     168 */
     169VMM_INT_DECL(VBOXSTRICTRC) CPUMVmxApicAccessPageRegister(PVMCPU pVCpu, RTGCPHYS GCPhysApicAccess)
     170{
     171    PVM pVM = pVCpu->CTX_SUFF(pVM);
     172    int rc = PGMHandlerPhysicalRegister(pVM, GCPhysApicAccess, GCPhysApicAccess, pVM->cpum.s.hVmxApicAccessPage,
     173                                        NIL_RTR3PTR /* pvUserR3 */, NIL_RTR0PTR /* pvUserR0 */,  NIL_RTRCPTR /* pvUserRC */,
     174                                        NULL /* pszDesc */);
     175    return rc;
     176}
     177
     178
     179/**
     180 * Registers the PGM physical page handelr for teh VMX APIC-access page.
     181 *
     182 * @returns VBox status code.
     183 * @param   pVCpu               The cross context virtual CPU structure.
     184 * @param   GCPhysApicAccess    The guest-physical address of the APIC-access page.
     185 */
     186VMM_INT_DECL(VBOXSTRICTRC) CPUMVmxApicAccessPageDeregister(PVMCPU pVCpu, RTGCPHYS GCPhysApicAccess)
     187{
     188    /** @todo NSTVMX: If there's anything else to do while APIC-access page is
     189     *        de-registered, do it here. */
     190    PVM pVM = pVCpu->CTX_SUFF(pVM);
     191    if (PGMHandlerPhysicalIsRegistered(pVM, GCPhysApicAccess))
     192        return PGMHandlerPhysicalDeregister(pVM, GCPhysApicAccess);
     193    return VINF_SUCCESS;
     194}
     195
  • trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp

    r75440 r75493  
    132132    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_AddrApicAccess           , "AddrApicAccess"            ),
    133133    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_AddrApicAccessEqVirtApic , "AddrApicAccessEqVirtApic"  ),
     134    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_AddrApicAccessHandlerReg , "AddrApicAccessHandlerReg"  ),
    134135    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_AddrEntryMsrLoad         , "AddrEntryMsrLoad"          ),
    135136    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_AddrExitMsrLoad          , "AddrExitMsrLoad"           ),
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r75387 r75493  
    89108910    iemMemUpdateWrittenCounter(pVCpu, fAccess, cbMem);
    89118911    *ppvMem = pvMem;
    8912 
    8913 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    8914     /*
    8915      * Check if this is an APIC-access and whether it needs to be virtualized.
    8916      */
    8917     if (   CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu))
    8918         && IEM_VMX_IS_PROCCTLS2_SET(pVCpu, VMX_PROC_CTLS2_VIRT_APIC_ACCESS))
    8919     {
    8920         RTGCPHYS const GCPhysMemAccessBase  = GCPhysFirst & ~(RTGCPHYS)PAGE_OFFSET_MASK;
    8921         RTGCPHYS const GCPhysApicAccessBase = CPUMGetGuestVmxApicAccessPageAddr(pVCpu, IEM_GET_CTX(pVCpu))
    8922                                             & ~(RTGCPHYS)PAGE_OFFSET_MASK;
    8923         if (GCPhysMemAccessBase == GCPhysApicAccessBase)
    8924         {
    8925             Assert(pvMem);
    8926             uint16_t const offAccess = GCPhysFirst & (RTGCPHYS)PAGE_OFFSET_MASK;
    8927             return iemVmxVirtApicAccessMem(pVCpu, offAccess, cbMem, pvMem, fAccess);
    8928         }
    8929     }
    8930 #endif
    89318912
    89328913    return VINF_SUCCESS;
     
    1395113932            int32_t const rcPassUp = pVCpu->iem.s.rcPassUp;
    1395213933#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    13953             if (   (   rcStrict == VINF_VMX_VMEXIT
    13954                     || rcStrict == VINF_VMX_MODIFIES_BEHAVIOR)
     13934            if (   rcStrict == VINF_VMX_VMEXIT
    1395513935                && rcPassUp == VINF_SUCCESS)
    1395613936                rcStrict = VINF_SUCCESS;
     
    1570115681 *
    1570215682 * @returns Strict VBox status code.
    15703  * @retval  VINF_SUCCESS if the MSR access was virtualized.
     15683 * @retval  VINF_VMX_MODIFIES_BEHAVIOR if the MSR access was virtualized.
    1570415684 * @retval  VINF_VMX_INTERCEPT_NOT_ACTIVE if the MSR access must be handled by
    1570515685 *          the x2APIC device.
    1570615686 * @retval  VERR_OUT_RANGE if the caller must raise \#GP(0).
     15687 *
    1570715688 * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
    1570815689 * @param   idMsr       The MSR being read.
     
    1571415695VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVirtApicAccessMsr(PVMCPU pVCpu, uint32_t idMsr, uint64_t *pu64Value, bool fWrite)
    1571515696{
    15716     IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_VMX_VMEXIT_MASK);
     15697    IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
    1571715698    Assert(pu64Value);
    1571815699
     
    1572615707    return iemExecStatusCodeFiddling(pVCpu, rcStrict);
    1572715708
     15709}
     15710
     15711
     15712/**
     15713 * Interface for HM and EM to virtualize memory-mapped APIC accesses.
     15714 *
     15715 * @returns Strict VBox status code.
     15716 * @retval  VINF_VMX_MODIFIES_BEHAVIOR if the memory access was virtualized.
     15717 *
     15718 * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
     15719 * @param   offAccess   The offset of the register being accessed (within the
     15720 *                      APIC-access page).
     15721 * @param   cbAccess    The size of the access in bytes.
     15722 * @param   pvData      Pointer to the data being written or where to store the data
     15723 *                      being read.
     15724 * @param   fWrite      Whether this is a write or read access.
     15725 * @thread  EMT(pVCpu)
     15726 */
     15727VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVirtApicAccessMem(PVMCPU pVCpu, uint16_t offAccess, size_t cbAccess, void *pvData,
     15728                                                       bool fWrite)
     15729{
     15730    IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_VMX_VMEXIT_MASK);
     15731    Assert(pvData);
     15732
     15733    /** @todo NSTVMX: Unfortunately, the caller has no idea about instruction fetch
     15734     *        accesses, so we only use read/write here. Maybe in the future the PGM
     15735     *        physical handler will be extended to include this information? */
     15736    uint32_t const fAccess = fWrite ? IEM_ACCESS_TYPE_WRITE : IEM_ACCESS_TYPE_READ;
     15737    VBOXSTRICTRC rcStrict = iemVmxVirtApicAccessMem(pVCpu, offAccess, cbAccess, pvData, fAccess);
     15738    if (pVCpu->iem.s.cActiveMappings)
     15739        iemMemRollback(pVCpu);
     15740    return iemExecStatusCodeFiddling(pVCpu, rcStrict);
    1572815741}
    1572915742
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r75440 r75493  
    26812681    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    26822682    bool const fHostInLongMode = RT_BOOL(pVmcs->u32ExitCtls & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE);
     2683    bool const fVirtApicAccess = RT_BOOL(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
    26832684
    26842685    /* We cannot return from a long-mode guest to a host that is not in long mode. */
     
    27062707    /* Clear address range monitoring. */
    27072708    EMMonitorWaitClear(pVCpu);
     2709
     2710    /* De-register the handler for the APIC-access page. */
     2711    if (fVirtApicAccess)
     2712    {
     2713        RTGCPHYS const GCPhysApicAccess = pVmcs->u64AddrApicAccess.u;
     2714        int rc = CPUMVmxApicAccessPageDeregister(pVCpu, GCPhysApicAccess);
     2715        if (RT_FAILURE(rc))
     2716            return rc;
     2717    }
    27082718
    27092719    /* Perform the VMX transition (PGM updates). */
     
    42364246 *
    42374247 * @returns VBox strict status code.
     4248 * @retval VINF_VMX_MODIFIES_BEHAVIOR if the access was virtualized.
     4249 * @retval VINF_VMX_VMEXIT if the access causes a VM-exit.
     4250 *
    42384251 * @param   pVCpu       The cross context virtual CPU structure.
    42394252 * @param   offAccess   The offset of the register being accessed (within the
    42404253 *                      APIC-access page).
    42414254 * @param   cbAccess    The size of the access in bytes.
    4242  * @param   pvData      Pointer to the data being read or written.
     4255 * @param   pvData      Pointer to the data being written or where to store the data
     4256 *                      being read.
    42434257 * @param   fAccess     The type of access (must contain IEM_ACCESS_TYPE_READ or
    42444258 *                      IEM_ACCESS_TYPE_WRITE or IEM_ACCESS_INSTRUCTION).
     
    60066020                IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_AddrApicAccessEqVirtApic);
    60076021        }
     6022
     6023        /* Register the handler for the APIC-access page. */
     6024        int rc = CPUMVmxApicAccessPageRegister(pVCpu, GCPhysApicAccess);
     6025        if (RT_FAILURE(rc))
     6026            IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_AddrApicAccessHandlerReg);
    60086027    }
    60096028
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