Changeset 57555 in vbox for trunk/src/VBox
- Timestamp:
- Aug 27, 2015 10:11:18 AM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 102373
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r57514 r57555 337 337 static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMXFLUSHEPT enmFlush); 338 338 static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMXFLUSHVPID enmFlush, RTGCPTR GCPtr); 339 static void hmR0VmxClearIntNmiWindowsVmcs(PVMCPU pVCpu); 339 340 static int hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntInfo, uint32_t cbInstr, 340 341 uint32_t u32ErrCode, RTGCUINTREG GCPtrFaultAddress, … … 6810 6811 6811 6812 /** 6812 * Converts any pending HM event into a TRPM trap. Typically used when leaving 6813 * VT-x to execute any instruction. 6813 * Converts the pending HM event into a TRPM trap. 6814 6814 * 6815 6815 * @param pvCpu Pointer to the VMCPU. … … 6873 6873 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr); 6874 6874 } 6875 6876 /* Clear the pending event from the VMCS. */ 6877 #ifdef VBOX_STRICT 6878 uint32_t u32EntryInfo; 6879 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo); 6880 AssertRC(rc); 6881 Assert(VMX_ENTRY_INTERRUPTION_INFO_IS_VALID(u32EntryInfo)); 6882 #endif 6883 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc); 6884 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, 0); AssertRC(rc); 6885 6886 /* We're now done converting the pending event. */ 6875 6887 pVCpu->hm.s.Event.fPending = false; 6876 6888 } … … 7107 7119 Assert(!pVCpu->hm.s.Event.fPending); 7108 7120 } 7121 7122 /* Clear interrupt-window and NMI-window controls as we re-evaluate it when we return from ring-3. */ 7123 hmR0VmxClearIntNmiWindowsVmcs(pVCpu); 7109 7124 7110 7125 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending … … 7311 7326 static void hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 7312 7327 { 7313 Assert(!pVCpu->hm.s.Event.fPending);7314 7315 7328 /* Get the current interruptibility-state of the guest and then figure out what can be injected. */ 7316 7329 uint32_t const uIntrState = hmR0VmxGetGuestIntrState(pVCpu, pMixedCtx); … … 7332 7345 { 7333 7346 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */ 7334 if ( !fBlockNmi 7347 if ( !pVCpu->hm.s.Event.fPending 7348 && !fBlockNmi 7335 7349 && !fBlockSti 7336 7350 && !fBlockMovSS) … … 7356 7370 AssertRC(rc); 7357 7371 bool const fBlockInt = !(pMixedCtx->eflags.u32 & X86_EFL_IF); 7358 if ( !fBlockInt 7372 if ( !pVCpu->hm.s.Event.fPending 7373 && !fBlockInt 7359 7374 && !fBlockSti 7360 7375 && !fBlockMovSS) … … 7435 7450 { 7436 7451 /* 7437 * Clear any interrupt-window exiting control if we're going to inject an interrupt. Saves one extra 7438 * VM-exit in situations where we previously setup interrupt-window exiting but got other VM-exits and 7439 * ended up enabling interrupts outside VT-x. 7452 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt 7453 * pending even while injecting an event and in this case, we want a VM-exit as soon as 7454 * the guest is ready for the next interrupt, see @bugref{6208#c45}. 7455 * 7456 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery". 7440 7457 */ 7441 uint32_t uIntType = VMX_EXIT_INTERRUPTION_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo); 7442 if ( (pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_INT_WINDOW_EXIT) 7443 && uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT) 7444 { 7445 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.VmxProcCtls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_INT_WINDOW_EXIT); 7446 hmR0VmxClearIntWindowExitVmcs(pVCpu); 7447 } 7448 7458 uint32_t const uIntType = VMX_EXIT_INTERRUPTION_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo); 7449 7459 #ifdef VBOX_STRICT 7450 7460 if (uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT) … … 7474 7484 fBlockSti = RT_BOOL(uIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI); 7475 7485 7476 #ifdef VBOX_WITH_STATISTICS7477 7486 if (uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT) 7478 7487 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt); 7479 7488 else 7480 7489 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt); 7481 #endif7482 7490 } 7483 7491 … … 7920 7928 * @remarks No-long-jump zone!!! 7921 7929 */ 7922 static void hmR0VmxClear EventVmcs(PVMCPU pVCpu)7930 static void hmR0VmxClearIntNmiWindowsVmcs(PVMCPU pVCpu) 7923 7931 { 7924 7932 int rc; … … 7930 7938 if (pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_NMI_WINDOW_EXIT) 7931 7939 hmR0VmxClearNmiWindowExitVmcs(pVCpu); 7932 7933 if (!pVCpu->hm.s.Event.fPending)7934 return;7935 7936 #ifdef VBOX_STRICT7937 uint32_t u32EntryInfo;7938 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);7939 AssertRC(rc);7940 Assert(VMX_ENTRY_INTERRUPTION_INFO_IS_VALID(u32EntryInfo));7941 #endif7942 7943 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);7944 AssertRC(rc);7945 7946 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, 0);7947 AssertRC(rc);7948 7949 /* We deliberately don't clear "hm.s.Event.fPending" here, it's taken7950 care of in hmR0VmxExitToRing3() converting the pending event to TRPM. */7951 7940 } 7952 7941 … … 8400 8389 if (TRPMHasTrap(pVCpu)) 8401 8390 hmR0VmxTrpmTrapToPendingEvent(pVCpu); 8402 else if (!pVCpu->hm.s.Event.fPending) 8403 hmR0VmxEvaluatePendingEvent(pVCpu, pMixedCtx); 8391 hmR0VmxEvaluatePendingEvent(pVCpu, pMixedCtx); 8404 8392 8405 8393 /* … … 8446 8434 || VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) ) 8447 8435 { 8448 hmR0VmxClearEventVmcs(pVCpu);8449 8436 ASMSetFlags(pVmxTransient->fEFlags); 8450 8437 VMMRZCallRing3Enable(pVCpu); … … 8455 8442 if (RTThreadPreemptIsPending(NIL_RTTHREAD)) 8456 8443 { 8457 hmR0VmxClearEventVmcs(pVCpu);8458 8444 ASMSetFlags(pVmxTransient->fEFlags); 8459 8445 VMMRZCallRing3Enable(pVCpu);
Note:
See TracChangeset
for help on using the changeset viewer.