Changeset 74784 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Oct 12, 2018 9:58:57 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r74756 r74784 1336 1336 * 1337 1337 * @returns The VMX event type. 1338 * @param uVector The interrupt / exception vector number.1338 * @param uVector The interrupt / exception vector. 1339 1339 * @param fFlags The IEM event flag (see IEM_XCPT_FLAGS_XXX). 1340 1340 */ … … 3668 3668 3669 3669 /** 3670 * VMX VM-exit handler for VM-exits due to delivery of an event (indirectly). 3670 * VMX VM-exit handler for VM-exits due to external interrupts. 3671 * 3672 * @returns VBox strict status code. 3673 * @param pVCpu The cross context virtual CPU structure. 3674 * @param uVector The external interrupt vector. 3675 * @param fIntPending Whether the external interrupt is pending or 3676 * acknowdledged in the interrupt controller. 3677 */ 3678 IEM_STATIC VBOXSTRICTRC iemVmxVmexitExtInt(PVMCPU pVCpu, uint8_t uVector, bool fIntPending) 3679 { 3680 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3681 Assert(pVmcs); 3682 3683 /* The VM-exit is subject to "External interrupt exiting" is being set. */ 3684 if (pVmcs->u32PinCtls & VMX_PIN_CTLS_EXT_INT_EXIT) 3685 { 3686 if (fIntPending) 3687 { 3688 /* 3689 * If the interrupt is pending and we don't need to acknowledge the 3690 * interrupt on VM-exit, cause the VM-exit immediately. 3691 * 3692 * See Intel spec 25.2 "Other Causes Of VM Exits". 3693 */ 3694 if (!(pVmcs->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)) 3695 { 3696 iemVmxVmcsSetExitIntInfo(pVCpu, 0); 3697 iemVmxVmcsSetExitIntErrCode(pVCpu, 0); 3698 iemVmxVmcsSetExitQual(pVCpu, 0); 3699 return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT); 3700 } 3701 3702 /* 3703 * If the interrupt is pending and we -do- need to acknowledge the interrupt 3704 * on VM-exit, postpone VM-exit til after the interrupt controller has been 3705 * acknowledged that the interrupt has been consumed. 3706 */ 3707 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 3708 } 3709 3710 /* 3711 * If the interrupt is no longer pending (i.e. it has been acknowledged) and the 3712 * "External interrupt exiting" and "Acknowledge interrupt on VM-exit" controls are 3713 * all set, we cause the VM-exit now. We need to record the external interrupt that 3714 * just occurred in the VM-exit interruption information field. 3715 * 3716 * See Intel spec. 27.2.2 "Information for VM Exits Due to Vectored Events". 3717 */ 3718 if (pVmcs->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT) 3719 { 3720 uint8_t const fNmiUnblocking = 0; /** @todo NSTVMX: Implement NMI-unblocking due to IRET. */ 3721 uint32_t const uExitIntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, uVector) 3722 | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_EXT_INT) 3723 | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET, fNmiUnblocking) 3724 | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID, 1); 3725 iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo); 3726 iemVmxVmcsSetExitIntErrCode(pVCpu, 0); 3727 iemVmxVmcsSetExitQual(pVCpu, 0); 3728 return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT); 3729 } 3730 } 3731 3732 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 3733 } 3734 3735 3736 /** 3737 * VMX VM-exit handler for VM-exits due to delivery of an event. 3671 3738 * 3672 3739 * @returns VBox strict status code. 3673 3740 * @param pVCpu The cross context virtual CPU structure. 3674 * @param uVector The interrupt / exception vector number.3741 * @param uVector The interrupt / exception vector. 3675 3742 * @param fFlags The flags (see IEM_XCPT_FLAGS_XXX). 3676 3743 * @param uErrCode The error code associated with the event. … … 3708 3775 3709 3776 /* 3777 * We are injecting an external interrupt, check if we need to cause a VM-exit now. 3778 * If not, the caller will continue delivery of the external interrupt as it would 3779 * normally. 3780 */ 3781 if (fFlags & IEM_XCPT_FLAGS_T_EXT_INT) 3782 { 3783 Assert(!VMX_IDT_VECTORING_INFO_IS_VALID(pVmcs->u32RoIdtVectoringInfo)); 3784 return iemVmxVmexitExtInt(pVCpu, uVector, false /* fIntPending */); 3785 } 3786 3787 /* 3710 3788 * Evaluate intercepts for hardware exceptions including #BP, #DB, #OF 3711 3789 * generated by INT3, INT1 (ICEBP) and INTO respectively. 3712 3790 */ 3713 bool fIntercept = false; 3714 bool fIsHwXcpt = false; 3715 if (fFlags & (IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_T_SOFT_INT)) 3716 { 3717 if ( !(fFlags & IEM_XCPT_FLAGS_T_SOFT_INT) 3718 || (fFlags & (IEM_XCPT_FLAGS_BP_INSTR | IEM_XCPT_FLAGS_OF_INSTR | IEM_XCPT_FLAGS_ICEBP_INSTR))) 3719 { 3720 fIsHwXcpt = true; 3721 do 3791 Assert(fFlags & (IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_T_SOFT_INT)); 3792 bool fIntercept = false; 3793 bool fIsHwXcpt = false; 3794 if ( !(fFlags & IEM_XCPT_FLAGS_T_SOFT_INT) 3795 || (fFlags & (IEM_XCPT_FLAGS_BP_INSTR | IEM_XCPT_FLAGS_OF_INSTR | IEM_XCPT_FLAGS_ICEBP_INSTR))) 3796 { 3797 fIsHwXcpt = true; 3798 /* NMIs have a dedicated VM-execution control for causing VM-exits. */ 3799 if (uVector == X86_XCPT_NMI) 3800 fIntercept = RT_BOOL(pVmcs->u32PinCtls & VMX_PIN_CTLS_NMI_EXIT); 3801 else 3802 { 3803 /* Page-faults are subject to masking using its error code. */ 3804 uint32_t fXcptBitmap = pVmcs->u32XcptBitmap; 3805 if (uVector == X86_XCPT_PF) 3722 3806 { 3723 /* NMIs have a dedicated VM-execution control for causing VM-exits. */ 3724 if (uVector == X86_XCPT_NMI) 3725 { 3726 fIntercept = RT_BOOL(pVmcs->u32PinCtls & VMX_PIN_CTLS_NMI_EXIT); 3727 break; 3728 } 3729 3730 /* Page-faults are subject to masking using its error code. */ 3731 uint32_t fXcptBitmap = pVmcs->u32XcptBitmap; 3732 if (uVector == X86_XCPT_PF) 3733 { 3734 uint32_t const fXcptPFMask = pVmcs->u32XcptPFMask; 3735 uint32_t const fXcptPFMatch = pVmcs->u32XcptPFMatch; 3736 if ((uErrCode & fXcptPFMask) != fXcptPFMatch) 3737 fXcptBitmap ^= RT_BIT(X86_XCPT_PF); 3738 } 3739 3740 /* Consult the exception bitmap. */ 3741 if (fXcptBitmap & RT_BIT(uVector)) 3742 fIntercept = true; 3743 } while (0); 3744 } 3745 /* else: Software interrupts cannot be intercepted and therefore do not cause a VM-exit. */ 3746 } 3747 else if (fFlags & IEM_XCPT_FLAGS_T_EXT_INT) 3748 { 3749 /* External interrupts have a dedicated VM-execution control for causing VM-exits. */ 3750 fIntercept = RT_BOOL(pVmcs->u32PinCtls & VMX_PIN_CTLS_EXT_INT_EXIT); 3751 3752 /** @todo NSTVMX: What about "acknowledge interrupt on exit" control? */ 3753 } 3754 3755 /* 3756 * Now that we've determined whether the external interrupt or hardware exception 3807 uint32_t const fXcptPFMask = pVmcs->u32XcptPFMask; 3808 uint32_t const fXcptPFMatch = pVmcs->u32XcptPFMatch; 3809 if ((uErrCode & fXcptPFMask) != fXcptPFMatch) 3810 fXcptBitmap ^= RT_BIT(X86_XCPT_PF); 3811 } 3812 3813 /* Consult the exception bitmap for all hardware exceptions (except NMI). */ 3814 if (fXcptBitmap & RT_BIT(uVector)) 3815 fIntercept = true; 3816 } 3817 } 3818 /* else: Software interrupts cannot be intercepted and therefore do not cause a VM-exit. */ 3819 3820 /* 3821 * Now that we've determined whether the software interrupt or hardware exception 3757 3822 * causes a VM-exit, we need to construct the relevant VM-exit information and 3758 3823 * cause the VM-exit. … … 3760 3825 if (fIntercept) 3761 3826 { 3827 Assert(!(fFlags & IEM_XCPT_FLAGS_T_EXT_INT)); 3828 3829 /* Construct the rest of the event related information fields and cause the VM-exit. */ 3762 3830 uint64_t uExitQual = 0; 3763 3831 if (fIsHwXcpt) … … 3772 3840 } 3773 3841 3774 /* Construct the rest of the event related information fields and cause the VM-exit. */3775 uint32_t const uExitReason = (fFlags & IEM_XCPT_FLAGS_T_EXT_INT) ? VMX_EXIT_EXT_INT : VMX_EXIT_XCPT_OR_NMI;3776 3842 uint8_t const fNmiUnblocking = 0; /** @todo NSTVMX: Implement NMI-unblocking due to IRET. */ 3777 3843 uint8_t const fErrCodeValid = (fFlags & IEM_XCPT_FLAGS_ERR); … … 3797 3863 iemVmxVmcsSetExitInstrLen(pVCpu, 0); 3798 3864 3799 return iemVmxVmexit(pVCpu, uExitReason);3865 return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI); 3800 3866 } 3801 3867
Note:
See TracChangeset
for help on using the changeset viewer.