lkml.org 
[lkml]   [2020]   [Apr]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: [PATCH v6 05/14] KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_DATA command
    From
    Date

    On 3/29/20 11:21 PM, Ashish Kalra wrote:
    > From: Brijesh Singh <Brijesh.Singh@amd.com>
    >
    > The command is used for copying the incoming buffer 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
    > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    > Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
    > ---
    > .../virt/kvm/amd-memory-encryption.rst | 24 ++++++
    > arch/x86/kvm/svm.c | 79 +++++++++++++++++++
    > include/uapi/linux/kvm.h | 9 +++
    > 3 files changed, 112 insertions(+)
    >
    > diff --git a/Documentation/virt/kvm/amd-memory-encryption.rst b/Documentation/virt/kvm/amd-memory-encryption.rst
    > index ef1f1f3a5b40..554aa33a99cc 100644
    > --- a/Documentation/virt/kvm/amd-memory-encryption.rst
    > +++ b/Documentation/virt/kvm/amd-memory-encryption.rst
    > @@ -351,6 +351,30 @@ On success, the 'handle' field contains a new handle and on error, a negative va
    >
    > For more details, see SEV spec Section 6.12.
    >
    > +14. KVM_SEV_RECEIVE_UPDATE_DATA
    > +----------------------------
    > +
    > +The KVM_SEV_RECEIVE_UPDATE_DATA command can be used by the hypervisor to copy
    > +the incoming buffers into the guest memory region with encryption context
    > +created during the KVM_SEV_RECEIVE_START.
    > +
    > +Parameters (in): struct kvm_sev_receive_update_data
    > +
    > +Returns: 0 on success, -negative on error
    > +
    > +::
    > +
    > + struct kvm_sev_launch_receive_update_data {
    > + __u64 hdr_uaddr; /* userspace address containing the packet header */
    > + __u32 hdr_len;
    > +
    > + __u64 guest_uaddr; /* the destination guest memory region */
    > + __u32 guest_len;
    > +
    > + __u64 trans_uaddr; /* the incoming buffer memory region */
    > + __u32 trans_len;
    > + };
    > +
    > References
    > ==========
    >
    > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
    > index 038b47685733..5fc5355536d7 100644
    > --- a/arch/x86/kvm/svm.c
    > +++ b/arch/x86/kvm/svm.c
    > @@ -7497,6 +7497,82 @@ static int sev_receive_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
    > return ret;
    > }
    >
    > +static int sev_receive_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp)
    > +{
    > + struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
    > + struct kvm_sev_receive_update_data params;
    > + struct sev_data_receive_update_data *data;
    > + void *hdr = NULL, *trans = NULL;
    > + struct page **guest_page;
    > + unsigned long n;
    > + int ret, offset;
    > +
    > + if (!sev_guest(kvm))
    > + return -EINVAL;
    > +
    > + if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data,
    > + sizeof(struct kvm_sev_receive_update_data)))
    > + return -EFAULT;
    > +
    > + if (!params.hdr_uaddr || !params.hdr_len ||
    > + !params.guest_uaddr || !params.guest_len ||
    > + !params.trans_uaddr || !params.trans_len)
    > + return -EINVAL;
    > +
    > + /* Check if we are crossing the page boundary */
    > + offset = params.guest_uaddr & (PAGE_SIZE - 1);
    > + if ((params.guest_len + offset > PAGE_SIZE))
    > + return -EINVAL;
    > +
    > + hdr = psp_copy_user_blob(params.hdr_uaddr, params.hdr_len);
    > + if (IS_ERR(hdr))
    > + return PTR_ERR(hdr);
    > +
    > + trans = psp_copy_user_blob(params.trans_uaddr, params.trans_len);
    > + if (IS_ERR(trans)) {
    > + ret = PTR_ERR(trans);
    > + goto e_free_hdr;
    > + }
    > +
    > + ret = -ENOMEM;
    > + data = kzalloc(sizeof(*data), GFP_KERNEL);
    > + if (!data)
    > + goto e_free_trans;
    > +
    > + data->hdr_address = __psp_pa(hdr);
    > + data->hdr_len = params.hdr_len;
    > + data->trans_address = __psp_pa(trans);
    > + data->trans_len = params.trans_len;
    > +
    > + /* Pin guest memory */
    > + ret = -EFAULT;
    > + guest_page = sev_pin_memory(kvm, params.guest_uaddr & PAGE_MASK,
    > + PAGE_SIZE, &n, 0);
    > + if (!guest_page)
    > + goto e_free;
    > +
    > + /* The RECEIVE_UPDATE_DATA command requires C-bit to be always set. */
    > + data->guest_address = (page_to_pfn(guest_page[0]) << PAGE_SHIFT) +
    > + offset;
    > + data->guest_address |= sev_me_mask;
    > + data->guest_len = params.guest_len;
    > + data->handle = sev->handle;
    > +
    > + ret = sev_issue_cmd(kvm, SEV_CMD_RECEIVE_UPDATE_DATA, data,
    > + &argp->error);
    > +
    > + sev_unpin_memory(kvm, guest_page, n);
    > +
    > +e_free:
    > + kfree(data);
    > +e_free_trans:
    > + kfree(trans);
    > +e_free_hdr:
    > + kfree(hdr);
    > +
    > + return ret;
    > +}
    > +
    > static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
    > {
    > struct kvm_sev_cmd sev_cmd;
    > @@ -7553,6 +7629,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
    > case KVM_SEV_RECEIVE_START:
    > r = sev_receive_start(kvm, &sev_cmd);
    > break;
    > + case KVM_SEV_RECEIVE_UPDATE_DATA:
    > + r = sev_receive_update_data(kvm, &sev_cmd);
    > + break;
    > default:
    > r = -EINVAL;
    > goto out;
    > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
    > index 74764b9db5fa..4e80c57a3182 100644
    > --- a/include/uapi/linux/kvm.h
    > +++ b/include/uapi/linux/kvm.h
    > @@ -1588,6 +1588,15 @@ struct kvm_sev_receive_start {
    > __u32 session_len;
    > };
    >
    > +struct kvm_sev_receive_update_data {
    > + __u64 hdr_uaddr;
    > + __u32 hdr_len;
    > + __u64 guest_uaddr;
    > + __u32 guest_len;
    > + __u64 trans_uaddr;
    > + __u32 trans_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)
    Reviewed-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>

    \
     
     \ /
      Last update: 2020-04-03 00:26    [W:7.688 / U:0.952 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site