lkml.org 
[lkml]   [2020]   [Apr]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH v6 04/14] KVM: SVM: Add support for KVM_SEV_RECEIVE_START command
    On 2020-03-30 06:21:04 +0000, Ashish Kalra wrote:
    > From: Brijesh Singh <Brijesh.Singh@amd.com>
    >
    > The command is used to create the encryption context for an incoming
    > SEV guest. The encryption context can be later used by the hypervisor
    > to import the incoming data into the SEV guest memory space.
    >
    > 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
    > Reviewed-by: Steve Rutherford <srutherford@google.com>
    > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    > Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
    > ---
    > .../virt/kvm/amd-memory-encryption.rst | 29 +++++++
    > arch/x86/kvm/svm.c | 81 +++++++++++++++++++
    > include/uapi/linux/kvm.h | 9 +++
    > 3 files changed, 119 insertions(+)
    >
    > diff --git a/Documentation/virt/kvm/amd-memory-encryption.rst b/Documentation/virt/kvm/amd-memory-encryption.rst
    > index a45dcb5f8687..ef1f1f3a5b40 100644
    > --- a/Documentation/virt/kvm/amd-memory-encryption.rst
    > +++ b/Documentation/virt/kvm/amd-memory-encryption.rst
    > @@ -322,6 +322,35 @@ issued by the hypervisor to delete the encryption context.
    >
    > Returns: 0 on success, -negative on error
    >
    > +13. KVM_SEV_RECEIVE_START
    > +------------------------
    > +
    > +The KVM_SEV_RECEIVE_START command is used for creating the memory encryption
    > +context for an incoming SEV guest. To create the encryption context, the user must
    > +provide a guest policy, the platform public Diffie-Hellman (PDH) key and session
    > +information.
    > +
    > +Parameters: struct kvm_sev_receive_start (in/out)
    > +
    > +Returns: 0 on success, -negative on error
    > +
    > +::
    > +
    > + struct kvm_sev_receive_start {
    > + __u32 handle; /* if zero then firmware creates a new handle */
    > + __u32 policy; /* guest's policy */
    > +
    > + __u64 pdh_uaddr; /* userspace address pointing to the PDH key */
    > + __u32 dh_len;

    Could dh_len be changed to pdh_len, to match the names in
    kvm_sev_receive_start in include/uapi/linux/kvm.h?

    > +
    > + __u64 session_addr; /* userspace address which points to the guest session information */

    Also, session_addr to session_uaddr?

    > + __u32 session_len;
    > + };
    > +
    > +On success, the 'handle' field contains a new handle and on error, a negative value.
    > +
    > +For more details, see SEV spec Section 6.12.
    > +
    > References
    > ==========
    >
    > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
    > index 71a4cb3b817d..038b47685733 100644
    > --- a/arch/x86/kvm/svm.c
    > +++ b/arch/x86/kvm/svm.c
    > @@ -7419,6 +7419,84 @@ static int sev_send_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)
    > return ret;
    > }
    >
    > +static int sev_receive_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
    > +{
    > + struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
    > + struct sev_data_receive_start *start;
    > + struct kvm_sev_receive_start params;
    > + int *error = &argp->error;
    > + void *session_data;
    > + void *pdh_data;
    > + int ret;
    > +
    > + if (!sev_guest(kvm))
    > + return -ENOTTY;
    > +
    > + /* Get parameter from the userspace */
    > + if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data,
    > + sizeof(struct kvm_sev_receive_start)))
    > + return -EFAULT;
    > +
    > + /* some sanity checks */
    > + if (!params.pdh_uaddr || !params.pdh_len ||
    > + !params.session_uaddr || !params.session_len)
    > + return -EINVAL;
    > +
    > + pdh_data = psp_copy_user_blob(params.pdh_uaddr, params.pdh_len);
    > + if (IS_ERR(pdh_data))
    > + return PTR_ERR(pdh_data);
    > +
    > + session_data = psp_copy_user_blob(params.session_uaddr,
    > + params.session_len);
    > + if (IS_ERR(session_data)) {
    > + ret = PTR_ERR(session_data);
    > + goto e_free_pdh;
    > + }
    > +
    > + ret = -ENOMEM;
    > + start = kzalloc(sizeof(*start), GFP_KERNEL);
    > + if (!start)
    > + goto e_free_session;
    > +
    > + start->handle = params.handle;
    > + start->policy = params.policy;
    > + start->pdh_cert_address = __psp_pa(pdh_data);
    > + start->pdh_cert_len = params.pdh_len;
    > + start->session_address = __psp_pa(session_data);
    > + start->session_len = params.session_len;
    > +
    > + /* create memory encryption context */
    > + ret = __sev_issue_cmd(argp->sev_fd, SEV_CMD_RECEIVE_START, start,
    > + error);
    > + if (ret)
    > + goto e_free;
    > +
    > + /* Bind ASID to this guest */
    > + ret = sev_bind_asid(kvm, start->handle, error);
    > + if (ret)
    > + goto e_free;
    > +
    > + params.handle = start->handle;
    > + if (copy_to_user((void __user *)(uintptr_t)argp->data,
    > + &params, sizeof(struct kvm_sev_receive_start))) {
    > + ret = -EFAULT;
    > + sev_unbind_asid(kvm, start->handle);
    > + goto e_free;
    > + }
    > +
    > + sev->handle = start->handle;
    > + sev->fd = argp->sev_fd;
    > +
    > +e_free:
    > + kfree(start);
    > +e_free_session:
    > + kfree(session_data);
    > +e_free_pdh:
    > + kfree(pdh_data);
    > +
    > + return ret;
    > +}
    > +
    > static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
    > {
    > struct kvm_sev_cmd sev_cmd;
    > @@ -7472,6 +7550,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
    > case KVM_SEV_SEND_FINISH:
    > r = sev_send_finish(kvm, &sev_cmd);
    > break;
    > + case KVM_SEV_RECEIVE_START:
    > + r = sev_receive_start(kvm, &sev_cmd);
    > + break;
    > default:
    > r = -EINVAL;
    > goto out;
    > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
    > index d9dc81bb9c55..74764b9db5fa 100644
    > --- a/include/uapi/linux/kvm.h
    > +++ b/include/uapi/linux/kvm.h
    > @@ -1579,6 +1579,15 @@ struct kvm_sev_send_update_data {
    > __u32 trans_len;
    > };
    >
    > +struct kvm_sev_receive_start {
    > + __u32 handle;
    > + __u32 policy;
    > + __u64 pdh_uaddr;
    > + __u32 pdh_len;
    > + __u64 session_uaddr;
    > + __u32 session_len;
    > +};
    > +
    > #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
    > #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
    > #define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
    > --
    > 2.17.1
    >

    \
     
     \ /
      Last update: 2020-04-02 23:38    [W:4.366 / U:1.976 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site