aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSheng Yang <sheng.yang@intel.com>2008-04-24 22:13:16 -0400
committerAvi Kivity <avi@qumranet.com>2008-05-04 05:26:38 -0400
commitd56f546db97795dca5aa575b00b0e9886895ac87 (patch)
tree4f92d84ddffde04031084447c048037558b994af
parentafa26be86b65a7183ceac29bdf1f51d6fc6932f0 (diff)
KVM: VMX: EPT Feature Detection
Signed-off-by: Sheng Yang <sheng.yang@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--arch/x86/kvm/vmx.c63
-rw-r--r--arch/x86/kvm/vmx.h25
2 files changed, 83 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);
42static int flexpriority_enabled = 1; 42static int flexpriority_enabled = 1;
43module_param(flexpriority_enabled, bool, 0); 43module_param(flexpriority_enabled, bool, 0);
44 44
45static int enable_ept;
46module_param(enable_ept, bool, 0);
47
45struct vmcs { 48struct 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
113struct 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
225static inline int cpu_has_vmx_invept_individual_addr(void)
226{
227 return (!!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT));
228}
229
230static inline int cpu_has_vmx_invept_context(void)
231{
232 return (!!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT));
233}
234
235static inline int cpu_has_vmx_invept_global(void)
236{
237 return (!!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT));
238}
239
240static inline int cpu_has_vmx_ept(void)
241{
242 return (vmcs_config.cpu_based_2nd_exec_ctrl &
243 SECONDARY_EXEC_ENABLE_EPT);
244}
245
246static inline int vm_need_ept(void)
247{
248 return (cpu_has_vmx_ept() && enable_ept);
249}
250
217static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm) 251static 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,
985static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) 1019static __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
diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h
index 5dff4606b988..5f7fdc965d39 100644
--- a/arch/x86/kvm/vmx.h
+++ b/arch/x86/kvm/vmx.h
@@ -35,6 +35,8 @@
35#define CPU_BASED_MWAIT_EXITING 0x00000400 35#define CPU_BASED_MWAIT_EXITING 0x00000400
36#define CPU_BASED_RDPMC_EXITING 0x00000800 36#define CPU_BASED_RDPMC_EXITING 0x00000800
37#define CPU_BASED_RDTSC_EXITING 0x00001000 37#define CPU_BASED_RDTSC_EXITING 0x00001000
38#define CPU_BASED_CR3_LOAD_EXITING 0x00008000
39#define CPU_BASED_CR3_STORE_EXITING 0x00010000
38#define CPU_BASED_CR8_LOAD_EXITING 0x00080000 40#define CPU_BASED_CR8_LOAD_EXITING 0x00080000
39#define CPU_BASED_CR8_STORE_EXITING 0x00100000 41#define CPU_BASED_CR8_STORE_EXITING 0x00100000
40#define CPU_BASED_TPR_SHADOW 0x00200000 42#define CPU_BASED_TPR_SHADOW 0x00200000
@@ -49,6 +51,7 @@
49 * Definitions of Secondary Processor-Based VM-Execution Controls. 51 * Definitions of Secondary Processor-Based VM-Execution Controls.
50 */ 52 */
51#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 53#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
54#define SECONDARY_EXEC_ENABLE_EPT 0x00000002
52#define SECONDARY_EXEC_ENABLE_VPID 0x00000020 55#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
53#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040 56#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
54 57
@@ -100,10 +103,22 @@ enum vmcs_field {
100 VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013, 103 VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
101 APIC_ACCESS_ADDR = 0x00002014, 104 APIC_ACCESS_ADDR = 0x00002014,
102 APIC_ACCESS_ADDR_HIGH = 0x00002015, 105 APIC_ACCESS_ADDR_HIGH = 0x00002015,
106 EPT_POINTER = 0x0000201a,
107 EPT_POINTER_HIGH = 0x0000201b,
108 GUEST_PHYSICAL_ADDRESS = 0x00002400,
109 GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
103 VMCS_LINK_POINTER = 0x00002800, 110 VMCS_LINK_POINTER = 0x00002800,
104 VMCS_LINK_POINTER_HIGH = 0x00002801, 111 VMCS_LINK_POINTER_HIGH = 0x00002801,
105 GUEST_IA32_DEBUGCTL = 0x00002802, 112 GUEST_IA32_DEBUGCTL = 0x00002802,
106 GUEST_IA32_DEBUGCTL_HIGH = 0x00002803, 113 GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
114 GUEST_PDPTR0 = 0x0000280a,
115 GUEST_PDPTR0_HIGH = 0x0000280b,
116 GUEST_PDPTR1 = 0x0000280c,
117 GUEST_PDPTR1_HIGH = 0x0000280d,
118 GUEST_PDPTR2 = 0x0000280e,
119 GUEST_PDPTR2_HIGH = 0x0000280f,
120 GUEST_PDPTR3 = 0x00002810,
121 GUEST_PDPTR3_HIGH = 0x00002811,
107 PIN_BASED_VM_EXEC_CONTROL = 0x00004000, 122 PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
108 CPU_BASED_VM_EXEC_CONTROL = 0x00004002, 123 CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
109 EXCEPTION_BITMAP = 0x00004004, 124 EXCEPTION_BITMAP = 0x00004004,
@@ -226,6 +241,8 @@ enum vmcs_field {
226#define EXIT_REASON_MWAIT_INSTRUCTION 36 241#define EXIT_REASON_MWAIT_INSTRUCTION 36
227#define EXIT_REASON_TPR_BELOW_THRESHOLD 43 242#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
228#define EXIT_REASON_APIC_ACCESS 44 243#define EXIT_REASON_APIC_ACCESS 44
244#define EXIT_REASON_EPT_VIOLATION 48
245#define EXIT_REASON_EPT_MISCONFIG 49
229#define EXIT_REASON_WBINVD 54 246#define EXIT_REASON_WBINVD 54
230 247
231/* 248/*
@@ -316,6 +333,7 @@ enum vmcs_field {
316#define MSR_IA32_VMX_CR4_FIXED1 0x489 333#define MSR_IA32_VMX_CR4_FIXED1 0x489
317#define MSR_IA32_VMX_VMCS_ENUM 0x48a 334#define MSR_IA32_VMX_VMCS_ENUM 0x48a
318#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48b 335#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48b
336#define MSR_IA32_VMX_EPT_VPID_CAP 0x48c
319 337
320#define MSR_IA32_FEATURE_CONTROL 0x3a 338#define MSR_IA32_FEATURE_CONTROL 0x3a
321#define MSR_IA32_FEATURE_CONTROL_LOCKED 0x1 339#define MSR_IA32_FEATURE_CONTROL_LOCKED 0x1
@@ -327,4 +345,11 @@ enum vmcs_field {
327#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1 345#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1
328#define VMX_VPID_EXTENT_ALL_CONTEXT 2 346#define VMX_VPID_EXTENT_ALL_CONTEXT 2
329 347
348#define VMX_EPT_EXTENT_INDIVIDUAL_ADDR 0
349#define VMX_EPT_EXTENT_CONTEXT 1
350#define VMX_EPT_EXTENT_GLOBAL 2
351#define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24)
352#define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25)
353#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)
354
330#endif 355#endif