VirtualBox

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


Ignore:
Timestamp:
Sep 15, 2018 4:29:24 AM (6 years ago)
Author:
vboxsync
Message:

VMM/IEM, HM, CPUM: Nested VMX: bugref:9180 vmlaunch/vmresume bits.

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

Legend:

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

    r74258 r74287  
    769769}
    770770
     771
     772/**
     773 * Injects an event using TRPM given a VM-entry interruption info. and related
     774 * fields.
     775 *
     776 * @returns VBox status code.
     777 * @param   uEntryIntInfo       The VM-entry interruption info.
     778 * @param   uErrCode            The error code associated with the event if any.
     779 * @param   cbInstr             The VM-entry instruction length (for software
     780 *                              interrupts and software exceptions). Pass 0
     781 *                              otherwise.
     782 * @param   GCPtrFaultAddress   The guest CR2 if this is a \#PF event.
     783 */
     784VMM_INT_DECL(int) HMVmxEntryIntInfoInjectTrpmEvent(PVMCPU pVCpu, uint32_t uEntryIntInfo, uint32_t uErrCode, uint32_t cbInstr,
     785                                                   RTGCUINTPTR GCPtrFaultAddress)
     786{
     787    Assert(VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
     788
     789    uint8_t const uType         = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo);
     790    uint8_t const uVector       = VMX_ENTRY_INT_INFO_VECTOR(uEntryIntInfo);
     791    bool const    fErrCodeValid = VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(uEntryIntInfo);
     792
     793    TRPMEVENT enmTrapType;
     794    switch (uType)
     795    {
     796        case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
     797           enmTrapType = TRPM_HARDWARE_INT;
     798           break;
     799
     800        case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
     801            enmTrapType = TRPM_SOFTWARE_INT;
     802            break;
     803
     804        case VMX_ENTRY_INT_INFO_TYPE_NMI:
     805        case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:  /* ICEBP. */
     806        case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT:       /* #BP and #OF */
     807        case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
     808            enmTrapType = TRPM_TRAP;
     809            break;
     810
     811        default:
     812            /* Shouldn't really happen. */
     813            AssertMsgFailedReturn(("Invalid trap type %#x\n", uType), VERR_VMX_IPE_4);
     814            break;
     815    }
     816
     817    int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
     818    AssertRCReturn(rc, rc);
     819
     820    if (fErrCodeValid)
     821        TRPMSetErrorCode(pVCpu, uErrCode);
     822
     823    if (   uType   == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
     824        && uVector == X86_XCPT_PF)
     825        TRPMSetFaultAddress(pVCpu, GCPtrFaultAddress);
     826    else if (   uType == VMX_ENTRY_INT_INFO_TYPE_SW_INT
     827             || uType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT
     828             || uType == VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT)
     829    {
     830        AssertMsg(   uType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
     831                  || (uVector == X86_XCPT_BP || uVector == X86_XCPT_OF),
     832                  ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uType));
     833        TRPMSetInstrLength(pVCpu, cbInstr);
     834    }
     835
     836    return VINF_SUCCESS;
     837}
     838
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r74258 r74287  
    29662966                            || uVector == X86_XCPT_MC))
    29672967                    || (   uIntType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT
    2968                         && uVector == 0))
     2968                        && uVector  == VMX_ENTRY_INT_INFO_VECTOR_MTF))
    29692969                { /* likely */ }
    29702970                else
     
    34803480        uint8_t const uVector = RT_BF_GET(uIntInfo, VMX_BF_ENTRY_INT_INFO_VECTOR);
    34813481        uint8_t const uRsvd   = RT_BF_GET(uIntInfo, VMX_BF_ENTRY_INT_INFO_RSVD_12_30);
    3482         if (   uRsvd == 0
     3482        if (   !uRsvd
    34833483            && HMVmxIsEntryIntInfoTypeValid(IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVmxMonitorTrapFlag, uType)
    34843484            && HMVmxIsEntryIntInfoVectorValid(uVector, uType))
     
    37093709        /* TPR threshold and VTPR. */
    37103710        uint8_t const *pbVirtApic = (uint8_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage);
    3711         uint8_t const u8VTpr = *(pbVirtApic + XAPIC_OFF_TPR);
     3711        uint8_t const  u8VTpr    = *(pbVirtApic + XAPIC_OFF_TPR);
    37123712        if (   !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
    37133713            && !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY)
     
    39893989 * Loads the guest auto-load MSRs area as part of VM-entry.
    39903990 *
     3991 * @returns VBox status code.
    39913992 * @param   pVCpu       The cross context virtual CPU structure.
    39923993 * @param   pszInstr    The VMX instruction name (for logging purposes).
     
    40714072 * Loads the guest-state as part of VM-entry.
    40724073 *
     4074 * @returns VBox status code.
    40734075 * @param   pVCpu           The cross context virtual CPU structure.
    40744076 * @param   pszInstr        The VMX instruction name (for logging purposes).
     
    40794081IEM_STATIC int iemVmxVmentryLoadGuestState(PVMCPU pVCpu, const char *pszInstr)
    40804082{
     4083    /*
     4084     * Load control, debug, segment, descriptor-table registers and some MSRs.
     4085     */
    40814086    iemVmxVmentryLoadGuestControlRegsMsr(pVCpu);
    40824087    iemVmxVmentryLoadGuestSegRegs(pVCpu);
     
    41054110
    41064111/**
     4112 * Performs event injection (if any) as part of VM-entry.
     4113 *
     4114 * @param   pVCpu       The cross context virtual CPU structure.
     4115 * @param   pszInstr    The VMX instruction name (for logging purposes).
     4116 */
     4117IEM_STATIC int iemVmxVmentryInjectEvent(PVMCPU pVCpu, const char *pszInstr)
     4118{
     4119    /*
     4120     * Inject events.
     4121     * See Intel spec. 26.5 "Event Injection".
     4122     */
     4123    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     4124    uint32_t const uEntryIntInfo = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->u32EntryIntInfo;
     4125    if (VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo))
     4126    {
     4127        uint8_t const uType = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo);
     4128        if (uType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT)
     4129        {
     4130            Assert(VMX_ENTRY_INT_INFO_VECTOR(uEntryIntInfo) == VMX_ENTRY_INT_INFO_VECTOR_MTF);
     4131            VMCPU_FF_SET(pVCpu, VMCPU_FF_MTF);
     4132            return VINF_SUCCESS;
     4133        }
     4134
     4135        /** @todo NSTVMX: Is it safe to update IDT-vectoring information in the VMCS
     4136         *        here? */
     4137
     4138        pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = false;
     4139        int rc = HMVmxEntryIntInfoInjectTrpmEvent(pVCpu, uEntryIntInfo, pVmcs->u32EntryXcptErrCode, pVmcs->u32EntryInstrLen,
     4140                                                  pVCpu->cpum.GstCtx.cr2);
     4141        AssertRCReturn(rc, rc);
     4142    }
     4143
     4144    NOREF(pszInstr);
     4145    return VINF_SUCCESS;
     4146}
     4147
     4148
     4149/**
     4150 * Perform a VMX transition updated PGM, IEM and CPUM.
     4151 *
     4152 * @param   pVCpu       The cross context virtual CPU structure.
     4153 */
     4154IEM_STATIC int iemVmxWorldSwitch(PVMCPU pVCpu)
     4155{
     4156    /*
     4157     * Inform PGM about paging mode changes.
     4158     * We include X86_CR0_PE because PGM doesn't handle paged-real mode yet,
     4159     * see comment in iemMemPageTranslateAndCheckAccess().
     4160     */
     4161    int rc = PGMChangeMode(pVCpu, pVCpu->cpum.GstCtx.cr0 | X86_CR0_PE, pVCpu->cpum.GstCtx.cr4, pVCpu->cpum.GstCtx.msrEFER);
     4162# ifdef IN_RING3
     4163    Assert(rc != VINF_PGM_CHANGE_MODE);
     4164# endif
     4165    AssertRCReturn(rc, rc);
     4166
     4167    /* Inform CPUM (recompiler), can later be removed. */
     4168    CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_ALL);
     4169
     4170    /*
     4171     * Flush the TLB with new CR3. This is required in case the PGM mode change
     4172     * above doesn't actually change anything.
     4173     */
     4174    if (rc == VINF_SUCCESS)
     4175    {
     4176        rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true);
     4177        AssertRCReturn(rc, rc);
     4178    }
     4179
     4180    /* Re-initialize IEM cache/state after the drastic mode switch. */
     4181    iemReInitExec(pVCpu);
     4182    return rc;
     4183}
     4184
     4185
     4186/**
    41074187 * VMLAUNCH/VMRESUME instruction execution worker.
    41084188 *
     
    41634243    {
    41644244        /* VMLAUNCH with non-clear VMCS. */
    4165         if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState != VMX_V_VMCS_STATE_CLEAR)
     4245        if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState == VMX_V_VMCS_STATE_CLEAR)
     4246        { /* likely */ }
     4247        else
    41664248        {
    41674249            Log(("vmlaunch: VMLAUNCH with non-clear VMCS -> VMFail\n"));
     
    41754257    {
    41764258        /* VMRESUME with non-launched VMCS. */
    4177         if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState != VMX_V_VMCS_STATE_LAUNCHED)
     4259        if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState == VMX_V_VMCS_STATE_LAUNCHED)
     4260        { /* likely */ }
     4261        else
    41784262        {
    41794263            Log(("vmresume: VMRESUME with non-launched VMCS -> VMFail\n"));
     
    42284312                                Assert(rc != VINF_CPUM_R3_MSR_WRITE);
    42294313
     4314                                /* VMLAUNCH instruction must update the VMCS launch state. */
     4315                                if (uInstrId == VMXINSTRID_VMLAUNCH)
     4316                                    pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState = VMX_V_VMCS_STATE_LAUNCHED;
     4317
     4318                                /* Perform the VMX transition (PGM updates). */
     4319                                VBOXSTRICTRC rcStrict = iemVmxWorldSwitch(pVCpu);
     4320                                if (rcStrict == VINF_SUCCESS)
     4321                                { /* likely */ }
     4322                                else if (RT_SUCCESS(rcStrict))
     4323                                {
     4324                                    Log3(("%s: iemVmxWorldSwitch returns %Rrc -> Setting passup status\n", pszInstr,
     4325                                          VBOXSTRICTRC_VAL(rcStrict)));
     4326                                    rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
     4327                                }
     4328                                else
     4329                                {
     4330                                    Log3(("%s: iemVmxWorldSwitch failed! rc=%Rrc\n", pszInstr, VBOXSTRICTRC_VAL(rcStrict)));
     4331                                    return rcStrict;
     4332                                }
     4333
     4334                                /* Event injection. */
     4335                                iemVmxVmentryInjectEvent(pVCpu, pszInstr);
     4336
     4337                                /** @todo NSTVMX: Setup VMX preemption timer */
     4338                                /** @todo NSTVMX: TPR thresholding. */
     4339
    42304340                                iemVmxVmSucceed(pVCpu);
    42314341                                iemRegAddToRipAndClearRF(pVCpu, cbInstr);
  • trunk/src/VBox/VMM/testcase/tstVMStruct.h

    r74258 r74287  
    151151    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxRootMode);
    152152    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxNonRootMode);
     153    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInterceptEvents);
    153154    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pVmcsR0);
    154155    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pVmcsR3);
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