aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0072-KVM-SVM-Add-support-for-KVM_SEV_LAUNCH_START-command.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0072-KVM-SVM-Add-support-for-KVM_SEV_LAUNCH_START-command.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0072-KVM-SVM-Add-support-for-KVM_SEV_LAUNCH_START-command.patch248
1 files changed, 248 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0072-KVM-SVM-Add-support-for-KVM_SEV_LAUNCH_START-command.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0072-KVM-SVM-Add-support-for-KVM_SEV_LAUNCH_START-command.patch
new file mode 100644
index 00000000..1e7c7735
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0072-KVM-SVM-Add-support-for-KVM_SEV_LAUNCH_START-command.patch
@@ -0,0 +1,248 @@
+From fbb9ae1da5aef85415efc29ae3a90d3662cb937b Mon Sep 17 00:00:00 2001
+From: Sudheesh Mavila <sudheesh.mavila@amd.com>
+Date: Tue, 14 Aug 2018 22:14:32 +0530
+Subject: [PATCH 72/95] KVM: SVM: Add support for KVM_SEV_LAUNCH_START command
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+ commit 59414c989220825f970f38dbcbf11f18e817d73c
+
+ The KVM_SEV_LAUNCH_START command is used to create a memory encryption
+ context within the SEV firmware. In order to do so, the guest owner
+ should provide the guest's policy, its public Diffie-Hellman (PDH) key
+ and session information. The command implements the LAUNCH_START flow
+ defined in SEV spec Section 6.2.
+
+ Cc: Thomas Gleixner <tglx@linutronix.de>
+ Cc: Ingo Molnar <mingo@redhat.com>
+ Cc: "H. Peter Anvin" <hpa@zytor.com>
+ Cc: Paolo Bonzini <pbonzini@redhat.com>
+ Cc: "Radim Krčmář" <rkrcmar@redhat.com>
+ Cc: Joerg Roedel <joro@8bytes.org>
+ Cc: Borislav Petkov <bp@suse.de>
+ Cc: Tom Lendacky <thomas.lendacky@amd.com>
+ Cc: x86@kernel.org
+ Cc: kvm@vger.kernel.org
+ Cc: linux-kernel@vger.kernel.org
+ Improvements-by: Borislav Petkov <bp@suse.de>
+ Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
+ Reviewed-by: Borislav Petkov <bp@suse.de>
+
+Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
+---
+ arch/x86/include/asm/kvm_host.h | 2 +
+ arch/x86/kvm/svm.c | 157 +++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 158 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index 9cc7c30..03ba288 100755
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -755,6 +755,8 @@ enum kvm_irqchip_mode {
+ struct kvm_sev_info {
+ bool active; /* SEV enabled guest */
+ unsigned int asid; /* ASID used for this guest */
++ unsigned int handle; /* SEV firmware handle */
++ int fd; /* SEV device fd */
+ };
+
+ struct kvm_arch {
+diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
+index f4fc0b2..2f6aa95 100755
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -1469,8 +1469,10 @@ static void init_vmcb(struct vcpu_svm *svm)
+ svm->vmcb->control.int_ctl |= V_GIF_ENABLE_MASK;
+ }
+
+- if (sev_guest(svm->vcpu.kvm))
++ if (sev_guest(svm->vcpu.kvm)) {
+ svm->vmcb->control.nested_ctl |= SVM_NESTED_CTL_SEV_ENABLE;
++ clr_exception_intercept(svm, UD_VECTOR);
++ }
+
+ mark_all_dirty(svm->vmcb);
+
+@@ -1575,11 +1577,45 @@ static void sev_asid_free(struct kvm *kvm)
+ __sev_asid_free(sev->asid);
+ }
+
++static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
++{
++ struct sev_data_decommission *decommission;
++ struct sev_data_deactivate *data;
++
++ if (!handle)
++ return;
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return;
++
++ /* deactivate handle */
++ data->handle = handle;
++ sev_guest_deactivate(data, NULL);
++
++ wbinvd_on_all_cpus();
++ sev_guest_df_flush(NULL);
++ kfree(data);
++
++ decommission = kzalloc(sizeof(*decommission), GFP_KERNEL);
++ if (!decommission)
++ return;
++
++ /* decommission handle */
++ decommission->handle = handle;
++ sev_guest_decommission(decommission, NULL);
++
++ kfree(decommission);
++}
++
+ static void sev_vm_destroy(struct kvm *kvm)
+ {
++ struct kvm_sev_info *sev = &kvm->arch.sev_info;
++
+ if (!sev_guest(kvm))
+ return;
+
++ sev_unbind_asid(kvm, sev->handle);
+ sev_asid_free(kvm);
+ }
+
+@@ -5812,6 +5848,122 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
+ return ret;
+ }
+
++static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error)
++{
++ struct sev_data_activate *data;
++ int asid = sev_get_asid(kvm);
++ int ret;
++
++ wbinvd_on_all_cpus();
++
++ ret = sev_guest_df_flush(error);
++ if (ret)
++ return ret;
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ /* activate ASID on the given handle */
++ data->handle = handle;
++ data->asid = asid;
++ ret = sev_guest_activate(data, error);
++ kfree(data);
++
++ return ret;
++}
++
++static int sev_issue_cmd(int fd, int id, void *data, int *error)
++{
++ struct fd f;
++ int ret;
++
++ f = fdget(fd);
++ if (!f.file)
++ return -EBADF;
++
++ ret = sev_issue_cmd_external_user(f.file, id, data, error);
++
++ fdput(f);
++ return ret;
++}
++
++static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
++{
++ struct kvm_sev_info *sev = &kvm->arch.sev_info;
++ struct sev_data_launch_start *start;
++ struct kvm_sev_launch_start params;
++ void *dh_blob, *session_blob;
++ int *error = &argp->error;
++ int ret;
++
++ if (!sev_guest(kvm))
++ return -ENOTTY;
++
++ if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data, sizeof(params)))
++ return -EFAULT;
++
++ start = kzalloc(sizeof(*start), GFP_KERNEL);
++ if (!start)
++ return -ENOMEM;
++
++ dh_blob = NULL;
++ if (params.dh_uaddr) {
++ dh_blob = psp_copy_user_blob(params.dh_uaddr, params.dh_len);
++ if (IS_ERR(dh_blob)) {
++ ret = PTR_ERR(dh_blob);
++ goto e_free;
++ }
++
++ start->dh_cert_address = __sme_set(__pa(dh_blob));
++ start->dh_cert_len = params.dh_len;
++ }
++
++ session_blob = NULL;
++ if (params.session_uaddr) {
++ session_blob = psp_copy_user_blob(params.session_uaddr, params.session_len);
++ if (IS_ERR(session_blob)) {
++ ret = PTR_ERR(session_blob);
++ goto e_free_dh;
++ }
++
++ start->session_address = __sme_set(__pa(session_blob));
++ start->session_len = params.session_len;
++ }
++
++ start->handle = params.handle;
++ start->policy = params.policy;
++
++ /* create memory encryption context */
++ ret = sev_issue_cmd(argp->sev_fd, SEV_CMD_LAUNCH_START, start, error);
++ if (ret)
++ goto e_free_session;
++
++ /* Bind ASID to this guest */
++ ret = sev_bind_asid(kvm, start->handle, error);
++ if (ret)
++ goto e_free_session;
++
++ /* return handle to userspace */
++ params.handle = start->handle;
++ if (copy_to_user((void __user *)(uintptr_t)argp->data, &params, sizeof(params))) {
++ sev_unbind_asid(kvm, start->handle);
++ ret = -EFAULT;
++ goto e_free_session;
++ }
++
++ sev->handle = start->handle;
++ sev->fd = argp->sev_fd;
++
++e_free_session:
++ kfree(session_blob);
++e_free_dh:
++ kfree(dh_blob);
++e_free:
++ kfree(start);
++ return ret;
++}
++
+ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
+ {
+ struct kvm_sev_cmd sev_cmd;
+@@ -5829,6 +5981,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
+ case KVM_SEV_INIT:
+ r = sev_guest_init(kvm, &sev_cmd);
+ break;
++ case KVM_SEV_LAUNCH_START:
++ r = sev_launch_start(kvm, &sev_cmd);
++ break;
+ default:
+ r = -EINVAL;
+ goto out;
+--
+2.7.4
+