Changeset 66701 in vbox
- Timestamp:
- Apr 27, 2017 4:49:12 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 115095
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r66390 r66701 5808 5808 5809 5809 /** 5810 * Gets the IEM exception flags for the specified vector and IDT vectoring / 5811 * VM-exit interruption info type. 5812 * 5813 * @returns The IEM exception flags. 5814 * @param uVector The event vector. 5815 * @param uVmxVectorType The VMX event type. 5816 */ 5817 static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxVectorType) 5818 { 5819 uint32_t fIemXcptFlags; 5820 switch (uVmxVectorType) 5821 { 5822 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT: 5823 case VMX_IDT_VECTORING_INFO_TYPE_NMI: 5824 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT; 5825 break; 5826 5827 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT: 5828 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT; 5829 break; 5830 5831 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT: 5832 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR; 5833 break; 5834 5835 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT: 5836 { 5837 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT; 5838 if (uVector == X86_XCPT_BP) 5839 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR; 5840 else if (uVector == X86_XCPT_OF) 5841 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR; 5842 else 5843 { 5844 fIemXcptFlags = 0; 5845 AssertMsgFailed(("Unexpected vector for software int. uVector=%#x", uVector)); 5846 } 5847 break; 5848 } 5849 5850 default: 5851 fIemXcptFlags = 0; 5852 AssertMsgFailed(("Unexpected vector type! uVmxVectorType=%#x uVector=%#x", uVmxVectorType, uVector)); 5853 break; 5854 } 5855 return fIemXcptFlags; 5856 } 5857 5858 5859 /** 5810 5860 * Handle a condition that occurred while delivering an event through the guest 5811 5861 * IDT. … … 5838 5888 uint32_t uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo); 5839 5889 uint32_t uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo); 5840 5890 #if 1 5891 /* See Intel spec. 30.7.1.1 "Reflecting Exceptions to Guest Software". */ 5892 IEMXCPTRAISE enmRaise; 5893 IEMXCPTRAISEINFO fRaiseInfo; 5894 if (VMX_EXIT_INTERRUPTION_INFO_IS_VALID(pVmxTransient->uExitIntInfo)) 5895 { 5896 uint32_t const uExitVectorType = VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uExitIntInfo); 5897 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType); 5898 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType); 5899 AssertMsg( uExitVectorType == VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT 5900 || uExitVectorType == VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI, 5901 ("hmR0VmxCheckExitDueToEventDelivery: Unexpected VM-exit interruption info. type %#x!\n", uExitVectorType)); 5902 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, 5903 &fRaiseInfo); 5904 } 5905 else 5906 { 5907 /* 5908 * If event delivery caused an EPT violation/misconfig or APIC access VM-exit, then the VM-exit 5909 * interruption-information will not be valid as it's not an exception and we end up here. 5910 * 5911 * If the event was an external interrupt or hardare exception (incl. NMI) it is sufficient to 5912 * reflect this event to the guest after handling the VM-exit. 5913 * 5914 * If the event was a software interrupt (generated with INT n) or a software exception (generated 5915 * by INT3/INTO) or a privileged software exception (generated by INT1), we can handle the VM-exit 5916 * and continue guest execution which will re-execute the instruction rather than re-injecting the 5917 * event, as that can cause premature trips to ring-3 before injection and involve TRPM which 5918 * currently has no way of storing that the exceptions were caused by these special instructions. 5919 */ 5920 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT 5921 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI 5922 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT) 5923 enmRaise = IEMXCPTRAISE_PREV_EVENT; 5924 else 5925 enmRaise = IEMXCPTRAISE_REEXEC_INSTR; 5926 fRaiseInfo = IEMXCPTRAISEINFO_NONE; 5927 } 5928 5929 /* 5930 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig 5931 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest 5932 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the 5933 * subsequent VM-entry would fail. 5934 * 5935 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception". See @bugref{7445}. 5936 */ 5937 if ( VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS) 5938 && uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI 5939 && ( enmRaise == IEMXCPTRAISE_PREV_EVENT 5940 || fRaiseInfo == IEMXCPTRAISEINFO_NMI_PF) 5941 && (pVCpu->hm.s.vmx.u32PinCtls & VMX_VMCS_CTRL_PIN_EXEC_VIRTUAL_NMI)) 5942 { 5943 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS); 5944 } 5945 5946 switch (enmRaise) 5947 { 5948 case IEMXCPTRAISE_CURRENT_XCPT: 5949 { 5950 /* 5951 * Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). 5952 */ 5953 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF)) 5954 pVmxTransient->fVectoringPF = true; 5955 5956 /* 5957 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the 5958 * second #PF as a guest #PF (and not a nested #PF) and needs to be converted into a #DF. 5959 */ 5960 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF) 5961 pVmxTransient->fVectoringDoublePF = true; 5962 5963 Assert(rcStrict == VINF_SUCCESS); 5964 break; 5965 } 5966 5967 case IEMXCPTRAISE_PREV_EVENT: 5968 { 5969 /* 5970 * Re-raise the previous (first) exception/interrupt as delivery caused a premature VM-exit. 5971 */ 5972 Assert( uIdtVectorType != VMX_IDT_VECTORING_INFO_TYPE_SW_INT 5973 && uIdtVectorType != VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT 5974 && uIdtVectorType != VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT); 5975 5976 uint32_t u32ErrCode; 5977 if (VMX_IDT_VECTORING_INFO_ERROR_CODE_IS_VALID(pVmxTransient->uIdtVectoringInfo)) 5978 { 5979 rc2 = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 5980 AssertRCReturn(rc2, rc2); 5981 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode; 5982 } 5983 else 5984 u32ErrCode = 0; 5985 5986 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */ 5987 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectPendingReflect); 5988 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo), 5989 0 /* cbInstr */, u32ErrCode, pMixedCtx->cr2); 5990 5991 Log4(("IDT: vcpu[%RU32] Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo, 5992 pVCpu->hm.s.Event.u32ErrCode)); 5993 Assert(rcStrict == VINF_SUCCESS); 5994 break; 5995 } 5996 5997 case IEMXCPTRAISE_DOUBLE_FAULT: 5998 { 5999 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectPendingReflect); 6000 hmR0VmxSetPendingXcptDF(pVCpu, pMixedCtx); 6001 6002 Log4(("IDT: vcpu[%RU32] Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->idCpu, 6003 pVCpu->hm.s.Event.u64IntInfo, uIdtVector, uExitVector)); 6004 rcStrict = VINF_HM_DOUBLE_FAULT; 6005 break; 6006 } 6007 6008 case IEMXCPTRAISE_TRIPLE_FAULT: 6009 { 6010 Log4(("IDT: vcpu[%RU32] Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", pVCpu->idCpu, uIdtVector, 6011 uExitVector)); 6012 rcStrict = VINF_EM_RESET; 6013 break; 6014 } 6015 6016 case IEMXCPTRAISE_CPU_HANG: 6017 { 6018 Log4(("IDT: vcpu[%RU32] Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", pVCpu->idCpu, fRaiseInfo)); 6019 rcStrict = VERR_EM_GUEST_CPU_HANG; 6020 break; 6021 } 6022 6023 case IEMXCPTRAISE_REEXEC_INSTR: 6024 Assert(rcStrict == VINF_SUCCESS); 6025 break; 6026 6027 default: 6028 { 6029 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise)); 6030 rcStrict = VERR_VMX_IPE_2; 6031 break; 6032 } 6033 } 6034 #else 5841 6035 typedef enum 5842 6036 { … … 5983 6177 break; 5984 6178 } 6179 #endif 5985 6180 } 5986 6181 else if ( VMX_EXIT_INTERRUPTION_INFO_IS_VALID(pVmxTransient->uExitIntInfo)
Note:
See TracChangeset
for help on using the changeset viewer.