Changeset 79648 in vbox
- Timestamp:
- Jul 10, 2019 4:54:24 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r79637 r79648 924 924 925 925 926 #if 0 927 /** 928 * Checks whether one of the given Processor-based VM-execution controls are set. 929 * 930 * @returns @c true if set, @c false otherwise. 926 /** 927 * Sets the given Processor-based VM-execution controls. 928 * 929 * @param pVmxTransient The VMX-transient structure. 930 * @param uProcCtls The Processor-based VM-execution controls to set. 931 */ 932 static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls) 933 { 934 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 935 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls) 936 { 937 pVmcsInfo->u32ProcCtls |= uProcCtls; 938 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls); 939 AssertRC(rc); 940 } 941 } 942 943 944 /** 945 * Removes the given Processor-based VM-execution controls. 946 * 931 947 * @param pVCpu The cross context virtual CPU structure. 932 948 * @param pVmxTransient The VMX-transient structure. 933 * @param uProcCtls The Processor-based VM-execution controls to check. 934 * 935 * @remarks This will not check merged controls when executing a nested-guest 936 * but the original control specified by the guest hypervisor. 937 */ 938 static bool hmR0VmxIsProcCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uProcCtls) 939 { 940 if (!pVmxTransient->fIsNestedGuest) 941 { 942 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 943 return RT_BOOL(pVmcsInfo->u32ProcCtls & uProcCtls); 944 } 945 return CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls); 946 } 947 948 949 /** 950 * Checks whether one of the given Secondary Processor-based VM-execution controls 951 * are set. 952 * 953 * @returns @c true if set, @c false otherwise. 954 * @param pVCpu The cross context virtual CPU structure. 955 * @param pVmxTransient The VMX-transient structure. 956 * @param uProcCtls2 The Secondary Processor-based VM-execution controls to 957 * check. 958 * 959 * @remarks This will not check merged controls when executing a nested-guest 960 * but the original control specified by the guest hypervisor. 961 */ 962 static bool hmR0VmxIsProcCtls2Set(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uProcCtls2) 963 { 964 if (!pVmxTransient->fIsNestedGuest) 965 { 966 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 967 return RT_BOOL(pVmcsInfo->u32ProcCtls2 & uProcCtls2); 968 } 969 return CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls2); 970 } 971 972 973 /** 974 * Checks whether one of the given VM-entry controls are set. 975 * 976 * @returns @c true if set, @c false otherwise. 977 * @param pVCpu The cross context virtual CPU structure. 978 * @param pVmxTransient The VMX-transient structure. 979 * @param uEntryCtls The VM-entry controls to check. 980 * 981 * @remarks This will not check merged controls when executing a nested-guest 982 * but the original control specified by the guest hypervisor. 983 */ 984 static bool hmR0VmxIsEntryCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uEntryCtls) 985 { 986 if (!pVmxTransient->fIsNestedGuest) 987 { 988 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 989 return RT_BOOL(pVmcsInfo->u32EntryCtls & uEntryCtls); 990 } 991 return CPUMIsGuestVmxEntryCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uEntryCtls); 992 } 993 994 995 /** 996 * Checks whether one of the given VM-exit controls are set. 997 * 998 * @returns @c true if set, @c false otherwise. 999 * @param pVCpu The cross context virtual CPU structure. 1000 * @param pVmxTransient The VMX-transient structure. 1001 * @param uExitCtls The VM-exit controls to check. 1002 * 1003 * @remarks This will not check merged controls when executing a nested-guest 1004 * but the original control specified by the guest hypervisor. 1005 */ 1006 static bool hmR0VmxIsExitCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uExitCtls) 1007 { 1008 if (!pVmxTransient->fIsNestedGuest) 1009 { 1010 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 1011 return RT_BOOL(pVmcsInfo->u32ExitCtls & uExitCtls); 1012 } 1013 return CPUMIsGuestVmxExitCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uExitCtls); 1014 } 949 * @param uProcCtls The Processor-based VM-execution controls to remove. 950 * 951 * @remarks When executing a nested-guest, this will not remove any of the specified 952 * controls if the guest hypervisor has set any one of them. 953 */ 954 static void hmR0VmxRemoveProcCtlsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls) 955 { 956 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 957 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest 958 ? true 959 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT); 960 #else 961 bool const fRemoveCtls = true; 1015 962 #endif 963 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 964 if ( fRemoveCtls 965 && (pVmcsInfo->u32ProcCtls & uProcCtls)) 966 { 967 pVmcsInfo->u32ProcCtls &= ~uProcCtls; 968 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls); 969 AssertRC(rc); 970 } 971 } 972 973 974 /** 975 * Sets the TSC offset for the current VMCS. 976 * 977 * @param uTscOffset The TSC offset to set. 978 * @param pVmcsInfo The VMCS info. object. 979 */ 980 static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset) 981 { 982 if (pVmcsInfo->u64TscOffset != uTscOffset) 983 { 984 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset); 985 AssertRC(rc); 986 pVmcsInfo->u64TscOffset = uTscOffset; 987 } 988 } 1016 989 1017 990 … … 7524 7497 } 7525 7498 7526 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;7527 7499 if ( fOffsettedTsc 7528 7500 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit)) … … 7530 7502 if (pVmxTransient->fIsNestedGuest) 7531 7503 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset); 7532 if (pVmcsInfo->u64TscOffset != uTscOffset) 7533 { 7534 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset); 7535 AssertRC(rc); 7536 pVmcsInfo->u64TscOffset = uTscOffset; 7537 } 7538 7539 if (uProcCtls & VMX_PROC_CTLS_RDTSC_EXIT) 7540 { 7541 uProcCtls &= ~VMX_PROC_CTLS_RDTSC_EXIT; 7542 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls); 7543 AssertRC(rc); 7544 pVmcsInfo->u32ProcCtls = uProcCtls; 7545 } 7546 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset); 7504 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset); 7505 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT); 7547 7506 } 7548 7507 else 7549 7508 { 7550 7509 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */ 7551 if (!(uProcCtls & VMX_PROC_CTLS_RDTSC_EXIT)) 7552 { 7553 uProcCtls |= VMX_PROC_CTLS_RDTSC_EXIT; 7554 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls); 7555 AssertRC(rc); 7556 pVmcsInfo->u32ProcCtls = uProcCtls; 7557 } 7558 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept); 7510 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT); 7559 7511 } 7560 7512 } … … 9345 9297 /* 9346 9298 * If we eventually support nested-guest execution without unrestricted guest execution, 9347 * we should clearfInterceptEvents here.9299 * we should set fInterceptEvents here. 9348 9300 */ 9349 9301 Assert(!pVmxTransient->fIsNestedGuest); … … 9377 9329 * Update guest CR2 if this is a page-fault. 9378 9330 */ 9379 if ( VMX_ENTRY_INT_INFO_TYPE(u32IntInfo) == VMX_EXIT_INT_INFO_TYPE_HW_XCPT 9380 && uVector == X86_XCPT_PF) 9331 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo)) 9381 9332 pCtx->cr2 = GCPtrFault; 9382 9333 … … 10023 9974 { 10024 9975 #define HMVMX_ERROR_BREAK(err) { uError = (err); break; } 10025 #define HMVMX_CHECK_BREAK(expr, err) if (!(expr)) { \ 10026 uError = (err); \ 10027 break; \ 10028 } else do { } while (0) 9976 #define HMVMX_CHECK_BREAK(expr, err) do { \ 9977 if (!(expr)) { uError = (err); break; } \ 9978 } while (0) 10029 9979 10030 9980 int rc; … … 10135 10085 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo); 10136 10086 AssertRCBreak(rc); 10137 if ( VMX_ENTRY_INT_INFO_IS_VALID(u32EntryInfo) 10138 && VMX_ENTRY_INT_INFO_TYPE(u32EntryInfo) == VMX_EXIT_INT_INFO_TYPE_EXT_INT) 10139 { 10087 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo)) 10140 10088 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID); 10141 }10142 10089 10143 10090 /* … … 10500 10447 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI), 10501 10448 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID); 10502 if (VMX_ENTRY_INT_INFO_IS_VALID(u32EntryInfo)) 10503 { 10504 if (VMX_ENTRY_INT_INFO_TYPE(u32EntryInfo) == VMX_EXIT_INT_INFO_TYPE_EXT_INT) 10505 { 10506 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI) 10507 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS), 10508 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID); 10509 } 10510 else if (VMX_ENTRY_INT_INFO_TYPE(u32EntryInfo) == VMX_EXIT_INT_INFO_TYPE_NMI) 10511 { 10512 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS), 10513 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID); 10514 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI), 10515 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID); 10516 } 10449 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo)) 10450 { 10451 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI) 10452 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS), 10453 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID); 10454 } 10455 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo)) 10456 { 10457 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS), 10458 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID); 10459 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI), 10460 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID); 10517 10461 } 10518 10462 /** @todo Assumes the processor is not in SMM. */ … … 10523 10467 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID); 10524 10468 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI) 10525 && VMX_ENTRY_INT_INFO_IS_VALID(u32EntryInfo) 10526 && VMX_ENTRY_INT_INFO_TYPE(u32EntryInfo) == VMX_EXIT_INT_INFO_TYPE_NMI) 10469 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo)) 10527 10470 { 10528 10471 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), … … 11324 11267 } 11325 11268 11269 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */ 11270 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT); 11271 if (!fIsRdtscIntercepted) 11272 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset); 11273 else 11274 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept); 11275 11326 11276 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */ 11327 11277 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */ … … 11343 11293 */ 11344 11294 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP) 11345 && ! (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))11295 && !fIsRdtscIntercepted) 11346 11296 { 11347 11297 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
Note:
See TracChangeset
for help on using the changeset viewer.