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

Commit 66336cab authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

KVM: x86: add support for emulating UMIP



The User-Mode Instruction Prevention feature present in recent Intel
processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and
str) from being executed with CPL > 0. Otherwise, a general protection
fault is issued.

UMIP instructions in general are also able to trigger vmexits, so we can
actually emulate UMIP on older processors.  This commit sets up the
infrastructure so that kvm-intel.ko and kvm-amd.ko can set the UMIP
feature bit for CPUID even if the feature is not actually available
in hardware.

Reviewed-by: default avatarWanpeng Li <wanpeng.li@hotmail.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent dd307d01
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -1017,6 +1017,7 @@ struct kvm_x86_ops {
	void (*handle_external_intr)(struct kvm_vcpu *vcpu);
	void (*handle_external_intr)(struct kvm_vcpu *vcpu);
	bool (*mpx_supported)(void);
	bool (*mpx_supported)(void);
	bool (*xsaves_supported)(void);
	bool (*xsaves_supported)(void);
	bool (*umip_emulated)(void);


	int (*check_nested_events)(struct kvm_vcpu *vcpu, bool external_intr);
	int (*check_nested_events)(struct kvm_vcpu *vcpu, bool external_intr);


+2 −0
Original line number Original line Diff line number Diff line
@@ -327,6 +327,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
	unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0;
	unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0;
	unsigned f_mpx = kvm_mpx_supported() ? F(MPX) : 0;
	unsigned f_mpx = kvm_mpx_supported() ? F(MPX) : 0;
	unsigned f_xsaves = kvm_x86_ops->xsaves_supported() ? F(XSAVES) : 0;
	unsigned f_xsaves = kvm_x86_ops->xsaves_supported() ? F(XSAVES) : 0;
	unsigned f_umip = kvm_x86_ops->umip_emulated() ? F(UMIP) : 0;


	/* cpuid 1.edx */
	/* cpuid 1.edx */
	const u32 kvm_cpuid_1_edx_x86_features =
	const u32 kvm_cpuid_1_edx_x86_features =
@@ -473,6 +474,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
			entry->ebx |= F(TSC_ADJUST);
			entry->ebx |= F(TSC_ADJUST);
			entry->ecx &= kvm_cpuid_7_0_ecx_x86_features;
			entry->ecx &= kvm_cpuid_7_0_ecx_x86_features;
			cpuid_mask(&entry->ecx, CPUID_7_ECX);
			cpuid_mask(&entry->ecx, CPUID_7_ECX);
			entry->ecx |= f_umip;
			/* PKU is not yet implemented for shadow paging. */
			/* PKU is not yet implemented for shadow paging. */
			if (!tdp_enabled || !boot_cpu_has(X86_FEATURE_OSPKE))
			if (!tdp_enabled || !boot_cpu_has(X86_FEATURE_OSPKE))
				entry->ecx &= ~F(PKU);
				entry->ecx &= ~F(PKU);
+6 −0
Original line number Original line Diff line number Diff line
@@ -5204,6 +5204,11 @@ static bool svm_xsaves_supported(void)
	return false;
	return false;
}
}


static bool svm_umip_emulated(void)
{
	return false;
}

static bool svm_has_wbinvd_exit(void)
static bool svm_has_wbinvd_exit(void)
{
{
	return true;
	return true;
@@ -5597,6 +5602,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
	.invpcid_supported = svm_invpcid_supported,
	.invpcid_supported = svm_invpcid_supported,
	.mpx_supported = svm_mpx_supported,
	.mpx_supported = svm_mpx_supported,
	.xsaves_supported = svm_xsaves_supported,
	.xsaves_supported = svm_xsaves_supported,
	.umip_emulated = svm_umip_emulated,


	.set_supported_cpuid = svm_set_supported_cpuid,
	.set_supported_cpuid = svm_set_supported_cpuid,


+6 −0
Original line number Original line Diff line number Diff line
@@ -9155,6 +9155,11 @@ static bool vmx_xsaves_supported(void)
		SECONDARY_EXEC_XSAVES;
		SECONDARY_EXEC_XSAVES;
}
}


static bool vmx_umip_emulated(void)
{
	return false;
}

static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
{
{
	u32 exit_intr_info;
	u32 exit_intr_info;
@@ -12170,6 +12175,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
	.handle_external_intr = vmx_handle_external_intr,
	.handle_external_intr = vmx_handle_external_intr,
	.mpx_supported = vmx_mpx_supported,
	.mpx_supported = vmx_mpx_supported,
	.xsaves_supported = vmx_xsaves_supported,
	.xsaves_supported = vmx_xsaves_supported,
	.umip_emulated = vmx_umip_emulated,


	.check_nested_events = vmx_check_nested_events,
	.check_nested_events = vmx_check_nested_events,