Changeset 74287 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Sep 15, 2018 4:29:24 AM (6 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp
r74258 r74287 769 769 } 770 770 771 772 /** 773 * Injects an event using TRPM given a VM-entry interruption info. and related 774 * fields. 775 * 776 * @returns VBox status code. 777 * @param uEntryIntInfo The VM-entry interruption info. 778 * @param uErrCode The error code associated with the event if any. 779 * @param cbInstr The VM-entry instruction length (for software 780 * interrupts and software exceptions). Pass 0 781 * otherwise. 782 * @param GCPtrFaultAddress The guest CR2 if this is a \#PF event. 783 */ 784 VMM_INT_DECL(int) HMVmxEntryIntInfoInjectTrpmEvent(PVMCPU pVCpu, uint32_t uEntryIntInfo, uint32_t uErrCode, uint32_t cbInstr, 785 RTGCUINTPTR GCPtrFaultAddress) 786 { 787 Assert(VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo)); 788 789 uint8_t const uType = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo); 790 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(uEntryIntInfo); 791 bool const fErrCodeValid = VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(uEntryIntInfo); 792 793 TRPMEVENT enmTrapType; 794 switch (uType) 795 { 796 case VMX_ENTRY_INT_INFO_TYPE_EXT_INT: 797 enmTrapType = TRPM_HARDWARE_INT; 798 break; 799 800 case VMX_ENTRY_INT_INFO_TYPE_SW_INT: 801 enmTrapType = TRPM_SOFTWARE_INT; 802 break; 803 804 case VMX_ENTRY_INT_INFO_TYPE_NMI: 805 case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT: /* ICEBP. */ 806 case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT: /* #BP and #OF */ 807 case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT: 808 enmTrapType = TRPM_TRAP; 809 break; 810 811 default: 812 /* Shouldn't really happen. */ 813 AssertMsgFailedReturn(("Invalid trap type %#x\n", uType), VERR_VMX_IPE_4); 814 break; 815 } 816 817 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType); 818 AssertRCReturn(rc, rc); 819 820 if (fErrCodeValid) 821 TRPMSetErrorCode(pVCpu, uErrCode); 822 823 if ( uType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT 824 && uVector == X86_XCPT_PF) 825 TRPMSetFaultAddress(pVCpu, GCPtrFaultAddress); 826 else if ( uType == VMX_ENTRY_INT_INFO_TYPE_SW_INT 827 || uType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT 828 || uType == VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT) 829 { 830 AssertMsg( uType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT 831 || (uVector == X86_XCPT_BP || uVector == X86_XCPT_OF), 832 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uType)); 833 TRPMSetInstrLength(pVCpu, cbInstr); 834 } 835 836 return VINF_SUCCESS; 837 } 838 -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r74258 r74287 2966 2966 || uVector == X86_XCPT_MC)) 2967 2967 || ( uIntType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT 2968 && uVector == 0))2968 && uVector == VMX_ENTRY_INT_INFO_VECTOR_MTF)) 2969 2969 { /* likely */ } 2970 2970 else … … 3480 3480 uint8_t const uVector = RT_BF_GET(uIntInfo, VMX_BF_ENTRY_INT_INFO_VECTOR); 3481 3481 uint8_t const uRsvd = RT_BF_GET(uIntInfo, VMX_BF_ENTRY_INT_INFO_RSVD_12_30); 3482 if ( uRsvd == 03482 if ( !uRsvd 3483 3483 && HMVmxIsEntryIntInfoTypeValid(IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVmxMonitorTrapFlag, uType) 3484 3484 && HMVmxIsEntryIntInfoVectorValid(uVector, uType)) … … 3709 3709 /* TPR threshold and VTPR. */ 3710 3710 uint8_t const *pbVirtApic = (uint8_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 3711 uint8_t const u8VTpr= *(pbVirtApic + XAPIC_OFF_TPR);3711 uint8_t const u8VTpr = *(pbVirtApic + XAPIC_OFF_TPR); 3712 3712 if ( !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS) 3713 3713 && !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY) … … 3989 3989 * Loads the guest auto-load MSRs area as part of VM-entry. 3990 3990 * 3991 * @returns VBox status code. 3991 3992 * @param pVCpu The cross context virtual CPU structure. 3992 3993 * @param pszInstr The VMX instruction name (for logging purposes). … … 4071 4072 * Loads the guest-state as part of VM-entry. 4072 4073 * 4074 * @returns VBox status code. 4073 4075 * @param pVCpu The cross context virtual CPU structure. 4074 4076 * @param pszInstr The VMX instruction name (for logging purposes). … … 4079 4081 IEM_STATIC int iemVmxVmentryLoadGuestState(PVMCPU pVCpu, const char *pszInstr) 4080 4082 { 4083 /* 4084 * Load control, debug, segment, descriptor-table registers and some MSRs. 4085 */ 4081 4086 iemVmxVmentryLoadGuestControlRegsMsr(pVCpu); 4082 4087 iemVmxVmentryLoadGuestSegRegs(pVCpu); … … 4105 4110 4106 4111 /** 4112 * Performs event injection (if any) as part of VM-entry. 4113 * 4114 * @param pVCpu The cross context virtual CPU structure. 4115 * @param pszInstr The VMX instruction name (for logging purposes). 4116 */ 4117 IEM_STATIC int iemVmxVmentryInjectEvent(PVMCPU pVCpu, const char *pszInstr) 4118 { 4119 /* 4120 * Inject events. 4121 * See Intel spec. 26.5 "Event Injection". 4122 */ 4123 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 4124 uint32_t const uEntryIntInfo = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->u32EntryIntInfo; 4125 if (VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo)) 4126 { 4127 uint8_t const uType = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo); 4128 if (uType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT) 4129 { 4130 Assert(VMX_ENTRY_INT_INFO_VECTOR(uEntryIntInfo) == VMX_ENTRY_INT_INFO_VECTOR_MTF); 4131 VMCPU_FF_SET(pVCpu, VMCPU_FF_MTF); 4132 return VINF_SUCCESS; 4133 } 4134 4135 /** @todo NSTVMX: Is it safe to update IDT-vectoring information in the VMCS 4136 * here? */ 4137 4138 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = false; 4139 int rc = HMVmxEntryIntInfoInjectTrpmEvent(pVCpu, uEntryIntInfo, pVmcs->u32EntryXcptErrCode, pVmcs->u32EntryInstrLen, 4140 pVCpu->cpum.GstCtx.cr2); 4141 AssertRCReturn(rc, rc); 4142 } 4143 4144 NOREF(pszInstr); 4145 return VINF_SUCCESS; 4146 } 4147 4148 4149 /** 4150 * Perform a VMX transition updated PGM, IEM and CPUM. 4151 * 4152 * @param pVCpu The cross context virtual CPU structure. 4153 */ 4154 IEM_STATIC int iemVmxWorldSwitch(PVMCPU pVCpu) 4155 { 4156 /* 4157 * Inform PGM about paging mode changes. 4158 * We include X86_CR0_PE because PGM doesn't handle paged-real mode yet, 4159 * see comment in iemMemPageTranslateAndCheckAccess(). 4160 */ 4161 int rc = PGMChangeMode(pVCpu, pVCpu->cpum.GstCtx.cr0 | X86_CR0_PE, pVCpu->cpum.GstCtx.cr4, pVCpu->cpum.GstCtx.msrEFER); 4162 # ifdef IN_RING3 4163 Assert(rc != VINF_PGM_CHANGE_MODE); 4164 # endif 4165 AssertRCReturn(rc, rc); 4166 4167 /* Inform CPUM (recompiler), can later be removed. */ 4168 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_ALL); 4169 4170 /* 4171 * Flush the TLB with new CR3. This is required in case the PGM mode change 4172 * above doesn't actually change anything. 4173 */ 4174 if (rc == VINF_SUCCESS) 4175 { 4176 rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true); 4177 AssertRCReturn(rc, rc); 4178 } 4179 4180 /* Re-initialize IEM cache/state after the drastic mode switch. */ 4181 iemReInitExec(pVCpu); 4182 return rc; 4183 } 4184 4185 4186 /** 4107 4187 * VMLAUNCH/VMRESUME instruction execution worker. 4108 4188 * … … 4163 4243 { 4164 4244 /* VMLAUNCH with non-clear VMCS. */ 4165 if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState != VMX_V_VMCS_STATE_CLEAR) 4245 if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState == VMX_V_VMCS_STATE_CLEAR) 4246 { /* likely */ } 4247 else 4166 4248 { 4167 4249 Log(("vmlaunch: VMLAUNCH with non-clear VMCS -> VMFail\n")); … … 4175 4257 { 4176 4258 /* VMRESUME with non-launched VMCS. */ 4177 if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState != VMX_V_VMCS_STATE_LAUNCHED) 4259 if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState == VMX_V_VMCS_STATE_LAUNCHED) 4260 { /* likely */ } 4261 else 4178 4262 { 4179 4263 Log(("vmresume: VMRESUME with non-launched VMCS -> VMFail\n")); … … 4228 4312 Assert(rc != VINF_CPUM_R3_MSR_WRITE); 4229 4313 4314 /* VMLAUNCH instruction must update the VMCS launch state. */ 4315 if (uInstrId == VMXINSTRID_VMLAUNCH) 4316 pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState = VMX_V_VMCS_STATE_LAUNCHED; 4317 4318 /* Perform the VMX transition (PGM updates). */ 4319 VBOXSTRICTRC rcStrict = iemVmxWorldSwitch(pVCpu); 4320 if (rcStrict == VINF_SUCCESS) 4321 { /* likely */ } 4322 else if (RT_SUCCESS(rcStrict)) 4323 { 4324 Log3(("%s: iemVmxWorldSwitch returns %Rrc -> Setting passup status\n", pszInstr, 4325 VBOXSTRICTRC_VAL(rcStrict))); 4326 rcStrict = iemSetPassUpStatus(pVCpu, rcStrict); 4327 } 4328 else 4329 { 4330 Log3(("%s: iemVmxWorldSwitch failed! rc=%Rrc\n", pszInstr, VBOXSTRICTRC_VAL(rcStrict))); 4331 return rcStrict; 4332 } 4333 4334 /* Event injection. */ 4335 iemVmxVmentryInjectEvent(pVCpu, pszInstr); 4336 4337 /** @todo NSTVMX: Setup VMX preemption timer */ 4338 /** @todo NSTVMX: TPR thresholding. */ 4339 4230 4340 iemVmxVmSucceed(pVCpu); 4231 4341 iemRegAddToRipAndClearRF(pVCpu, cbInstr); -
trunk/src/VBox/VMM/testcase/tstVMStruct.h
r74258 r74287 151 151 GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxRootMode); 152 152 GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxNonRootMode); 153 GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInterceptEvents); 153 154 GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pVmcsR0); 154 155 GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pVmcsR3);
Note:
See TracChangeset
for help on using the changeset viewer.