diff options
author | vboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f> | 2023-05-08 10:19:01 +0000 |
---|---|---|
committer | vboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f> | 2023-05-08 10:19:01 +0000 |
commit | c207032d166390918e335901f0fd5715b35d646a (patch) | |
tree | d4861a35efc92de275e6b1a4e2a98bf51891f494 /src | |
parent | 57e1207920e13e63064088d9c8eb55285da0f5c2 (diff) | |
download | VirtualBox-svn-c207032d166390918e335901f0fd5715b35d646a.tar.gz |
VMM: Nested VMX: bugref:10318 Moved vmxHCGetGuestIntrStateAndUpdateFFs outside of vmxHCEvaluatePendingEvent[Nested] as it isn't used internally. Fix callers accordingly.
Fixed superfluous call to CPUMIsInInterruptShadowWithUpdate (called unconditionally), replaced subsequent calls with CPUMIsInInterruptShadow.
Import RFLAGS explicitly when an interrupt is pending in the nested-guest case.
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@99663 cfe28804-0f27-0410-a406-dd0f0b0b656f
Diffstat (limited to 'src')
-rw-r--r-- | src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h | 98 | ||||
-rw-r--r-- | src/VBox/VMM/VMMR0/HMVMXR0.cpp | 11 | ||||
-rw-r--r-- | src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp | 4 |
3 files changed, 49 insertions, 64 deletions
diff --git a/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h b/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h index 9c04b5c0697..3f616d0b941 100644 --- a/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h +++ b/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h @@ -1696,14 +1696,15 @@ static void vmxHCExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient /** - * Gets the guest interruptibility-state and updates related force-flags. + * Gets the guest interruptibility-state and updates related internal eflags + * inhibition state. * * @returns Guest's interruptibility-state. - * @param pVCpu The cross context virtual CPU structure. + * @param pVCpu The cross context virtual CPU structure. * * @remarks No-long-jump zone!!! */ -static uint32_t vmxHCGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu) +static uint32_t vmxHCGetGuestIntrStateWithUpdate(PVMCPUCC pVCpu) { uint32_t fIntrState; @@ -4857,27 +4858,19 @@ static VBOXSTRICTRC vmxHCInjectEventVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, * NOT restore these force-flags. * * @returns Strict VBox status code (i.e. informational status codes too). - * @param pVCpu The cross context virtual CPU structure. - * @param pVmcsInfo The VMCS information structure. - * @param pfIntrState Where to store the VT-x guest-interruptibility state. + * @param pVCpu The cross context virtual CPU structure. + * @param pVmcsInfo The VMCS information structure. */ -static VBOXSTRICTRC vmxHCEvaluatePendingEvent(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t *pfIntrState) +static VBOXSTRICTRC vmxHCEvaluatePendingEvent(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo) { - Assert(pfIntrState); Assert(!TRPMHasTrap(pVCpu)); /* - * Compute/update guest-interruptibility state related FFs. - * The FFs will be used below while evaluating events to be injected. - */ - *pfIntrState = vmxHCGetGuestIntrStateAndUpdateFFs(pVCpu); - - /* * Evaluate if a new event needs to be injected. * An event that's already pending has already performed all necessary checks. */ if ( !VCPU_2_VMXSTATE(pVCpu).Event.fPending - && !CPUMIsInInterruptShadowWithUpdate(&pVCpu->cpum.GstCtx)) + && !CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx)) { /** @todo SMI. SMIs take priority over NMIs. */ @@ -4990,28 +4983,19 @@ static VBOXSTRICTRC vmxHCEvaluatePendingEvent(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcs * NOT restore these force-flags. * * @returns Strict VBox status code (i.e. informational status codes too). - * @param pVCpu The cross context virtual CPU structure. - * @param pVmcsInfo The VMCS information structure. - * @param pfIntrState Where to store the VT-x guest-interruptibility state. + * @param pVCpu The cross context virtual CPU structure. + * @param pVmcsInfo The VMCS information structure. * * @remarks The guest must be in VMX non-root mode. */ -static VBOXSTRICTRC vmxHCEvaluatePendingEventNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t *pfIntrState) +static VBOXSTRICTRC vmxHCEvaluatePendingEventNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo) { - NOREF(pVmcsInfo); PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx; - Assert(pfIntrState); Assert(CPUMIsGuestInVmxNonRootMode(pCtx)); Assert(!TRPMHasTrap(pVCpu)); /* - * Compute/update guest-interruptibility state related FFs. - * The FFs will be used below while evaluating events to be injected. - */ - *pfIntrState = vmxHCGetGuestIntrStateAndUpdateFFs(pVCpu); - - /* * If we are injecting an event, we must not setup any interrupt/NMI-window * exiting or we would get into an infinite VM-exit loop. An event that's * already pending has already performed all necessary checks. @@ -5037,7 +5021,7 @@ static VBOXSTRICTRC vmxHCEvaluatePendingEventNested(PVMCPUCC pVCpu, PVMXVMCSINFO * See Intel spec. 24.4.2 "Guest Non-Register State". * See Intel spec. 25.4.1 "Event Blocking". */ - if (!CPUMIsInInterruptShadowWithUpdate(&pVCpu->cpum.GstCtx)) + if (!CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx)) { /* likely */ } else return VINF_SUCCESS; @@ -5107,48 +5091,50 @@ static VBOXSTRICTRC vmxHCEvaluatePendingEventNested(PVMCPUCC pVCpu, PVMXVMCSINFO * This fixes a nasty SMP hang while executing nested-guest VCPUs on spinlocks which aren't rescued * by other VM-exits (like a preemption timer), see @bugref{9562#c18}. * - * See Intel spec. 25.4.1 "Event Blocking". - * * NMIs block external interrupts as they are dispatched through the interrupt gate (vector 2) * which automatically clears EFLAGS.IF. Also it's possible an NMI handler could enable interrupts * and thus we should not check for NMI inhibition here. * + * See Intel spec. 25.4.1 "Event Blocking". * See Intel spec. 6.8.1 "Masking Maskable Hardware Interrupts". */ if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC) - && !VCPU_2_VMXSTATE(pVCpu).fSingleInstruction - && CPUMIsGuestVmxPhysIntrEnabled(pCtx)) + && !VCPU_2_VMXSTATE(pVCpu).fSingleInstruction) { Assert(!DBGFIsStepping(pVCpu)); - - /* Nested-guest external interrupt VM-exit. */ - if ( CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT) - && !CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT)) - { - VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */); - Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE); - return rcStrict; - } - - /* - * Fetch the external interrupt from the interrupt controller. - * Once PDMGetInterrupt() returns an interrupt we -must- deliver it or pass it to - * the nested-hypervisor. We cannot re-request the interrupt from the controller again. - */ - uint8_t u8Interrupt; - int rc = PDMGetInterrupt(pVCpu, &u8Interrupt); - if (RT_SUCCESS(rc)) + int rc = vmxHCImportGuestStateEx(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS); + AssertRC(rc); + if (CPUMIsGuestVmxPhysIntrEnabled(pCtx)) { - /* Nested-guest external interrupt VM-exit when the "acknowledge interrupt on exit" is enabled. */ - if (CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)) + /* Nested-guest external interrupt VM-exit. */ + if ( CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT) + && !CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT)) { - Assert(CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT)); - VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */); + VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */); Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE); return rcStrict; } - vmxHCSetPendingExtInt(pVCpu, u8Interrupt); - return VINF_SUCCESS; + + /* + * Fetch the external interrupt from the interrupt controller. + * Once PDMGetInterrupt() returns an interrupt we -must- deliver it or pass it to + * the nested-hypervisor. We cannot re-request the interrupt from the controller again. + */ + uint8_t u8Interrupt; + rc = PDMGetInterrupt(pVCpu, &u8Interrupt); + if (RT_SUCCESS(rc)) + { + /* Nested-guest external interrupt VM-exit when the "acknowledge interrupt on exit" is enabled. */ + if (CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)) + { + Assert(CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT)); + VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */); + Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE); + return rcStrict; + } + vmxHCSetPendingExtInt(pVCpu, u8Interrupt); + return VINF_SUCCESS; + } } } return VINF_SUCCESS; diff --git a/src/VBox/VMM/VMMR0/HMVMXR0.cpp b/src/VBox/VMM/VMMR0/HMVMXR0.cpp index 2a16c319997..12753f203ab 100644 --- a/src/VBox/VMM/VMMR0/HMVMXR0.cpp +++ b/src/VBox/VMM/VMMR0/HMVMXR0.cpp @@ -5922,12 +5922,12 @@ static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransie if (TRPMHasTrap(pVCpu)) vmxHCTrpmTrapToPendingEvent(pVCpu); - uint32_t fIntrState; + uint32_t const fIntrState = vmxHCGetGuestIntrStateWithUpdate(pVCpu); #ifdef VBOX_WITH_NESTED_HWVIRT_VMX if (!pVmxTransient->fIsNestedGuest) - rcStrict = vmxHCEvaluatePendingEvent(pVCpu, pVmxTransient->pVmcsInfo, &fIntrState); + rcStrict = vmxHCEvaluatePendingEvent(pVCpu, pVmxTransient->pVmcsInfo); else - rcStrict = vmxHCEvaluatePendingEventNested(pVCpu, pVmxTransient->pVmcsInfo, &fIntrState); + rcStrict = vmxHCEvaluatePendingEventNested(pVCpu, pVmxTransient->pVmcsInfo); /* * While evaluating pending events if something failed (unlikely) or if we were @@ -5942,7 +5942,7 @@ static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransie return VINF_VMX_VMEXIT; } #else - rcStrict = vmxHCEvaluatePendingEvent(pVCpu, pVmxTransient->pVmcsInfo, &fIntrState); + rcStrict = vmxHCEvaluatePendingEvent(pVCpu, pVmxTransient->pVmcsInfo); Assert(rcStrict == VINF_SUCCESS); #endif @@ -5954,8 +5954,7 @@ static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransie * With nested-guests, the above does not apply since unrestricted guest execution is a * requirement. Regardless, we do this here to avoid duplicating code elsewhere. */ - rcStrict = vmxHCInjectPendingEvent(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->fIsNestedGuest, - fIntrState, fStepping); + rcStrict = vmxHCInjectPendingEvent(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->fIsNestedGuest, fIntrState, fStepping); if (RT_LIKELY(rcStrict == VINF_SUCCESS)) { /* likely */ } else diff --git a/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp b/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp index a4922ef081b..e5102151a72 100644 --- a/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp +++ b/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp @@ -3737,8 +3737,8 @@ static VBOXSTRICTRC nemR3DarwinPreRunGuest(PVM pVM, PVMCPU pVCpu, PVMXTRANSIENT if (TRPMHasTrap(pVCpu)) vmxHCTrpmTrapToPendingEvent(pVCpu); - uint32_t fIntrState; - rcStrict = vmxHCEvaluatePendingEvent(pVCpu, &pVCpu->nem.s.VmcsInfo, &fIntrState); + uint32_t const fIntrState = vmxHCGetGuestIntrStateWithUpdate(pVCpu); + rcStrict = vmxHCEvaluatePendingEvent(pVCpu, &pVCpu->nem.s.VmcsInfo); /* * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus |