All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kai Huang <kaih.linux@gmail.com>
To: pbonzini@redhat.com, rkrcmar@redhat.com, kvm@vger.kernel.org
Subject: [PATCH 06/10] kvm: x86: add KVM_SET_CPUID2 SGX support
Date: Mon,  8 May 2017 17:24:29 +1200	[thread overview]
Message-ID: <20170508052434.3627-7-kai.huang@linux.intel.com> (raw)
In-Reply-To: <20170508052434.3627-1-kai.huang@linux.intel.com>

This patch adds SGX CPUID support for KVM_SET_CPUID2. Besides setting up
guest's SGX CPUID, guest's SGX is initialized in KVM_SET_CPUID2 as well.
This is because, to avoid adding a new IOCTL to set guest's EPC base & size,
we need to get such info from KVM_SET_CPUID2 (where userspace will setup
guest's EPC base & size), and guest's SGX can only be initialized after KVM
knows such info.

Initializing guest's SGX may fail, so kvm_x86_ops->cpuid_update is changed
to return integer to reflect whether guest's SGX is initialized successfully
or not. kvm_update_cpuid is also moved to be called before
kvm_x86_ops->cpuid_update, as guest's SGX CPUID.0x12.1 needs to depends on
vcpu->arch.guest_supported_xcr0 (which is set in kvm_update_cpuid).

Also a new kvm_x86_ops->vm_destroy is added for VMX, in which guest's SGX is
destroyed.

Signed-off-by: Kai Huang <kai.huang@linux.intel.com>
---
 arch/x86/include/asm/kvm_host.h |   2 +-
 arch/x86/kvm/cpuid.c            |   8 ++-
 arch/x86/kvm/cpuid.h            |  20 +++++++
 arch/x86/kvm/svm.c              |   6 ++-
 arch/x86/kvm/vmx.c              | 113 +++++++++++++++++++++++++++++++++++++++-
 5 files changed, 143 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d7254f36b17d..38cbb1eb652f 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -894,7 +894,7 @@ struct kvm_x86_ops {
 	void (*hardware_unsetup)(void);            /* __exit */
 	bool (*cpu_has_accelerated_tpr)(void);
 	bool (*cpu_has_high_real_mode_segbase)(void);
-	void (*cpuid_update)(struct kvm_vcpu *vcpu);
+	int (*cpuid_update)(struct kvm_vcpu *vcpu);
 
 	int (*vm_init)(struct kvm *kvm);
 	void (*vm_destroy)(struct kvm *kvm);
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index d2c396b0b32f..11a13afef373 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -220,8 +220,10 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
 	vcpu->arch.cpuid_nent = cpuid->nent;
 	cpuid_fix_nx_cap(vcpu);
 	kvm_apic_set_version(vcpu);
-	kvm_x86_ops->cpuid_update(vcpu);
 	r = kvm_update_cpuid(vcpu);
+	if (r)
+		goto out;
+	r = kvm_x86_ops->cpuid_update(vcpu);
 
 out:
 	vfree(cpuid_entries);
@@ -243,8 +245,10 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
 		goto out;
 	vcpu->arch.cpuid_nent = cpuid->nent;
 	kvm_apic_set_version(vcpu);
-	kvm_x86_ops->cpuid_update(vcpu);
 	r = kvm_update_cpuid(vcpu);
+	if (r)
+		goto out;
+	r = kvm_x86_ops->cpuid_update(vcpu);
 out:
 	return r;
 }
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index de658f4fa1c6..7d10f2884779 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -155,6 +155,26 @@ static inline bool guest_cpuid_has_rdtscp(struct kvm_vcpu *vcpu)
 }
 
 /*
+ * Only checks CPUID.0x7.0x0:EBX.SGX. SDM says if this bit is 1, logical
+ * processor supports SGX CPUID 0x12.
+ */
+static inline bool guest_cpuid_has_sgx(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
+	return best && (best->ebx & bit(X86_FEATURE_SGX));
+}
+
+static inline bool guest_cpuid_has_sgx_launch_control(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
+	return best && (best->ecx & bit(X86_FEATURE_SGX_LAUNCH_CONTROL));
+}
+
+/*
  * NRIPS is provided through cpuidfn 0x8000000a.edx bit 3
  */
 #define BIT_NRIPS	3
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 678b30d2a188..d5a5410ba623 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -4972,7 +4972,7 @@ static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
 	return 0;
 }
 
-static void svm_cpuid_update(struct kvm_vcpu *vcpu)
+static int svm_cpuid_update(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 	struct kvm_cpuid_entry2 *entry;
@@ -4981,11 +4981,13 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 	svm->nrips_enabled = !!guest_cpuid_has_nrips(&svm->vcpu);
 
 	if (!kvm_vcpu_apicv_active(vcpu))
-		return;
+		return 0;
 
 	entry = kvm_find_cpuid_entry(vcpu, 1, 0);
 	if (entry)
 		entry->ecx &= ~bit(X86_FEATURE_X2APIC);
+
+	return 0;
 }
 
 static int svm_set_supported_cpuid(u32 func, u32 index,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 31de95986dbd..3c1cc94e7e6d 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -9447,11 +9447,109 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)
 #undef cr4_fixed1_update
 }
 
-static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
+/* This should be called after vcpu's SGX CPUID has been properly setup */
+static void vmx_cpuid_get_sgx_cpuinfo(struct kvm_vcpu *vcpu, struct
+		sgx_cpuinfo *sgxinfo)
+{
+	struct kvm_cpuid_entry2 *best;
+	u64 base, size;
+
+	BUG_ON(!sgxinfo);
+
+	/* See comments in detect_sgx... */
+	memset(sgxinfo, 0, sizeof(struct sgx_cpuinfo));
+
+	best = kvm_find_cpuid_entry(vcpu, 0x12, 0);
+	if (!best)
+		goto not_supported;
+	if (!(best->eax & SGX_CAP_SGX1))
+		goto not_supported;
+
+	sgxinfo->cap = best->eax;
+	sgxinfo->miscselect = best->ebx;
+	sgxinfo->max_enclave_size32 = best->edx & 0xff;
+	sgxinfo->max_enclave_size64 = (best->edx & 0xff00) >> 8;
+
+	best = kvm_find_cpuid_entry(vcpu, 0x12, 1);
+	if (!best)
+		goto not_supported;
+
+	sgxinfo->secs_attr_bitmask[0] = best->eax;
+	sgxinfo->secs_attr_bitmask[1] = best->ebx;
+	sgxinfo->secs_attr_bitmask[2] = best->ecx;
+	sgxinfo->secs_attr_bitmask[3] = best->edx;
+
+	best = kvm_find_cpuid_entry(vcpu, 0x12, 2);
+	if (!(best->eax & 0x1) || !(best->ecx & 0x1))
+		goto not_supported;
+
+	base = (((u64)(best->ebx & 0xfffff)) << 32) | (best->eax & 0xfffff000);
+	size = (((u64)(best->edx & 0xfffff)) << 32) | (best->ecx & 0xfffff000);
+	if (!base || !size)
+		goto not_supported;
+
+	sgxinfo->epc_base = base;
+	sgxinfo->epc_size = size;
+
+	return;
+
+not_supported:
+	memset(sgxinfo, 0, sizeof(struct sgx_cpuinfo));
+}
+
+static int vmx_cpuid_update_sgx(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+	struct sgx_cpuinfo si;
+	int r;
+
+	/* Nothing to check if SGX is not enabled for guest */
+	if (!guest_cpuid_has_sgx(vcpu))
+		return 0;
+
+	/*
+	 * Update CPUID.0x12.0x1 according to vcpu->arch.guest_supported_xcr0,
+	 * which is calculated in kvm_update_cpuid. This is the reason we
+	 * change the order of kvm_x86_ops->cpuid_update and kvm_update_cpuid.
+	 */
+	best = kvm_find_cpuid_entry(vcpu, 0x12, 0x1);
+	if (!best)
+		return -EFAULT;
+	best->ecx &= (unsigned int)(vcpu->arch.guest_supported_xcr0 & 0xffffffff);
+	best->ecx |= 0x3;
+	best->edx &= (unsigned int)(vcpu->arch.guest_supported_xcr0 >> 32);
+
+	/*
+	 * Make sure all SGX CPUIDs are properly set in KVM_SET_CPUID2 from
+	 * userspace. vmx_cpuid_get_sgx_cpuinfo will report invalid SGX if
+	 * any SGX CPUID is not properly setup in KVM_SET_CPUID2.
+	 */
+	vmx_cpuid_get_sgx_cpuinfo(vcpu, &si);
+	if (!(si.cap & SGX_CAP_SGX1))
+		return -EFAULT;
+
+	/*
+	 * Initialize guest's SGX staff here. To avoid a new IOCTL to allow
+	 * userspace to pass guest's (virtual) EPC base and size to, KVM gets
+	 * such info from KVM_SET_CPUID2. Initializing guest's SGX here also
+	 * provides a way for KVM to check whether userspace did everything
+	 * right about SGX CPUID (ex, inconsistent SGX CPUID between vcpus
+	 * is passed to KVM). In case of any error, we return error to reflect
+	 * userspace did something wrong about CPUID.
+	 */
+	r = kvm_init_sgx(vcpu->kvm, &si);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int vmx_cpuid_update(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	u32 secondary_exec_ctl = vmx_secondary_exec_control(vmx);
+	int r = 0;
 
 	if (vmx_rdtscp_supported()) {
 		bool rdtscp_enabled = guest_cpuid_has_rdtscp(vcpu);
@@ -9491,6 +9589,12 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 
 	if (nested_vmx_allowed(vcpu))
 		nested_vmx_cr_fixed1_bits_update(vcpu);
+
+	r = vmx_cpuid_update_sgx(vcpu);
+	if (r)
+		return r;
+
+	return 0;
 }
 
 static int vmx_set_supported_cpuid(u32 func, u32 index,
@@ -11589,6 +11693,11 @@ static void vmx_setup_mce(struct kvm_vcpu *vcpu)
 			~FEATURE_CONTROL_LMCE;
 }
 
+static void vmx_vm_destroy(struct kvm *kvm)
+{
+	kvm_destroy_sgx(kvm);
+}
+
 static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
 	.cpu_has_kvm_support = cpu_has_kvm_support,
 	.disabled_by_bios = vmx_disabled_by_bios,
@@ -11600,6 +11709,8 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
 	.cpu_has_accelerated_tpr = report_flexpriority,
 	.cpu_has_high_real_mode_segbase = vmx_has_high_real_mode_segbase,
 
+	.vm_destroy = vmx_vm_destroy,
+
 	.vcpu_create = vmx_create_vcpu,
 	.vcpu_free = vmx_free_vcpu,
 	.vcpu_reset = vmx_vcpu_reset,
-- 
2.11.0

  parent reply	other threads:[~2017-05-08  5:25 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-08  5:24 [RFC PATCH 00/10] Basic KVM SGX Virtualization support Kai Huang
2017-05-08  5:24 ` [PATCH 01/10] x86: add SGX Launch Control definition to cpufeature Kai Huang
2017-05-08  5:24 ` [PATCH 02/10] kvm: vmx: add ENCLS VMEXIT detection Kai Huang
2017-05-08  5:24 ` [PATCH 03/10] kvm: vmx: detect presence of host SGX driver Kai Huang
2017-05-08  5:24 ` [PATCH 04/10] kvm: sgx: new functions to init and destory SGX for guest Kai Huang
2017-05-08  5:24 ` [PATCH 05/10] kvm: x86: add KVM_GET_SUPPORTED_CPUID SGX support Kai Huang
2017-05-08  5:24 ` Kai Huang [this message]
2017-05-08  5:24 ` [PATCH 07/10] kvm: vmx: add SGX IA32_FEATURE_CONTROL MSR emulation Kai Huang
2017-05-08  5:24 ` [PATCH 08/10] kvm: vmx: add guest's IA32_SGXLEPUBKEYHASHn runtime switch support Kai Huang
2017-05-12  0:32   ` Huang, Kai
2017-05-12  3:28     ` [intel-sgx-kernel-dev] " Andy Lutomirski
2017-05-12  4:56       ` Huang, Kai
2017-05-12  6:11         ` Andy Lutomirski
2017-05-12 18:48           ` Christopherson, Sean J
2017-05-12 20:50             ` Christopherson, Sean J
2017-05-16  0:59             ` Huang, Kai
2017-05-16  1:22             ` Huang, Kai
2017-05-16  0:48           ` Huang, Kai
2017-05-16 14:21             ` Paolo Bonzini
2017-05-18  7:54               ` Huang, Kai
2017-05-18  8:58                 ` Paolo Bonzini
2017-05-17  0:09             ` Andy Lutomirski
2017-05-18  7:45               ` Huang, Kai
2017-06-06 20:52                 ` Huang, Kai
2017-06-06 21:22                   ` Andy Lutomirski
2017-06-06 22:51                     ` Huang, Kai
2017-06-07 14:45                       ` Cohen, Haim
2017-06-08 12:31                   ` Jarkko Sakkinen
2017-06-08 23:47                     ` Huang, Kai
2017-06-08 23:53                       ` Andy Lutomirski
2017-06-09 15:38                         ` Cohen, Haim
2017-06-10 12:23                       ` Jarkko Sakkinen
2017-06-11 22:45                         ` Huang, Kai
2017-06-12  8:36                           ` Jarkko Sakkinen
2017-06-12  9:53                             ` Huang, Kai
2017-06-12 16:24                               ` Andy Lutomirski
2017-06-12 22:08                                 ` Huang, Kai
2017-06-12 23:00                                   ` Andy Lutomirski
2017-06-16  3:46                                     ` Huang, Kai
2017-06-16  4:11                                       ` Andy Lutomirski
2017-06-16  4:33                                         ` Huang, Kai
2017-06-16  9:34                                           ` Huang, Kai
2017-06-16 16:03                                           ` Andy Lutomirski
2017-06-16 16:25                                           ` Andy Lutomirski
2017-06-16 16:31                                             ` Christopherson, Sean J
2017-06-16 16:43                                               ` Andy Lutomirski
2017-06-13 18:57                               ` Jarkko Sakkinen
2017-06-13 19:05                                 ` Jarkko Sakkinen
2017-06-13 20:13                                   ` Sean Christopherson
2017-06-14  9:37                                     ` Jarkko Sakkinen
2017-06-14 15:11                                       ` Christopherson, Sean J
2017-06-14 17:03                                         ` Jarkko Sakkinen
2017-06-13 23:28                                 ` Huang, Kai
2017-06-14  9:44                                   ` Jarkko Sakkinen
2017-07-19 15:04           ` Sean Christopherson
2017-05-15 12:46       ` Jarkko Sakkinen
2017-05-15 23:56         ` Huang, Kai
2017-05-16 14:23           ` Paolo Bonzini
2017-05-17 14:21           ` Sean Christopherson
2017-05-18  8:14             ` Huang, Kai
2017-05-20 21:55               ` Andy Lutomirski
2017-05-23  5:43                 ` Huang, Kai
2017-05-23  5:55                   ` Huang, Kai
2017-05-23 16:34                   ` Andy Lutomirski
2017-05-23 16:43                     ` Paolo Bonzini
2017-05-24  8:20                       ` Huang, Kai
2017-05-20 13:23           ` Jarkko Sakkinen
2017-05-08  5:24 ` [PATCH 09/10] kvm: vmx: handle ENCLS VMEXIT Kai Huang
2017-05-08  8:08   ` Paolo Bonzini
2017-05-10  1:30     ` Huang, Kai
2017-05-08  5:24 ` [PATCH 10/10] kvm: vmx: handle VMEXIT from SGX Enclave Kai Huang
2017-05-08  8:22   ` Paolo Bonzini
2017-05-11  9:34     ` Huang, Kai
2017-06-19  5:02       ` Huang, Kai
2017-06-27 15:29         ` Radim Krčmář
2017-06-28 22:22           ` Huang, Kai
2017-05-08  5:24 ` [PATCH 11/11] kvm: vmx: workaround FEATURE_CONTROL[17] is not set by BIOS Kai Huang
2017-05-08  5:29   ` Huang, Kai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170508052434.3627-7-kai.huang@linux.intel.com \
    --to=kaih.linux@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.