- Timestamp:
- May 2, 2017 3:53:18 PM (7 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r66581 r66750 41 41 # define HMSVM_ALWAYS_TRAP_PF 42 42 # define HMSVM_ALWAYS_TRAP_TASK_SWITCH 43 # define HMSVM_USE_IEM_EVENT_REFLECTION 43 44 #endif 44 45 … … 3925 3926 } 3926 3927 3927 3928 #ifdef HMSVM_USE_IEM_EVENT_REFLECTION 3929 /** 3930 * Gets the IEM exception flags for the specified SVM event. 3931 * 3932 * @returns The IEM exception flags. 3933 * @param pEvent Pointer to the SVM event. 3934 * 3935 * @remarks This function currently only constructs flags required for 3936 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g. error-code 3937 * and CR2 aspects of an exception are not included). 3938 */ 3939 static uint32_t hmR0SvmGetIemXcptFlags(PCSVMEVENT pEvent) 3940 { 3941 uint8_t const uEventType = pEvent->n.u3Type; 3942 uint32_t fIemXcptFlags; 3943 switch (uEventType) 3944 { 3945 case SVM_EVENT_EXCEPTION: 3946 if (pEvent->n.u8Vector == X86_XCPT_BP) 3947 { 3948 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_BP_INSTR; 3949 break; 3950 } 3951 if (pEvent->n.u8Vector == X86_XCPT_OF) 3952 { 3953 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_OF_INSTR; 3954 break; 3955 } 3956 /** @todo How do we distinguish ICEBP \#DB from the regular one? */ 3957 /* fall thru */ 3958 case SVM_EVENT_NMI: 3959 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT; 3960 break; 3961 3962 case SVM_EVENT_EXTERNAL_IRQ: 3963 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT; 3964 break; 3965 3966 case SVM_EVENT_SOFTWARE_INT: 3967 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT; 3968 break; 3969 3970 default: 3971 fIemXcptFlags = 0; 3972 AssertMsgFailed(("Unexpected event type! uEventType=%#x uVector=%#x", uEventType, pEvent->n.u8Vector)); 3973 break; 3974 } 3975 return fIemXcptFlags; 3976 } 3977 3978 #else 3928 3979 /** 3929 3980 * Determines if an exception is a contributory exception. … … 3951 4002 return false; 3952 4003 } 4004 #endif /* HMSVM_USE_IEM_EVENT_REFLECTION */ 3953 4005 3954 4006 … … 3983 4035 if (pVmcb->ctrl.ExitIntInfo.n.u1Valid) 3984 4036 { 4037 #ifdef HMSVM_USE_IEM_EVENT_REFLECTION 4038 IEMXCPTRAISE enmRaise; 4039 IEMXCPTRAISEINFO fRaiseInfo; 4040 bool fReflectingNmi = false; 4041 bool const fExitIsHwXcpt = pSvmTransient->u64ExitCode - SVM_EXIT_EXCEPTION_0 <= SVM_EXIT_EXCEPTION_31; 4042 if (fExitIsHwXcpt) 4043 { 4044 uint8_t const uIdtVector = pVmcb->ctrl.ExitIntInfo.n.u8Vector; 4045 uint8_t const uExitVector = pSvmTransient->u64ExitCode - SVM_EXIT_EXCEPTION_0; 4046 uint32_t const fIdtVectorFlags = hmR0SvmGetIemXcptFlags(&pVmcb->ctrl.ExitIntInfo); 4047 uint32_t const fExitVectorFlags = IEM_XCPT_FLAGS_T_CPU_XCPT; 4048 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo); 4049 4050 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF)) 4051 { 4052 if (fRaiseInfo & IEMXCPTRAISEINFO_NMI_XCPT) 4053 fReflectingNmi = true; 4054 pSvmTransient->fVectoringPF = true; 4055 } 4056 else if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF) 4057 pSvmTransient->fVectoringDoublePF = true; 4058 } 4059 else 4060 { 4061 /* 4062 * If event delivery caused an #VMEXIT that is not an exception (e.g. #NPF) then reflect the original 4063 * exception to the guest after handling the #VMEXIT. 4064 */ 4065 enmRaise = IEMXCPTRAISE_PREV_EVENT; 4066 fRaiseInfo = IEMXCPTRAISEINFO_NONE; 4067 } 4068 4069 switch (enmRaise) 4070 { 4071 case IEMXCPTRAISE_CURRENT_XCPT: 4072 case IEMXCPTRAISE_PREV_EVENT: 4073 { 4074 /* For software interrupts, we shall re-execute the instruction. */ 4075 if (!(fRaiseInfo & IEMXCPTRAISEINFO_SOFT_INT_XCPT)) 4076 { 4077 /* If we are re-injecting the NMI, clear NMI blocking. */ 4078 if (fReflectingNmi) 4079 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS); 4080 4081 Assert(pVmcb->ctrl.ExitIntInfo.n.u3Type != SVM_EVENT_SOFTWARE_INT); 4082 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectPendingReflect); 4083 hmR0SvmSetPendingEvent(pVCpu, &pVmcb->ctrl.ExitIntInfo, 0 /* GCPtrFaultAddress */); 4084 4085 /* If uExitVector is #PF, CR2 value will be updated from the VMCB if it's a guest #PF. See hmR0SvmExitXcptPF(). */ 4086 Log4(("IDT: Pending vectoring event %#RX64 ErrValid=%RTbool Err=%#RX32\n", pVmcb->ctrl.ExitIntInfo.u, 4087 !!pVmcb->ctrl.ExitIntInfo.n.u1ErrorCodeValid, pVmcb->ctrl.ExitIntInfo.n.u32ErrorCode)); 4088 } 4089 break; 4090 } 4091 4092 case IEMXCPTRAISE_DOUBLE_FAULT: 4093 { 4094 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectPendingReflect); 4095 hmR0SvmSetPendingXcptDF(pVCpu); 4096 rc = VINF_HM_DOUBLE_FAULT; 4097 break; 4098 } 4099 4100 case IEMXCPTRAISE_TRIPLE_FAULT: 4101 { 4102 rc = VINF_EM_RESET; 4103 break; 4104 } 4105 4106 case IEMXCPTRAISE_CPU_HANG: 4107 { 4108 rc = VERR_EM_GUEST_CPU_HANG; 4109 break; 4110 } 4111 4112 default: 4113 { 4114 AssertMsgFailed(("hmR0SvmExitCpuid: EMInterpretCpuId failed with %Rrc\n", rc)); 4115 rc = VERR_SVM_IPE_2; 4116 break; 4117 } 4118 } 4119 #else 3985 4120 uint8_t uIdtVector = pVmcb->ctrl.ExitIntInfo.n.u8Vector; 3986 4121 … … 4114 4249 break; 4115 4250 } 4251 #endif /* HMSVM_USE_IEM_EVENT_REFLECTION */ 4116 4252 } 4117 4253 Assert(rc == VINF_SUCCESS || rc == VINF_HM_DOUBLE_FAULT || rc == VINF_EM_RESET || rc == VERR_EM_GUEST_CPU_HANG);
Note:
See TracChangeset
for help on using the changeset viewer.

