KVM: VMX: EPT Feature Detection
Signed-off-by: Sheng Yang <sheng.yang@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
This commit is contained in:
parent
afa26be86b
commit
d56f546db9
@ -42,6 +42,9 @@ module_param(enable_vpid, bool, 0);
|
|||||||
static int flexpriority_enabled = 1;
|
static int flexpriority_enabled = 1;
|
||||||
module_param(flexpriority_enabled, bool, 0);
|
module_param(flexpriority_enabled, bool, 0);
|
||||||
|
|
||||||
|
static int enable_ept;
|
||||||
|
module_param(enable_ept, bool, 0);
|
||||||
|
|
||||||
struct vmcs {
|
struct vmcs {
|
||||||
u32 revision_id;
|
u32 revision_id;
|
||||||
u32 abort;
|
u32 abort;
|
||||||
@ -107,6 +110,11 @@ static struct vmcs_config {
|
|||||||
u32 vmentry_ctrl;
|
u32 vmentry_ctrl;
|
||||||
} vmcs_config;
|
} vmcs_config;
|
||||||
|
|
||||||
|
struct vmx_capability {
|
||||||
|
u32 ept;
|
||||||
|
u32 vpid;
|
||||||
|
} vmx_capability;
|
||||||
|
|
||||||
#define VMX_SEGMENT_FIELD(seg) \
|
#define VMX_SEGMENT_FIELD(seg) \
|
||||||
[VCPU_SREG_##seg] = { \
|
[VCPU_SREG_##seg] = { \
|
||||||
.selector = GUEST_##seg##_SELECTOR, \
|
.selector = GUEST_##seg##_SELECTOR, \
|
||||||
@ -214,6 +222,32 @@ static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
|
|||||||
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
|
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int cpu_has_vmx_invept_individual_addr(void)
|
||||||
|
{
|
||||||
|
return (!!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cpu_has_vmx_invept_context(void)
|
||||||
|
{
|
||||||
|
return (!!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cpu_has_vmx_invept_global(void)
|
||||||
|
{
|
||||||
|
return (!!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cpu_has_vmx_ept(void)
|
||||||
|
{
|
||||||
|
return (vmcs_config.cpu_based_2nd_exec_ctrl &
|
||||||
|
SECONDARY_EXEC_ENABLE_EPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int vm_need_ept(void)
|
||||||
|
{
|
||||||
|
return (cpu_has_vmx_ept() && enable_ept);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
|
static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
|
||||||
{
|
{
|
||||||
return ((cpu_has_vmx_virtualize_apic_accesses()) &&
|
return ((cpu_has_vmx_virtualize_apic_accesses()) &&
|
||||||
@ -985,7 +1019,7 @@ static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt,
|
|||||||
static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
|
static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
|
||||||
{
|
{
|
||||||
u32 vmx_msr_low, vmx_msr_high;
|
u32 vmx_msr_low, vmx_msr_high;
|
||||||
u32 min, opt;
|
u32 min, opt, min2, opt2;
|
||||||
u32 _pin_based_exec_control = 0;
|
u32 _pin_based_exec_control = 0;
|
||||||
u32 _cpu_based_exec_control = 0;
|
u32 _cpu_based_exec_control = 0;
|
||||||
u32 _cpu_based_2nd_exec_control = 0;
|
u32 _cpu_based_2nd_exec_control = 0;
|
||||||
@ -1003,6 +1037,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
|
|||||||
CPU_BASED_CR8_LOAD_EXITING |
|
CPU_BASED_CR8_LOAD_EXITING |
|
||||||
CPU_BASED_CR8_STORE_EXITING |
|
CPU_BASED_CR8_STORE_EXITING |
|
||||||
#endif
|
#endif
|
||||||
|
CPU_BASED_CR3_LOAD_EXITING |
|
||||||
|
CPU_BASED_CR3_STORE_EXITING |
|
||||||
CPU_BASED_USE_IO_BITMAPS |
|
CPU_BASED_USE_IO_BITMAPS |
|
||||||
CPU_BASED_MOV_DR_EXITING |
|
CPU_BASED_MOV_DR_EXITING |
|
||||||
CPU_BASED_USE_TSC_OFFSETING;
|
CPU_BASED_USE_TSC_OFFSETING;
|
||||||
@ -1018,11 +1054,13 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
|
|||||||
~CPU_BASED_CR8_STORE_EXITING;
|
~CPU_BASED_CR8_STORE_EXITING;
|
||||||
#endif
|
#endif
|
||||||
if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
|
if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
|
||||||
min = 0;
|
min2 = 0;
|
||||||
opt = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
|
opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
|
||||||
SECONDARY_EXEC_WBINVD_EXITING |
|
SECONDARY_EXEC_WBINVD_EXITING |
|
||||||
SECONDARY_EXEC_ENABLE_VPID;
|
SECONDARY_EXEC_ENABLE_VPID |
|
||||||
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS2,
|
SECONDARY_EXEC_ENABLE_EPT;
|
||||||
|
if (adjust_vmx_controls(min2, opt2,
|
||||||
|
MSR_IA32_VMX_PROCBASED_CTLS2,
|
||||||
&_cpu_based_2nd_exec_control) < 0)
|
&_cpu_based_2nd_exec_control) < 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@ -1031,6 +1069,16 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
|
|||||||
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
|
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
|
||||||
_cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW;
|
_cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW;
|
||||||
#endif
|
#endif
|
||||||
|
if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) {
|
||||||
|
/* CR3 accesses don't need to cause VM Exits when EPT enabled */
|
||||||
|
min &= ~(CPU_BASED_CR3_LOAD_EXITING |
|
||||||
|
CPU_BASED_CR3_STORE_EXITING);
|
||||||
|
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
|
||||||
|
&_cpu_based_exec_control) < 0)
|
||||||
|
return -EIO;
|
||||||
|
rdmsr(MSR_IA32_VMX_EPT_VPID_CAP,
|
||||||
|
vmx_capability.ept, vmx_capability.vpid);
|
||||||
|
}
|
||||||
|
|
||||||
min = 0;
|
min = 0;
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
@ -1638,6 +1686,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
|
|||||||
CPU_BASED_CR8_LOAD_EXITING;
|
CPU_BASED_CR8_LOAD_EXITING;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (!vm_need_ept())
|
||||||
|
exec_control |= CPU_BASED_CR3_STORE_EXITING |
|
||||||
|
CPU_BASED_CR3_LOAD_EXITING;
|
||||||
vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
|
vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
|
||||||
|
|
||||||
if (cpu_has_secondary_exec_ctrls()) {
|
if (cpu_has_secondary_exec_ctrls()) {
|
||||||
@ -1647,6 +1698,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
|
|||||||
~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
||||||
if (vmx->vpid == 0)
|
if (vmx->vpid == 0)
|
||||||
exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
|
exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
|
||||||
|
if (!vm_need_ept())
|
||||||
|
exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
|
||||||
vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
|
vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#define CPU_BASED_MWAIT_EXITING 0x00000400
|
#define CPU_BASED_MWAIT_EXITING 0x00000400
|
||||||
#define CPU_BASED_RDPMC_EXITING 0x00000800
|
#define CPU_BASED_RDPMC_EXITING 0x00000800
|
||||||
#define CPU_BASED_RDTSC_EXITING 0x00001000
|
#define CPU_BASED_RDTSC_EXITING 0x00001000
|
||||||
|
#define CPU_BASED_CR3_LOAD_EXITING 0x00008000
|
||||||
|
#define CPU_BASED_CR3_STORE_EXITING 0x00010000
|
||||||
#define CPU_BASED_CR8_LOAD_EXITING 0x00080000
|
#define CPU_BASED_CR8_LOAD_EXITING 0x00080000
|
||||||
#define CPU_BASED_CR8_STORE_EXITING 0x00100000
|
#define CPU_BASED_CR8_STORE_EXITING 0x00100000
|
||||||
#define CPU_BASED_TPR_SHADOW 0x00200000
|
#define CPU_BASED_TPR_SHADOW 0x00200000
|
||||||
@ -49,6 +51,7 @@
|
|||||||
* Definitions of Secondary Processor-Based VM-Execution Controls.
|
* Definitions of Secondary Processor-Based VM-Execution Controls.
|
||||||
*/
|
*/
|
||||||
#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
|
#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
|
||||||
|
#define SECONDARY_EXEC_ENABLE_EPT 0x00000002
|
||||||
#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
|
#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
|
||||||
#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
|
#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
|
||||||
|
|
||||||
@ -100,10 +103,22 @@ enum vmcs_field {
|
|||||||
VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
|
VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
|
||||||
APIC_ACCESS_ADDR = 0x00002014,
|
APIC_ACCESS_ADDR = 0x00002014,
|
||||||
APIC_ACCESS_ADDR_HIGH = 0x00002015,
|
APIC_ACCESS_ADDR_HIGH = 0x00002015,
|
||||||
|
EPT_POINTER = 0x0000201a,
|
||||||
|
EPT_POINTER_HIGH = 0x0000201b,
|
||||||
|
GUEST_PHYSICAL_ADDRESS = 0x00002400,
|
||||||
|
GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
|
||||||
VMCS_LINK_POINTER = 0x00002800,
|
VMCS_LINK_POINTER = 0x00002800,
|
||||||
VMCS_LINK_POINTER_HIGH = 0x00002801,
|
VMCS_LINK_POINTER_HIGH = 0x00002801,
|
||||||
GUEST_IA32_DEBUGCTL = 0x00002802,
|
GUEST_IA32_DEBUGCTL = 0x00002802,
|
||||||
GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
|
GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
|
||||||
|
GUEST_PDPTR0 = 0x0000280a,
|
||||||
|
GUEST_PDPTR0_HIGH = 0x0000280b,
|
||||||
|
GUEST_PDPTR1 = 0x0000280c,
|
||||||
|
GUEST_PDPTR1_HIGH = 0x0000280d,
|
||||||
|
GUEST_PDPTR2 = 0x0000280e,
|
||||||
|
GUEST_PDPTR2_HIGH = 0x0000280f,
|
||||||
|
GUEST_PDPTR3 = 0x00002810,
|
||||||
|
GUEST_PDPTR3_HIGH = 0x00002811,
|
||||||
PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
|
PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
|
||||||
CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
|
CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
|
||||||
EXCEPTION_BITMAP = 0x00004004,
|
EXCEPTION_BITMAP = 0x00004004,
|
||||||
@ -226,6 +241,8 @@ enum vmcs_field {
|
|||||||
#define EXIT_REASON_MWAIT_INSTRUCTION 36
|
#define EXIT_REASON_MWAIT_INSTRUCTION 36
|
||||||
#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
|
#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
|
||||||
#define EXIT_REASON_APIC_ACCESS 44
|
#define EXIT_REASON_APIC_ACCESS 44
|
||||||
|
#define EXIT_REASON_EPT_VIOLATION 48
|
||||||
|
#define EXIT_REASON_EPT_MISCONFIG 49
|
||||||
#define EXIT_REASON_WBINVD 54
|
#define EXIT_REASON_WBINVD 54
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -316,6 +333,7 @@ enum vmcs_field {
|
|||||||
#define MSR_IA32_VMX_CR4_FIXED1 0x489
|
#define MSR_IA32_VMX_CR4_FIXED1 0x489
|
||||||
#define MSR_IA32_VMX_VMCS_ENUM 0x48a
|
#define MSR_IA32_VMX_VMCS_ENUM 0x48a
|
||||||
#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48b
|
#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48b
|
||||||
|
#define MSR_IA32_VMX_EPT_VPID_CAP 0x48c
|
||||||
|
|
||||||
#define MSR_IA32_FEATURE_CONTROL 0x3a
|
#define MSR_IA32_FEATURE_CONTROL 0x3a
|
||||||
#define MSR_IA32_FEATURE_CONTROL_LOCKED 0x1
|
#define MSR_IA32_FEATURE_CONTROL_LOCKED 0x1
|
||||||
@ -327,4 +345,11 @@ enum vmcs_field {
|
|||||||
#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1
|
#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1
|
||||||
#define VMX_VPID_EXTENT_ALL_CONTEXT 2
|
#define VMX_VPID_EXTENT_ALL_CONTEXT 2
|
||||||
|
|
||||||
|
#define VMX_EPT_EXTENT_INDIVIDUAL_ADDR 0
|
||||||
|
#define VMX_EPT_EXTENT_CONTEXT 1
|
||||||
|
#define VMX_EPT_EXTENT_GLOBAL 2
|
||||||
|
#define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24)
|
||||||
|
#define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25)
|
||||||
|
#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user