diff options
author | Sheng Yang <sheng.yang@intel.com> | 2008-04-24 22:13:16 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-05-04 05:26:38 -0400 |
commit | d56f546db97795dca5aa575b00b0e9886895ac87 (patch) | |
tree | 4f92d84ddffde04031084447c048037558b994af /arch/x86/kvm/vmx.c | |
parent | afa26be86b65a7183ceac29bdf1f51d6fc6932f0 (diff) |
KVM: VMX: EPT Feature Detection
Signed-off-by: Sheng Yang <sheng.yang@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 8e5d6645b90d..d93250d11caa 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -42,6 +42,9 @@ module_param(enable_vpid, bool, 0); | |||
42 | static int flexpriority_enabled = 1; | 42 | static int flexpriority_enabled = 1; |
43 | module_param(flexpriority_enabled, bool, 0); | 43 | module_param(flexpriority_enabled, bool, 0); |
44 | 44 | ||
45 | static int enable_ept; | ||
46 | module_param(enable_ept, bool, 0); | ||
47 | |||
45 | struct vmcs { | 48 | struct vmcs { |
46 | u32 revision_id; | 49 | u32 revision_id; |
47 | u32 abort; | 50 | u32 abort; |
@@ -107,6 +110,11 @@ static struct vmcs_config { | |||
107 | u32 vmentry_ctrl; | 110 | u32 vmentry_ctrl; |
108 | } vmcs_config; | 111 | } vmcs_config; |
109 | 112 | ||
113 | struct vmx_capability { | ||
114 | u32 ept; | ||
115 | u32 vpid; | ||
116 | } vmx_capability; | ||
117 | |||
110 | #define VMX_SEGMENT_FIELD(seg) \ | 118 | #define VMX_SEGMENT_FIELD(seg) \ |
111 | [VCPU_SREG_##seg] = { \ | 119 | [VCPU_SREG_##seg] = { \ |
112 | .selector = GUEST_##seg##_SELECTOR, \ | 120 | .selector = GUEST_##seg##_SELECTOR, \ |
@@ -214,6 +222,32 @@ static inline bool cpu_has_vmx_virtualize_apic_accesses(void) | |||
214 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES); | 222 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES); |
215 | } | 223 | } |
216 | 224 | ||
225 | static inline int cpu_has_vmx_invept_individual_addr(void) | ||
226 | { | ||
227 | return (!!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT)); | ||
228 | } | ||
229 | |||
230 | static inline int cpu_has_vmx_invept_context(void) | ||
231 | { | ||
232 | return (!!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT)); | ||
233 | } | ||
234 | |||
235 | static inline int cpu_has_vmx_invept_global(void) | ||
236 | { | ||
237 | return (!!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT)); | ||
238 | } | ||
239 | |||
240 | static inline int cpu_has_vmx_ept(void) | ||
241 | { | ||
242 | return (vmcs_config.cpu_based_2nd_exec_ctrl & | ||
243 | SECONDARY_EXEC_ENABLE_EPT); | ||
244 | } | ||
245 | |||
246 | static inline int vm_need_ept(void) | ||
247 | { | ||
248 | return (cpu_has_vmx_ept() && enable_ept); | ||
249 | } | ||
250 | |||
217 | static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm) | 251 | static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm) |
218 | { | 252 | { |
219 | return ((cpu_has_vmx_virtualize_apic_accesses()) && | 253 | return ((cpu_has_vmx_virtualize_apic_accesses()) && |
@@ -985,7 +1019,7 @@ static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt, | |||
985 | static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | 1019 | static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) |
986 | { | 1020 | { |
987 | u32 vmx_msr_low, vmx_msr_high; | 1021 | u32 vmx_msr_low, vmx_msr_high; |
988 | u32 min, opt; | 1022 | u32 min, opt, min2, opt2; |
989 | u32 _pin_based_exec_control = 0; | 1023 | u32 _pin_based_exec_control = 0; |
990 | u32 _cpu_based_exec_control = 0; | 1024 | u32 _cpu_based_exec_control = 0; |
991 | u32 _cpu_based_2nd_exec_control = 0; | 1025 | u32 _cpu_based_2nd_exec_control = 0; |
@@ -1003,6 +1037,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
1003 | CPU_BASED_CR8_LOAD_EXITING | | 1037 | CPU_BASED_CR8_LOAD_EXITING | |
1004 | CPU_BASED_CR8_STORE_EXITING | | 1038 | CPU_BASED_CR8_STORE_EXITING | |
1005 | #endif | 1039 | #endif |
1040 | CPU_BASED_CR3_LOAD_EXITING | | ||
1041 | CPU_BASED_CR3_STORE_EXITING | | ||
1006 | CPU_BASED_USE_IO_BITMAPS | | 1042 | CPU_BASED_USE_IO_BITMAPS | |
1007 | CPU_BASED_MOV_DR_EXITING | | 1043 | CPU_BASED_MOV_DR_EXITING | |
1008 | CPU_BASED_USE_TSC_OFFSETING; | 1044 | CPU_BASED_USE_TSC_OFFSETING; |
@@ -1018,11 +1054,13 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
1018 | ~CPU_BASED_CR8_STORE_EXITING; | 1054 | ~CPU_BASED_CR8_STORE_EXITING; |
1019 | #endif | 1055 | #endif |
1020 | if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) { | 1056 | if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) { |
1021 | min = 0; | 1057 | min2 = 0; |
1022 | opt = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | | 1058 | opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
1023 | SECONDARY_EXEC_WBINVD_EXITING | | 1059 | SECONDARY_EXEC_WBINVD_EXITING | |
1024 | SECONDARY_EXEC_ENABLE_VPID; | 1060 | SECONDARY_EXEC_ENABLE_VPID | |
1025 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS2, | 1061 | SECONDARY_EXEC_ENABLE_EPT; |
1062 | if (adjust_vmx_controls(min2, opt2, | ||
1063 | MSR_IA32_VMX_PROCBASED_CTLS2, | ||
1026 | &_cpu_based_2nd_exec_control) < 0) | 1064 | &_cpu_based_2nd_exec_control) < 0) |
1027 | return -EIO; | 1065 | return -EIO; |
1028 | } | 1066 | } |
@@ -1031,6 +1069,16 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
1031 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) | 1069 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) |
1032 | _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW; | 1070 | _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW; |
1033 | #endif | 1071 | #endif |
1072 | if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) { | ||
1073 | /* CR3 accesses don't need to cause VM Exits when EPT enabled */ | ||
1074 | min &= ~(CPU_BASED_CR3_LOAD_EXITING | | ||
1075 | CPU_BASED_CR3_STORE_EXITING); | ||
1076 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS, | ||
1077 | &_cpu_based_exec_control) < 0) | ||
1078 | return -EIO; | ||
1079 | rdmsr(MSR_IA32_VMX_EPT_VPID_CAP, | ||
1080 | vmx_capability.ept, vmx_capability.vpid); | ||
1081 | } | ||
1034 | 1082 | ||
1035 | min = 0; | 1083 | min = 0; |
1036 | #ifdef CONFIG_X86_64 | 1084 | #ifdef CONFIG_X86_64 |
@@ -1638,6 +1686,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
1638 | CPU_BASED_CR8_LOAD_EXITING; | 1686 | CPU_BASED_CR8_LOAD_EXITING; |
1639 | #endif | 1687 | #endif |
1640 | } | 1688 | } |
1689 | if (!vm_need_ept()) | ||
1690 | exec_control |= CPU_BASED_CR3_STORE_EXITING | | ||
1691 | CPU_BASED_CR3_LOAD_EXITING; | ||
1641 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control); | 1692 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control); |
1642 | 1693 | ||
1643 | if (cpu_has_secondary_exec_ctrls()) { | 1694 | if (cpu_has_secondary_exec_ctrls()) { |
@@ -1647,6 +1698,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
1647 | ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; | 1698 | ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; |
1648 | if (vmx->vpid == 0) | 1699 | if (vmx->vpid == 0) |
1649 | exec_control &= ~SECONDARY_EXEC_ENABLE_VPID; | 1700 | exec_control &= ~SECONDARY_EXEC_ENABLE_VPID; |
1701 | if (!vm_need_ept()) | ||
1702 | exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; | ||
1650 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); | 1703 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); |
1651 | } | 1704 | } |
1652 | 1705 | ||