Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d56f546d authored by Sheng Yang's avatar Sheng Yang Committed by Avi Kivity
Browse files

KVM: VMX: EPT Feature Detection



Signed-off-by: default avatarSheng Yang <sheng.yang@intel.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent afa26be8
Loading
Loading
Loading
Loading
+58 −5
Original line number Original line Diff line number Diff line
@@ -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);
	}
	}


+25 −0
Original line number Original line Diff line number Diff line
@@ -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