From patchwork Thu Sep 2 18:17:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Gonda X-Patchwork-Id: 12472283 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B9BBC433F5 for ; Thu, 2 Sep 2021 18:18:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EC2B361051 for ; Thu, 2 Sep 2021 18:18:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346965AbhIBSTG (ORCPT ); Thu, 2 Sep 2021 14:19:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346926AbhIBSTC (ORCPT ); Thu, 2 Sep 2021 14:19:02 -0400 Received: from mail-qt1-x84a.google.com (mail-qt1-x84a.google.com [IPv6:2607:f8b0:4864:20::84a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4D95CC061757 for ; Thu, 2 Sep 2021 11:18:03 -0700 (PDT) Received: by mail-qt1-x84a.google.com with SMTP id c20-20020a05622a059400b002a0bb6f8d84so2565164qtb.15 for ; Thu, 02 Sep 2021 11:18:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=vi00j8i95gzlA2JogRJZOpEKy7t58Be6t0UyDx2Twqk=; b=FsTvb40Aj+T4ym0oiVLCWAsq5jfNDkcTytOs636elmul9FMTJv4kp2HcQsxIzYVrW+ 25WPhnvT6xyTqYFmU0pCL+PeZwUFDLcdltSQc7dud+C0cAOl0dYmxLqvSUok+xxZGLT2 naTrHubJFPMbPLFp/PiJ+cLz+dTEluC3zwAca+4fW2gWczn3sDFqq6/T4GrVvhAercAO nrhG2FrJIQ16x704qjfhY8+n3Zxp7arN0ensy3gllK+/8ZezdzWRY3bXCn0SzY4r3EET xQPNllwbwsYBzWnu9PsV3l9cRRcfCRCzbDiAYIL4GQ2uQyT25Qamlb0TWXsQj5zgg8J+ 2odg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=vi00j8i95gzlA2JogRJZOpEKy7t58Be6t0UyDx2Twqk=; b=YyZaWYsaewT7WK7wTd7LaFy0KnSZvEg3U3IukczQAFF3ZTMgubtkUmx2msR628V2aY KUsEDszsPxC8OWEd4gbK6QRLZobeveSO1Vk8v1peYRhSNT52SRu7FMDAgqfHcRhJZfEF RlJ0cS5i0Jz0BnU7QijsvUZ4xhQALATQgN9mSDGZ6VueHtU0bR1lW4DBan2E0BgxbgzE O01LzuPxOjyEFlLopMCy5b8sgLAwkYOfsGTy+c5105vAZ4gXvAvkB0Qov6QH/biIFZry 3PHBLai1OShTSfLJOZ6ouUwcOwrmWQefyDELvRZCWLs83O8H7O3TXX5wubxBIhr/7PfK oZgA== X-Gm-Message-State: AOAM531IPx/QHs7UfnzqPbVwMQ6W9Ofjk+ILifUMVwCHyay87FzLtM9w F0ngU1rETlZ9RaHacJIfbiZaMWTxROUsE9JQfRkAY0WE2cOtVdPWnCOqZncIgVKsStDPy1/HlMe ZYBgB3VtKlKsNl5zVEcdKKxEnKA/9TTJ1Qt76ZTdKaV2OXHxdxKCMyofCyQ== X-Google-Smtp-Source: ABdhPJwmXksaTZmuphP9pjyf9+v9VGtGSmw6GnSNPgp0UnKj7JA+2VkIMO6SK48I6OOwbVck8zNpVzKlZoE= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:204:faf4:6e40:7b4e:999f]) (user=pgonda job=sendgmr) by 2002:a05:6214:b11:: with SMTP id u17mr4500603qvj.40.1630606682465; Thu, 02 Sep 2021 11:18:02 -0700 (PDT) Date: Thu, 2 Sep 2021 11:17:49 -0700 In-Reply-To: <20210902181751.252227-1-pgonda@google.com> Message-Id: <20210902181751.252227-2-pgonda@google.com> Mime-Version: 1.0 References: <20210902181751.252227-1-pgonda@google.com> X-Mailer: git-send-email 2.33.0.153.gba50c8fa24-goog Subject: [PATCH 1/3 V7] KVM, SEV: Add support for SEV intra host migration From: Peter Gonda To: kvm@vger.kernel.org Cc: Peter Gonda , Sean Christopherson , Marc Orr , Paolo Bonzini , David Rientjes , "Dr . David Alan Gilbert" , Brijesh Singh , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" , linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org For SEV to work with intra host migration, contents of the SEV info struct such as the ASID (used to index the encryption key in the AMD SP) and the list of memory regions need to be transferred to the target VM. This change adds a commands for a target VMM to get a source SEV VM's sev info. The target is expected to be initialized (sev_guest_init), but not launched state (sev_launch_start) when performing receive. Once the target has received, it will be in a launched state and will not need to perform the typical SEV launch commands. Signed-off-by: Peter Gonda Suggested-by: Sean Christopherson Reviewed-by: Marc Orr Cc: Marc Orr Cc: Paolo Bonzini Cc: Sean Christopherson Cc: David Rientjes Cc: Dr. David Alan Gilbert Cc: Brijesh Singh Cc: Vitaly Kuznetsov Cc: Wanpeng Li Cc: Jim Mattson Cc: Joerg Roedel Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- Documentation/virt/kvm/api.rst | 15 +++++ arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/svm/sev.c | 101 ++++++++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 1 + arch/x86/kvm/svm/svm.h | 2 + arch/x86/kvm/x86.c | 5 ++ include/uapi/linux/kvm.h | 1 + 7 files changed, 126 insertions(+) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 4ea1bb28297b..e8cecc024649 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -6702,6 +6702,21 @@ MAP_SHARED mmap will result in an -EINVAL return. When enabled the VMM may make use of the ``KVM_ARM_MTE_COPY_TAGS`` ioctl to perform a bulk copy of tags to/from the guest. +7.29 KVM_CAP_VM_MIGRATE_ENC_CONTEXT_FROM +------------------------------------- + +Architectures: x86 SEV enabled +Type: vm +Parameters: args[0] is the fd of the source vm +Returns: 0 on success + +This capability enables userspace to migrate the encryption context from the vm +indicated by the fd to the vm this is called on. + +This is intended to support intra-host migration of VMs between userspace VMMs. +in-guest workloads scheduled by the host. This allows for upgrading the VMM +process without interrupting the guest. + 8. Other capabilities. ====================== diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 09b256db394a..f06d87a85654 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1456,6 +1456,7 @@ struct kvm_x86_ops { int (*mem_enc_reg_region)(struct kvm *kvm, struct kvm_enc_region *argp); int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp); int (*vm_copy_enc_context_from)(struct kvm *kvm, unsigned int source_fd); + int (*vm_migrate_enc_context_from)(struct kvm *kvm, unsigned int source_fd); int (*get_msr_feature)(struct kvm_msr_entry *entry); diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 46eb1ba62d3d..8db666a362d4 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -1501,6 +1501,107 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) return sev_issue_cmd(kvm, SEV_CMD_RECEIVE_FINISH, &data, &argp->error); } +static int svm_sev_lock_for_migration(struct kvm *kvm) +{ + struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; + + /* + * Bail if this VM is already involved in a migration to avoid deadlock + * between two VMs trying to migrate to/from each other. + */ + if (atomic_cmpxchg_acquire(&sev->migration_in_progress, 0, 1)) + return -EBUSY; + + mutex_lock(&kvm->lock); + + return 0; +} + +static void svm_unlock_after_migration(struct kvm *kvm) +{ + struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; + + mutex_unlock(&kvm->lock); + atomic_set_release(&sev->migration_in_progress, 0); +} + +static void migrate_info_from(struct kvm_sev_info *dst, + struct kvm_sev_info *src) +{ + sev_asid_free(dst); + + dst->asid = src->asid; + dst->misc_cg = src->misc_cg; + dst->handle = src->handle; + dst->pages_locked = src->pages_locked; + + src->asid = 0; + src->active = false; + src->handle = 0; + src->pages_locked = 0; + src->misc_cg = NULL; + + INIT_LIST_HEAD(&dst->regions_list); + list_replace_init(&src->regions_list, &dst->regions_list); +} + +int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd) +{ + struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info; + struct file *source_kvm_file; + struct kvm *source_kvm; + int ret; + + ret = svm_sev_lock_for_migration(kvm); + if (ret) + return ret; + + if (!sev_guest(kvm) || sev_es_guest(kvm)) { + ret = -EINVAL; + pr_warn_ratelimited("VM must be SEV enabled to migrate to.\n"); + goto out_unlock; + } + + if (!list_empty(&dst_sev->regions_list)) { + ret = -EINVAL; + pr_warn_ratelimited( + "VM must not have encrypted regions to migrate to.\n"); + goto out_unlock; + } + + source_kvm_file = fget(source_fd); + if (!file_is_kvm(source_kvm_file)) { + ret = -EBADF; + pr_warn_ratelimited( + "Source VM must be SEV enabled to migrate from.\n"); + goto out_fput; + } + + source_kvm = source_kvm_file->private_data; + ret = svm_sev_lock_for_migration(source_kvm); + if (ret) + goto out_fput; + + if (!sev_guest(source_kvm) || sev_es_guest(source_kvm)) { + ret = -EINVAL; + pr_warn_ratelimited( + "Source VM must be SEV enabled to migrate from.\n"); + goto out_source; + } + + migrate_info_from(dst_sev, &to_kvm_svm(source_kvm)->sev_info); + ret = 0; + +out_source: + svm_unlock_after_migration(source_kvm); +out_fput: + if (source_kvm_file) + fput(source_kvm_file); +out_unlock: + svm_unlock_after_migration(kvm); + return ret; +} + int svm_mem_enc_op(struct kvm *kvm, void __user *argp) { struct kvm_sev_cmd sev_cmd; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 1a70e11f0487..88dd76dd966f 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4625,6 +4625,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .mem_enc_unreg_region = svm_unregister_enc_region, .vm_copy_enc_context_from = svm_vm_copy_asid_from, + .vm_migrate_enc_context_from = svm_vm_migrate_from, .can_emulate_instruction = svm_can_emulate_instruction, diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 524d943f3efc..67bfb43301e1 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -80,6 +80,7 @@ struct kvm_sev_info { u64 ap_jump_table; /* SEV-ES AP Jump Table address */ struct kvm *enc_context_owner; /* Owner of copied encryption context */ struct misc_cg *misc_cg; /* For misc cgroup accounting */ + atomic_t migration_in_progress; }; struct kvm_svm { @@ -552,6 +553,7 @@ int svm_register_enc_region(struct kvm *kvm, int svm_unregister_enc_region(struct kvm *kvm, struct kvm_enc_region *range); int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd); +int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd); void pre_sev_run(struct vcpu_svm *svm, int cpu); void __init sev_set_cpu_caps(void); void __init sev_hardware_setup(void); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 86539c1686fa..c461867d37aa 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5654,6 +5654,11 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, if (kvm_x86_ops.vm_copy_enc_context_from) r = kvm_x86_ops.vm_copy_enc_context_from(kvm, cap->args[0]); return r; + case KVM_CAP_VM_MIGRATE_ENC_CONTEXT_FROM: + r = -EINVAL; + if (kvm_x86_ops.vm_migrate_enc_context_from) + r = kvm_x86_ops.vm_migrate_enc_context_from(kvm, cap->args[0]); + return r; case KVM_CAP_EXIT_HYPERCALL: if (cap->args[0] & ~KVM_EXIT_HYPERCALL_VALID_MASK) { r = -EINVAL; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a067410ebea5..49660204cdb9 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1112,6 +1112,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_BINARY_STATS_FD 203 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 #define KVM_CAP_ARM_MTE 205 +#define KVM_CAP_VM_MIGRATE_ENC_CONTEXT_FROM 206 #ifdef KVM_CAP_IRQ_ROUTING From patchwork Thu Sep 2 18:17:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Gonda X-Patchwork-Id: 12472287 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 29340C433F5 for ; Thu, 2 Sep 2021 18:18:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0F6E660F56 for ; Thu, 2 Sep 2021 18:18:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346986AbhIBSTX (ORCPT ); Thu, 2 Sep 2021 14:19:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45420 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346941AbhIBSTD (ORCPT ); Thu, 2 Sep 2021 14:19:03 -0400 Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1B1E6C061764 for ; Thu, 2 Sep 2021 11:18:05 -0700 (PDT) Received: by mail-qk1-x74a.google.com with SMTP id x19-20020a05620a099300b003f64d79cbbaso3199274qkx.7 for ; Thu, 02 Sep 2021 11:18:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Aypxzqpu+vAXywZbUjl25jIypyUHDmFPudaxL3Vq6PQ=; b=vce/MUghP+vYh+QLW6k3+QnOLQW/MB2oJAGR8yg0OKACE7PEo71nmDMMmTXkNQGacG P7FCH4T9jYiBa8jKNXdz47tSxkrJT2ErWnqtY+jQp+lHjDvxZz5K1pHbHWfj3D+q7iNi vaYKpjqfuXeUeC9MyVnZovjAVb2iBLS3A03eCj/Q95m+00myydBD1bhjlSyl4lIIZik5 wf7Aw/gi+vhUT2SiJjyak2p5cIEuPt6NW5ggvGsDww7RUMuFUump1yxECmkRZD7xykPc sRwY5BlzzR9ntWOO1spKOloAnTxVo6R/qaYj4qyzUkA3fU9qMkJGfVGhIkTotye2IwW1 bMGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Aypxzqpu+vAXywZbUjl25jIypyUHDmFPudaxL3Vq6PQ=; b=TcMbNGdOgSrE7xgZ2URJ03sQdpszkS9cLt9Cp1Vfyh5359XVVnbX+6FRPqzQGGzPQL rB9DNPKv3n5y/OBEt3dIUORLliaagmehcYlSm4cK2ufUfJXiN7QCMPa3g6OVLqVkGbSz D/s7hixq+6A64bhAwisoAYwaeesRHk8BTt2q++BJPyTtKa0wJ4EDiYH/py2i82RqbFwl 1M+AJl0PuN8UXF2Tfy+rwJotgxR44Y1muvrn7ggt9yrWEpfVMBXbhHHwhpelUKYVA4uM oIzyBdXkgHQ1jVkC001aYvNW9LqzNBn9cZ+1OcfvDo9c8Z49dOWeh/7enX/MpfPFBRh0 Hi9Q== X-Gm-Message-State: AOAM531yF+FkFIStsYWAvbE5RnNzb9DO5wrVDbQixX+UB5KU2PAkpA4I +kOCKW+0kf4+KwHI1mOFr/19BzRk7ujrxLzlGzq8JkH4jiXWRfBJoDjx7Ly5o5BItLp2P5HDllG D9KABeBVScWEM5rSw/mRKa+FxkuC62cDHstkFG/ASsUaFNn5hsyh06NYD+w== X-Google-Smtp-Source: ABdhPJzR7VRGWNqmYMbLRu0dq4MxHDaTDzW2bon4oUBr6TdUM/HV0/M2zoGiz+SKN8srKQ0n3y+BsoPpfQ4= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:204:faf4:6e40:7b4e:999f]) (user=pgonda job=sendgmr) by 2002:a0c:c490:: with SMTP id u16mr4540564qvi.26.1630606684120; Thu, 02 Sep 2021 11:18:04 -0700 (PDT) Date: Thu, 2 Sep 2021 11:17:50 -0700 In-Reply-To: <20210902181751.252227-1-pgonda@google.com> Message-Id: <20210902181751.252227-3-pgonda@google.com> Mime-Version: 1.0 References: <20210902181751.252227-1-pgonda@google.com> X-Mailer: git-send-email 2.33.0.153.gba50c8fa24-goog Subject: [PATCH 2/3 V7] KVM, SEV: Add support for SEV-ES intra host migration From: Peter Gonda To: kvm@vger.kernel.org Cc: Peter Gonda , Marc Orr , Paolo Bonzini , Sean Christopherson , David Rientjes , "Dr . David Alan Gilbert" , Brijesh Singh , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" , linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org For SEV-ES to work with intra host migration the VMSAs, GHCB metadata, and other SEV-ES info needs to be preserved along with the guest's memory. Signed-off-by: Peter Gonda Reviewed-by: Marc Orr Cc: Marc Orr Cc: Paolo Bonzini Cc: Sean Christopherson Cc: David Rientjes Cc: Dr. David Alan Gilbert Cc: Brijesh Singh Cc: Vitaly Kuznetsov Cc: Wanpeng Li Cc: Jim Mattson Cc: Joerg Roedel Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- arch/x86/kvm/svm/sev.c | 62 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 8db666a362d4..fac21a82e4de 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -1545,6 +1545,59 @@ static void migrate_info_from(struct kvm_sev_info *dst, list_replace_init(&src->regions_list, &dst->regions_list); } +static int migrate_vmsa_from(struct kvm *dst, struct kvm *src) +{ + int i, num_vcpus; + struct kvm_vcpu *dst_vcpu, *src_vcpu; + struct vcpu_svm *dst_svm, *src_svm; + + num_vcpus = atomic_read(&dst->online_vcpus); + if (num_vcpus != atomic_read(&src->online_vcpus)) { + pr_warn_ratelimited( + "Source and target VMs must have same number of vCPUs.\n"); + return -EINVAL; + } + + for (i = 0; i < num_vcpus; ++i) { + src_vcpu = src->vcpus[i]; + if (!src_vcpu->arch.guest_state_protected) { + pr_warn_ratelimited( + "Source ES VM vCPUs must have protected state.\n"); + return -EINVAL; + } + } + + for (i = 0; i < num_vcpus; ++i) { + src_vcpu = src->vcpus[i]; + src_svm = to_svm(src_vcpu); + dst_vcpu = dst->vcpus[i]; + dst_svm = to_svm(dst_vcpu); + + /* + * Copy VMSA and GHCB fields from the source to the destination. + * Clear them on the source to prevent the VM running and + * changing the state of the VMSA/GHCB unexpectedly. + */ + dst_vcpu->vcpu_id = src_vcpu->vcpu_id; + dst_svm->vmsa = src_svm->vmsa; + src_svm->vmsa = NULL; + dst_svm->ghcb = src_svm->ghcb; + src_svm->ghcb = NULL; + dst_svm->vmcb->control.ghcb_gpa = + src_svm->vmcb->control.ghcb_gpa; + src_svm->vmcb->control.ghcb_gpa = 0; + dst_svm->ghcb_sa = src_svm->ghcb_sa; + src_svm->ghcb_sa = NULL; + dst_svm->ghcb_sa_len = src_svm->ghcb_sa_len; + src_svm->ghcb_sa_len = 0; + dst_svm->ghcb_sa_sync = src_svm->ghcb_sa_sync; + src_svm->ghcb_sa_sync = false; + dst_svm->ghcb_sa_free = src_svm->ghcb_sa_free; + src_svm->ghcb_sa_free = false; + } + return 0; +} + int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd) { struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info; @@ -1556,7 +1609,7 @@ int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd) if (ret) return ret; - if (!sev_guest(kvm) || sev_es_guest(kvm)) { + if (!sev_guest(kvm)) { ret = -EINVAL; pr_warn_ratelimited("VM must be SEV enabled to migrate to.\n"); goto out_unlock; @@ -1582,13 +1635,18 @@ int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd) if (ret) goto out_fput; - if (!sev_guest(source_kvm) || sev_es_guest(source_kvm)) { + if (!sev_guest(source_kvm)) { ret = -EINVAL; pr_warn_ratelimited( "Source VM must be SEV enabled to migrate from.\n"); goto out_source; } + if (sev_es_guest(kvm)) { + ret = migrate_vmsa_from(kvm, source_kvm); + if (ret) + goto out_source; + } migrate_info_from(dst_sev, &to_kvm_svm(source_kvm)->sev_info); ret = 0; From patchwork Thu Sep 2 18:17:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Gonda X-Patchwork-Id: 12472285 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5425C433EF for ; Thu, 2 Sep 2021 18:18:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8C05661051 for ; Thu, 2 Sep 2021 18:18:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347000AbhIBST1 (ORCPT ); Thu, 2 Sep 2021 14:19:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45430 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346954AbhIBSTF (ORCPT ); Thu, 2 Sep 2021 14:19:05 -0400 Received: from mail-qk1-x749.google.com (mail-qk1-x749.google.com [IPv6:2607:f8b0:4864:20::749]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9A8C7C061757 for ; Thu, 2 Sep 2021 11:18:06 -0700 (PDT) Received: by mail-qk1-x749.google.com with SMTP id c27-20020a05620a165b00b003d3817c7c23so3179439qko.16 for ; Thu, 02 Sep 2021 11:18:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Sn+g2bADD404qqjx2up6VXRVrUYy8eh5xavXQUrq6zk=; b=YA/z9SWZizIuQlkt7Sah9G1tInnrR7SLQie53RYcf0VJIaF2AzSr1TfkmKDWUKTTdS ss7ynVvdbhCl5Xi4b5gC9125rH40UCFUN78/XN5LfTTOKKFcF5v6d0uKvuJKmO+aX5aK Lxp7zrrZE5oJjiK9hZySN1OB+mu5M+8wIyWif6P/9ifWehxROkhyrDdxxi6q0oSji/Ej KJgmTgxu0y1KXtDN5Vfxn3ewUIcFlt3Jn2//wcmhjc4VvLQQh8AISXjThuQfZGnUzDLi CGphYzq55Sb/RYdwW3tUvlqXVF8GeYc//IilYx7EgY+FgADgIjCqg0fGD/iUkSfq2pj7 tldg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Sn+g2bADD404qqjx2up6VXRVrUYy8eh5xavXQUrq6zk=; b=EJe3x3JIaNVg6rp7vJ4n/zUd1UapDlNl+XLvsGLcYGlE/Zfq/3lLpL4jMuW7gg5ZXf AuXnhEYFDOvIrydyf58UJvH0xbcm5y1vip4jMEII1psbGR//F8NSt7rrhdoouZpS2U3e KIySkLNPs1ZHzt+//gu+od6tCaOh092GF1wpVWLdvx7qslA/lBOBmGn8A67EbTeEz3iJ oBaF2Vlz4LUpAqKv7FI3CrOwv5juwsUOCwj2SPa119B5sHbJw89iFefQLUQvmPZXvudN a4FD4eptP9GGLlnmBMY9Xj8ZFZid7peUkg6iR/zEyKx+Z2sQAIDLHjv3IxfkybvuIaPB qYaQ== X-Gm-Message-State: AOAM530RIHT+pAmtS0VYRNwOq7jbhbPfWGD1EmdygNNpIit2kfOna1fe AC2PbcqV5+1Amp7y/JAxH45KZM72Pj+tEav6BDYlDiq8oGkx5Vr5glf1rP51Hi4gEn7Q5mhCDDm 0LngTSQwUdku3wUvz60VLpWk3tUdLmhYTZUHlMkBWBNow3H0P3KKDvEfPzQ== X-Google-Smtp-Source: ABdhPJwcG8CnRLSx8mq6diZXX4lSPsxjiKeHD4iJow4eFxlcGB4nxa4pkFw1OzWn3WssEiBSwrC8rqJ21UY= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:204:faf4:6e40:7b4e:999f]) (user=pgonda job=sendgmr) by 2002:a0c:be8e:: with SMTP id n14mr4314725qvi.16.1630606685750; Thu, 02 Sep 2021 11:18:05 -0700 (PDT) Date: Thu, 2 Sep 2021 11:17:51 -0700 In-Reply-To: <20210902181751.252227-1-pgonda@google.com> Message-Id: <20210902181751.252227-4-pgonda@google.com> Mime-Version: 1.0 References: <20210902181751.252227-1-pgonda@google.com> X-Mailer: git-send-email 2.33.0.153.gba50c8fa24-goog Subject: [PATCH 3/3 V7] selftest: KVM: Add intra host migration tests From: Peter Gonda To: kvm@vger.kernel.org Cc: Peter Gonda , Sean Christopherson , Marc Orr , David Rientjes , Brijesh Singh , linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Adds testcases for intra host migration for SEV and SEV-ES. Also adds locking test to confirm no deadlock exists. Signed-off-by: Peter Gonda Suggested-by: Sean Christopherson Cc: Marc Orr Cc: Sean Christopherson Cc: David Rientjes Cc: Brijesh Singh Cc: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/x86_64/sev_vm_tests.c | 159 ++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/sev_vm_tests.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index c103873531e0..44fd3566fb51 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -72,6 +72,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/vmx_pmu_msrs_test TEST_GEN_PROGS_x86_64 += x86_64/xen_shinfo_test TEST_GEN_PROGS_x86_64 += x86_64/xen_vmcall_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_pi_mmio_test +TEST_GEN_PROGS_x86_64 += x86_64/sev_vm_tests TEST_GEN_PROGS_x86_64 += access_tracking_perf_test TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test diff --git a/tools/testing/selftests/kvm/x86_64/sev_vm_tests.c b/tools/testing/selftests/kvm/x86_64/sev_vm_tests.c new file mode 100644 index 000000000000..8ce8dd63ca85 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/sev_vm_tests.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "svm_util.h" +#include "kselftest.h" +#include "../lib/kvm_util_internal.h" + +#define SEV_DEV_PATH "/dev/sev" + +#define MIGRATE_TEST_NUM_VCPUS 4 +#define MIGRATE_TEST_VMS 3 +#define LOCK_TESTING_THREADS 3 +#define LOCK_TESTING_ITERATIONS 10000 + +/* + * Open SEV_DEV_PATH if available, otherwise exit the entire program. + * + * Input Args: + * flags - The flags to pass when opening SEV_DEV_PATH. + * + * Return: + * The opened file descriptor of /dev/sev. + */ +static int open_sev_dev_path_or_exit(int flags) +{ + static int fd; + + if (fd != 0) + return fd; + + fd = open(SEV_DEV_PATH, flags); + if (fd < 0) { + print_skip("%s not available, is SEV not enabled? (errno: %d)", + SEV_DEV_PATH, errno); + exit(KSFT_SKIP); + } + + return fd; +} + +static void sev_ioctl(int vm_fd, int cmd_id, void *data) +{ + struct kvm_sev_cmd cmd = { + .id = cmd_id, + .data = (uint64_t)data, + .sev_fd = open_sev_dev_path_or_exit(0), + }; + int ret; + + TEST_ASSERT(cmd_id < KVM_SEV_NR_MAX && cmd_id >= 0, + "Unknown SEV CMD : %d\n", cmd_id); + + ret = ioctl(vm_fd, KVM_MEMORY_ENCRYPT_OP, &cmd); + TEST_ASSERT((ret == 0 || cmd.error == SEV_RET_SUCCESS), + "%d failed: return code: %d, errno: %d, fw error: %d", + cmd_id, ret, errno, cmd.error); +} + +static struct kvm_vm *sev_vm_create(bool es) +{ + struct kvm_vm *vm; + struct kvm_sev_launch_start start = { 0 }; + int i; + + vm = vm_create(VM_MODE_DEFAULT, 0, O_RDWR); + sev_ioctl(vm->fd, es ? KVM_SEV_ES_INIT : KVM_SEV_INIT, NULL); + for (i = 0; i < MIGRATE_TEST_NUM_VCPUS; ++i) + vm_vcpu_add(vm, i); + start.policy |= (es) << 2; + sev_ioctl(vm->fd, KVM_SEV_LAUNCH_START, &start); + if (es) + sev_ioctl(vm->fd, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL); + return vm; +} + +static void test_sev_migrate_from(bool es) +{ + struct kvm_vm *vms[MIGRATE_TEST_VMS]; + struct kvm_enable_cap cap = { + .cap = KVM_CAP_VM_MIGRATE_ENC_CONTEXT_FROM + }; + int i; + + for (i = 0; i < MIGRATE_TEST_VMS; ++i) { + vms[i] = sev_vm_create(es); + if (i > 0) { + cap.args[0] = vms[i - 1]->fd; + vm_enable_cap(vms[i], &cap); + } + } +} + +struct locking_thread_input { + struct kvm_vm *vm; + int source_fds[LOCK_TESTING_THREADS]; +}; + +static void *locking_test_thread(void *arg) +{ + /* + * This test case runs a number of threads all trying to use the intra + * host migration ioctls. This tries to detect if a deadlock exists. + */ + struct kvm_enable_cap cap = { + .cap = KVM_CAP_VM_MIGRATE_ENC_CONTEXT_FROM + }; + int i, j; + struct locking_thread_input *input = (struct locking_test_thread *)arg; + + for (i = 0; i < LOCK_TESTING_ITERATIONS; ++i) { + j = input->source_fds[i % LOCK_TESTING_THREADS]; + cap.args[0] = input->source_fds[j]; + /* + * Call IOCTL directly without checking return code or + * asserting. We are * simply trying to confirm there is no + * deadlock from userspace * not check correctness of + * migration here. + */ + ioctl(input->vm->fd, KVM_ENABLE_CAP, &cap); + } +} + +static void test_sev_migrate_locking(void) +{ + struct locking_thread_input input[LOCK_TESTING_THREADS]; + pthread_t pt[LOCK_TESTING_THREADS]; + int i; + + for (i = 0; i < LOCK_TESTING_THREADS; ++i) { + input[i].vm = sev_vm_create(/* es= */ false); + input[0].source_fds[i] = input[i].vm->fd; + } + for (i = 1; i < LOCK_TESTING_THREADS; ++i) + memcpy(input[i].source_fds, input[0].source_fds, + sizeof(input[i].source_fds)); + + for (i = 0; i < LOCK_TESTING_THREADS; ++i) + pthread_create(&pt[i], NULL, locking_test_thread, &input[i]); + + for (i = 0; i < LOCK_TESTING_THREADS; ++i) + pthread_join(pt[i], NULL); +} + +int main(int argc, char *argv[]) +{ + test_sev_migrate_from(/* es= */ false); + test_sev_migrate_from(/* es= */ true); + test_sev_migrate_locking(); + return 0; +}