From: Kai Huang <kai.huang@intel.com>
To: kvm@vger.kernel.org, linux-sgx@vger.kernel.org
Cc: seanjc@google.com, pbonzini@redhat.com, bp@alien8.de,
jarkko@kernel.org, dave.hansen@intel.com, luto@kernel.org,
rick.p.edgecombe@intel.com, haitao.huang@intel.com,
Kai Huang <kai.huang@intel.com>
Subject: [PATCH v4 09/11] KVM: VMX: Add ENCLS[EINIT] handler to support SGX Launch Control (LC)
Date: Thu, 8 Apr 2021 08:49:33 +1200 [thread overview]
Message-ID: <6bf731227ac8d75696fa974846c3c2c64eadae7b.1617825858.git.kai.huang@intel.com> (raw)
In-Reply-To: <cover.1617825858.git.kai.huang@intel.com>
From: Sean Christopherson <sean.j.christopherson@intel.com>
Add a VM-Exit handler to trap-and-execute EINIT when SGX LC is enabled
in the host. When SGX LC is enabled, the host kernel may rewrite the
hardware values at will, e.g. to launch enclaves with different signers,
thus KVM needs to intercept EINIT to ensure it is executed with the
correct LE hash (even if the guest sees a hardwired hash).
Switching the LE hash MSRs on VM-Enter/VM-Exit is not a viable option as
writing the MSRs is prohibitively expensive, e.g. on SKL hardware each
WRMSR is ~400 cycles. And because EINIT takes tens of thousands of
cycles to execute, the ~1500 cycle overhead to trap-and-execute EINIT is
unlikely to be noticed by the guest, let alone impact its overall SGX
performance.
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Kai Huang <kai.huang@intel.com>
---
arch/x86/kvm/vmx/sgx.c | 63 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c
index fb729e5c6949..6c96f87710f8 100644
--- a/arch/x86/kvm/vmx/sgx.c
+++ b/arch/x86/kvm/vmx/sgx.c
@@ -286,6 +286,67 @@ static int handle_encls_ecreate(struct kvm_vcpu *vcpu)
return r;
}
+static int handle_encls_einit(struct kvm_vcpu *vcpu)
+{
+ unsigned long sig_hva, secs_hva, token_hva, rflags;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ gva_t sig_gva, secs_gva, token_gva;
+ gpa_t sig_gpa, secs_gpa, token_gpa;
+ int ret, trapnr;
+
+ if (sgx_get_encls_gva(vcpu, kvm_rbx_read(vcpu), 1808, 4096, &sig_gva) ||
+ sgx_get_encls_gva(vcpu, kvm_rcx_read(vcpu), 4096, 4096, &secs_gva) ||
+ sgx_get_encls_gva(vcpu, kvm_rdx_read(vcpu), 304, 512, &token_gva))
+ return 1;
+
+ /*
+ * Translate the SIGSTRUCT, SECS and TOKEN pointers from GVA to GPA.
+ * Resume the guest on failure to inject a #PF.
+ */
+ if (sgx_gva_to_gpa(vcpu, sig_gva, false, &sig_gpa) ||
+ sgx_gva_to_gpa(vcpu, secs_gva, true, &secs_gpa) ||
+ sgx_gva_to_gpa(vcpu, token_gva, false, &token_gpa))
+ return 1;
+
+ /*
+ * ...and then to HVA. The order of accesses isn't architectural, i.e.
+ * KVM doesn't have to fully process one address at a time. Exit to
+ * userspace if a GPA is invalid. Note, all structures are aligned and
+ * cannot split pages.
+ */
+ if (sgx_gpa_to_hva(vcpu, sig_gpa, &sig_hva) ||
+ sgx_gpa_to_hva(vcpu, secs_gpa, &secs_hva) ||
+ sgx_gpa_to_hva(vcpu, token_gpa, &token_hva))
+ return 0;
+
+ ret = sgx_virt_einit((void __user *)sig_hva, (void __user *)token_hva,
+ (void __user *)secs_hva,
+ vmx->msr_ia32_sgxlepubkeyhash, &trapnr);
+
+ if (ret == -EFAULT)
+ return sgx_inject_fault(vcpu, secs_gva, trapnr);
+
+ /*
+ * sgx_virt_einit() returns -EINVAL when access_ok() fails on
+ * @sig_hva, @token_hva or @secs_hva. It's unexpected and is kernel bug.
+ * Just return.
+ */
+ if (ret < 0)
+ return ret;
+
+ rflags = vmx_get_rflags(vcpu) & ~(X86_EFLAGS_CF | X86_EFLAGS_PF |
+ X86_EFLAGS_AF | X86_EFLAGS_SF |
+ X86_EFLAGS_OF);
+ if (ret)
+ rflags |= X86_EFLAGS_ZF;
+ else
+ rflags &= ~X86_EFLAGS_ZF;
+ vmx_set_rflags(vcpu, rflags);
+
+ kvm_rax_write(vcpu, ret);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
static inline bool encls_leaf_enabled_in_guest(struct kvm_vcpu *vcpu, u32 leaf)
{
if (!enable_sgx || !guest_cpuid_has(vcpu, X86_FEATURE_SGX))
@@ -318,6 +379,8 @@ int handle_encls(struct kvm_vcpu *vcpu)
} else {
if (leaf == ECREATE)
return handle_encls_ecreate(vcpu);
+ if (leaf == EINIT)
+ return handle_encls_einit(vcpu);
WARN(1, "KVM: unexpected exit on ENCLS[%u]", leaf);
vcpu->run->exit_reason = KVM_EXIT_UNKNOWN;
vcpu->run->hw.hardware_exit_reason = EXIT_REASON_ENCLS;
--
2.30.2
next prev parent reply other threads:[~2021-04-07 20:50 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-07 20:49 [PATCH v4 00/11] KVM SGX virtualization support (KVM part) Kai Huang
2021-04-07 20:49 ` [PATCH v4 01/11] KVM: x86: Export kvm_mmu_gva_to_gpa_{read,write}() for SGX (VMX) Kai Huang
2021-04-07 20:49 ` [PATCH v4 02/11] KVM: x86: Define new #PF SGX error code bit Kai Huang
2021-04-07 20:49 ` [PATCH v4 03/11] KVM: x86: Add support for reverse CPUID lookup of scattered features Kai Huang
2021-04-07 20:49 ` [PATCH v4 04/11] KVM: x86: Add reverse-CPUID lookup support for scattered SGX features Kai Huang
2021-04-07 20:49 ` [PATCH v4 05/11] KVM: VMX: Add basic handling of VM-Exit from SGX enclave Kai Huang
2021-04-07 20:49 ` [PATCH v4 06/11] KVM: VMX: Frame in ENCLS handler for SGX virtualization Kai Huang
2021-04-07 22:16 ` Sean Christopherson
2021-04-07 22:33 ` Kai Huang
2021-04-07 22:35 ` Sean Christopherson
2021-04-07 22:44 ` Kai Huang
2021-04-07 22:47 ` Sean Christopherson
2021-04-07 22:59 ` Kai Huang
2021-04-07 20:49 ` [PATCH v4 07/11] KVM: VMX: Add SGX ENCLS[ECREATE] handler to enforce CPUID restrictions Kai Huang
2021-04-07 21:52 ` Sean Christopherson
2021-04-07 21:58 ` Kai Huang
2021-04-07 22:04 ` Sean Christopherson
2021-04-07 22:16 ` Kai Huang
2021-04-07 22:10 ` Sean Christopherson
2021-04-07 22:15 ` Kai Huang
2021-04-07 20:49 ` [PATCH v4 08/11] KVM: VMX: Add emulation of SGX Launch Control LE hash MSRs Kai Huang
2021-04-07 20:49 ` Kai Huang [this message]
2021-04-07 20:49 ` [PATCH v4 10/11] KVM: VMX: Enable SGX virtualization for SGX1, SGX2 and LC Kai Huang
2021-04-07 20:49 ` [PATCH v4 11/11] KVM: x86: Add capability to grant VM access to privileged SGX attribute Kai Huang
2021-04-07 23:08 ` [PATCH v4 00/11] KVM SGX virtualization support (KVM part) Kai Huang
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=6bf731227ac8d75696fa974846c3c2c64eadae7b.1617825858.git.kai.huang@intel.com \
--to=kai.huang@intel.com \
--cc=bp@alien8.de \
--cc=dave.hansen@intel.com \
--cc=haitao.huang@intel.com \
--cc=jarkko@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-sgx@vger.kernel.org \
--cc=luto@kernel.org \
--cc=pbonzini@redhat.com \
--cc=rick.p.edgecombe@intel.com \
--cc=seanjc@google.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.