Changeset 74633 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Oct 6, 2018 6:29:16 AM (6 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
r74632 r74633 5203 5203 /* 5204 5204 * If the Mov-from-CR8 doesn't cause a VM-exit, bits 7:4 of the VTPR is copied 5205 * to bits 0:3 of the destination operand and bits 63:4 are cleared. 5205 * to bits 0:3 of the destination operand. Bits 63:4 of the destination operand 5206 * are cleared. 5206 5207 * 5207 * See Intel Spec. 2 5.3 "Changes To Instruction Behavior In VMX Non-root Operation".5208 * See Intel Spec. 29.3 "Virtualizing CR8-based TPR Accesses" 5208 5209 */ 5209 5210 if (IEM_VMX_IS_PROCCTLS_SET(pVCpu, VMX_PROC_CTLS_USE_TPR_SHADOW)) … … 5725 5726 } 5726 5727 5728 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 5729 if ( IEM_VMX_IS_NON_ROOT_MODE(pVCpu) 5730 && IEM_VMX_IS_PROCCTLS_SET(pVCpu, VMX_PROC_CTLS_USE_TPR_SHADOW)) 5731 { 5732 /* 5733 * If the Mov-to-CR8 doesn't cause a VM-exit, bits 0:3 of the source operand 5734 * is copied to bits 7:4 of the VTPR. Bits 0:3 and bits 31:8 of the VTPR are 5735 * cleared. Following this the processor performs TPR virtualization. 5736 * 5737 * See Intel Spec. 29.3 "Virtualizing CR8-based TPR Accesses" 5738 */ 5739 uint32_t const uVTpr = (uNewCrX & 0xf) << 4; 5740 iemVmxVirtApicWriteRaw32(pVCpu, uVTpr, XAPIC_OFF_TPR); 5741 rcStrict = iemVmxVmexitTprVirtualization(pVCpu, cbInstr); 5742 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE) 5743 return rcStrict; 5744 rcStrict = VINF_SUCCESS; 5745 break; 5746 } 5747 #endif 5748 5727 5749 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 5728 5750 if (CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu))) … … 5795 5817 { 5796 5818 case 0: 5797 case 4: 5798 rcStrict = iemVmxVmexitInstrMovToCr0Cr4(pVCpu, iCrReg, &uNewCrX, iGReg, cbInstr); 5799 break; 5800 case 3: 5801 rcStrict = iemVmxVmexitInstrMovToCr3(pVCpu, uNewCrX, iGReg, cbInstr); 5802 break; 5803 default: 5804 break; 5805 } 5806 5819 case 4: rcStrict = iemVmxVmexitInstrMovToCr0Cr4(pVCpu, iCrReg, &uNewCrX, iGReg, cbInstr); break; 5820 case 3: rcStrict = iemVmxVmexitInstrMovToCr3(pVCpu, uNewCrX, iGReg, cbInstr); break; 5821 case 8: rcStrict = iemVmxVmexitInstrMovToCr8(pVCpu, iGReg, cbInstr); break; 5822 } 5807 5823 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE) 5808 5824 return rcStrict; -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r74632 r74633 910 910 { 911 911 Assert(idxCr3Target < VMX_V_CR3_TARGET_COUNT); 912 913 912 uint8_t const uWidth = VMX_VMCS_ENC_WIDTH_NATURAL; 914 913 uint8_t const uType = VMX_VMCS_ENC_TYPE_CONTROL; … … 935 934 { 936 935 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uint32_t)); 937 938 936 uint8_t const *pbVirtApic = (const uint8_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 939 937 Assert(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage)); 940 uint32_t const uValue = *(const uint32_t *)(pbVirtApic + offReg); 941 return uValue; 938 uint32_t const uReg = *(const uint32_t *)(pbVirtApic + offReg); 939 return uReg; 940 } 941 942 943 /** 944 * Writes a 32-bit register to the virtual-APIC page at the given offset. 945 * 946 * @param pVCpu The cross context virtual CPU structure. 947 * @param uReg The register value to write. 948 * @param offReg The offset of the register being written. 949 */ 950 DECLINLINE(void) iemVmxVirtApicWriteRaw32(PVMCPU pVCpu, uint32_t uReg, uint8_t offReg) 951 { 952 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uint32_t)); 953 uint8_t *pbVirtApic = (uint8_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 954 Assert(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage)); 955 *(uint32_t *)(pbVirtApic + offReg) = uReg; 942 956 } 943 957 … … 1386 1400 * @param pVCpu The cross context virtual CPU structure. 1387 1401 * @param cbInstr The VM-exit instruction length in bytes. 1402 * 1403 * @remarks Callers may clear this field to 0. Hence, this function does not check 1404 * the validity of the instruction length. 1388 1405 */ 1389 1406 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitInstrLen(PVMCPU pVCpu, uint32_t cbInstr) … … 2083 2100 * Save guest RIP, RSP and RFLAGS. 2084 2101 * See Intel spec. 27.3.3 "Saving RIP, RSP and RFLAGS". 2085 */ 2102 * 2103 * For trap-like VM-exits we must advance the RIP by the length of the instruction. 2104 * Callers must pass the instruction length in the VM-exit instruction length 2105 * field though it is undefined for such VM-exits. After updating RIP here, we clear 2106 * the VM-exit instruction length field. 2107 * 2108 * See Intel spec. 27.1 "Architectural State Before A VM Exit" 2109 */ 2110 if (HMVmxIsTrapLikeVmexit(uExitReason)) 2111 { 2112 uint8_t const cbInstr = pVmcs->u32RoExitInstrLen; 2113 AssertMsg(cbInstr >= 1 && cbInstr <= 15, ("uReason=%u cbInstr=%u\n", uExitReason, cbInstr)); 2114 iemRegAddToRipAndClearRF(pVCpu, cbInstr); 2115 iemVmxVmcsSetExitInstrLen(pVCpu, 0 /* cbInstr */); 2116 } 2117 2086 2118 /* We don't support enclave mode yet. */ 2087 2119 pVmcs->u64GuestRip.u = pVCpu->cpum.GstCtx.rip; … … 3159 3191 * 3160 3192 * @returns VBox strict status code. 3193 * @retval VINF_VMX_INTERCEPT_NOT_ACTIVE if the Mov instruction did not cause a 3194 * VM-exit. 3161 3195 * @param pVCpu The cross context virtual CPU structure. 3162 3196 * @param iGReg The general register to which the CR8 value is being stored. … … 3185 3219 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_GENREG, iGReg); 3186 3220 return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo); 3221 } 3222 3223 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 3224 } 3225 3226 3227 /** 3228 * VMX VM-exit handler for VM-exits due to 'Mov CR8,GReg' (CR8 write). 3229 * 3230 * @returns VBox strict status code. 3231 * @param pVCpu The cross context virtual CPU structure. 3232 * @param iGReg The general register from which the CR8 value is being 3233 * loaded. 3234 * @param cbInstr The instruction length in bytes. 3235 */ 3236 IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrMovToCr8(PVMCPU pVCpu, uint8_t iGReg, uint8_t cbInstr) 3237 { 3238 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3239 Assert(pVmcs); 3240 3241 /* 3242 * If the CR8-load exiting control is set, we must cause a VM-exit. 3243 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally". 3244 */ 3245 if (pVmcs->u32ProcCtls & VMX_PROC_CTLS_CR8_LOAD_EXIT) 3246 { 3247 Log2(("mov_Cr_Rd: (CR8) Guest intercept -> VM-exit\n")); 3248 3249 VMXVEXITINFO ExitInfo; 3250 RT_ZERO(ExitInfo); 3251 ExitInfo.uReason = VMX_EXIT_MOV_CRX; 3252 ExitInfo.cbInstr = cbInstr; 3253 3254 ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, 8) /* CR8 */ 3255 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS, VMX_EXIT_QUAL_CRX_ACCESS_WRITE) 3256 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_GENREG, iGReg); 3257 return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo); 3258 } 3259 3260 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 3261 } 3262 3263 3264 /** 3265 * VMX VM-exit handler for TPR virtualization. 3266 * 3267 * @returns VBox strict status code. 3268 * @param pVCpu The cross context virtual CPU structure. 3269 * @param cbInstr The instruction length in bytes. 3270 */ 3271 IEM_STATIC VBOXSTRICTRC iemVmxVmexitTprVirtualization(PVMCPU pVCpu, uint8_t cbInstr) 3272 { 3273 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3274 Assert(pVmcs); 3275 3276 Assert(pVmcs->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW); 3277 Assert(!(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY)); /* We don't support virtual-interrupt delivery yet. */ 3278 3279 uint32_t const uTprThreshold = pVmcs->u32TprThreshold; 3280 uint32_t const uVTpr = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR); 3281 3282 /* 3283 * If the VTPR falls below the TPR threshold, we must cause a VM-exit. 3284 * See Intel spec. 29.1.2 "TPR Virtualization". 3285 */ 3286 if (((uVTpr >> 4) & 0xf) < uTprThreshold) 3287 { 3288 Log2(("tpr_virt: uVTpr=%u uTprThreshold=%u -> VM-exit\n", uVTpr, uTprThreshold)); 3289 3290 /* 3291 * This is a trap-like VM-exit. We pass the instruction length along in the VM-exit 3292 * instruction length field and let the VM-exit handler update the RIP when appropriate. 3293 * It will then clear the VM-exit instruction length field before completing the VM-exit. 3294 */ 3295 iemVmxVmcsSetExitInstrLen(pVCpu, cbInstr); 3296 return iemVmxVmexit(pVCpu, VMX_EXIT_TPR_BELOW_THRESHOLD); 3187 3297 } 3188 3298
Note:
See TracChangeset
for help on using the changeset viewer.