From patchwork Wed Apr 17 15:34:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13633529 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 802D31487C6 for ; Wed, 17 Apr 2024 15:34:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368100; cv=none; b=uE6YGE56r8kdPfZaJgg7i9uUMvXeGlPX8umS2NmBgSa+aTlb6Ovr07d85jX0FAZ+YHhgcB4qoJ8PyuPFi5nyIlAVzf7kkslp7YkIJb0ptKZHs8m7ft5jGtLak6xcCz+csjtC0NG+z5jCfV5r5LIhEhHlFC8AoFlbRvSGXjQEpFk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368100; c=relaxed/simple; bh=P7qL8n859l6t9aHE/CUbWmDOIT6vHCAOzzjvKY5e/Qk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BKsL0qNisba2TOSl1VAtbYI5YkyBnJrqFx6cd8BY/UesJWGlQ2pMJX2OYsm0l93uHmxT+JeSYLopQKurKAjYJVlD449lfIkHtM3VkshAKjQh8jlR6hog3sg8WoSIBpqt/eW08t/kIoTaASk7lYc96AA5QldAMkovcQ49hVLIHww= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=asSDFpog; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="asSDFpog" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713368097; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QpEqSEJva6pseMNSTEMb3KlMpGn0cTWl47IYQ+iVjpE=; b=asSDFpogrR8wcf/TGGRkcXCHARhuhY1Ul71eaCaCT1FLPwVNABstugxi9SDC2f82rg6hZZ igRxcs3ke9Ejw2OERHzf4+omk9DIiOE4TnG5Pnc3tyR6RElcZT4kqBNM/OGBqCIbrxPKsa SBnEyGZhUSpD7+LSQBfwcIJMYPYdd38= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-569-FUEJyAKJPkKzrD_fx3WfIA-1; Wed, 17 Apr 2024 11:34:52 -0400 X-MC-Unique: FUEJyAKJPkKzrD_fx3WfIA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 808C69C2F22; Wed, 17 Apr 2024 15:34:51 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 50B11581CD; Wed, 17 Apr 2024 15:34:51 +0000 (UTC) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, xiaoyao.li@intel.com, binbin.wu@linux.intel.com, seanjc@google.com, rick.p.edgecombe@intel.com Subject: [PATCH 1/7] KVM: Document KVM_MAP_MEMORY ioctl Date: Wed, 17 Apr 2024 11:34:44 -0400 Message-ID: <20240417153450.3608097-2-pbonzini@redhat.com> In-Reply-To: <20240417153450.3608097-1-pbonzini@redhat.com> References: <20240417153450.3608097-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 From: Isaku Yamahata Adds documentation of KVM_MAP_MEMORY ioctl. [1] It populates guest memory. It doesn't do extra operations on the underlying technology-specific initialization [2]. For example, CoCo-related operations won't be performed. Concretely for TDX, this API won't invoke TDH.MEM.PAGE.ADD() or TDH.MR.EXTEND(). Vendor-specific APIs are required for such operations. The key point is to adapt of vcpu ioctl instead of VM ioctl. First, populating guest memory requires vcpu. If it is VM ioctl, we need to pick one vcpu somehow. Secondly, vcpu ioctl allows each vcpu to invoke this ioctl in parallel. It helps to scale regarding guest memory size, e.g., hundreds of GB. [1] https://lore.kernel.org/kvm/Zbrj5WKVgMsUFDtb@google.com/ [2] https://lore.kernel.org/kvm/Ze-TJh0BBOWm9spT@google.com/ Suggested-by: Sean Christopherson Signed-off-by: Isaku Yamahata Message-ID: <9a060293c9ad9a78f1d8994cfe1311e818e99257.1712785629.git.isaku.yamahata@intel.com> Signed-off-by: Paolo Bonzini --- Documentation/virt/kvm/api.rst | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index f0b76ff5030d..c16906a42db1 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -6352,6 +6352,60 @@ a single guest_memfd file, but the bound ranges must not overlap). See KVM_SET_USER_MEMORY_REGION2 for additional details. +4.143 KVM_MAP_MEMORY +------------------------ + +:Capability: KVM_CAP_MAP_MEMORY +:Architectures: none +:Type: vcpu ioctl +:Parameters: struct kvm_map_memory (in/out) +:Returns: 0 on success, < 0 on error + +Errors: + + ========== =============================================================== + EINVAL The specified `base_address` and `size` were invalid (e.g. not + page aligned or outside the defined memory slots). + EAGAIN The ioctl should be invoked again and no page was processed. + EINTR An unmasked signal is pending and no page was processed. + EFAULT The parameter address was invalid. + EOPNOTSUPP The architecture does not support this operation, or the + guest state does not allow it. + ========== =============================================================== + +:: + + struct kvm_map_memory { + /* in/out */ + __u64 base_address; + __u64 size; + /* in */ + __u64 flags; + __u64 padding[5]; + }; + +KVM_MAP_MEMORY populates guest memory in the page tables of a vCPU. +When the ioctl returns, the input values are updated to point to the +remaining range. If `size` > 0 on return, the caller can just issue +the ioctl again with the same `struct kvm_map_memory` argument. + +In some cases, multiple vCPUs might share the page tables. In this +case, if this ioctl is called in parallel for multiple vCPUs the +ioctl might return with `size` > 0. + +The ioctl may not be supported for all VMs, and may just return +an `EOPNOTSUPP` error if a VM does not support it. You may use +`KVM_CHECK_EXTENSION` on the VM file descriptor to check if it is +supported. + +Also, shadow page tables cannot support this ioctl because they +are indexed by virtual address or nested guest physical address. +Calling this ioctl when the guest is using shadow page tables (for +example because it is running a nested guest) will also fail. + +`flags` must currently be zero. + + 5. The kvm_run structure ======================== From patchwork Wed Apr 17 15:34:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13633530 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EFA1A1487E7 for ; Wed, 17 Apr 2024 15:34:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368100; cv=none; b=HxBzmWDL+azNh703vqRjk/fU/agFT4hAA3FtHVbslFbUXI5HoZEUKbqlZcOiX8rH+ivWVxBSgyGU8n1dmGizYq73sGOJq2UaYVrPTxWV7SGNtg08Rb2ecb1N6DDo5TT1Qrx3jQgIUO+Q/DUmqLIWigOJ6NjzpU/JwdPO4N+0I4Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368100; c=relaxed/simple; bh=L7GanalmRhcS5JLx9XE1Hz67smUvUszxA2GzyAUJq7g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=as2d7CIxrJvRUgcUqh+bOgbtYttdheUOMD3TuU1KC6q32XCPr0gjcMBOmXSTtKKhdqbc4j+AATNMrkoCpqhlFKx8i0bmIk+JSxjARWzoCmIoXpi0QfpoTdpXyipNfUpaI+aww8UexP8BFySPAU+GCeKC34XFDl/ex8OfFAvO+9E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=FNJnLtUJ; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="FNJnLtUJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713368098; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aaDHxUBbyM9NAtjyjLLo4Vwi1b0JqYRQ5feEYlXA/BY=; b=FNJnLtUJqjqTmGkiQQzsfSO/5x98u7Cxp+cq3Wm7Lweic3Wz3Ohp/15QYfX8JCx+wzZzZH BYgnB9Yy2VkeEKQqT3fEOv6NE3C9RBp74gMcSJvTsHNsxZElWyyWg1Tg37QnNbjzBXWGkM ngPpCJFpo2WIm8Xj6M5aTxe8G9jSNZc= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-153-sJ5cafnoOg2dSl8G-rl8Iw-1; Wed, 17 Apr 2024 11:34:52 -0400 X-MC-Unique: sJ5cafnoOg2dSl8G-rl8Iw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BA193802A6F; Wed, 17 Apr 2024 15:34:51 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8A1C0581CD; Wed, 17 Apr 2024 15:34:51 +0000 (UTC) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, xiaoyao.li@intel.com, binbin.wu@linux.intel.com, seanjc@google.com, rick.p.edgecombe@intel.com Subject: [PATCH 2/7] KVM: Add KVM_MAP_MEMORY vcpu ioctl to pre-populate guest memory Date: Wed, 17 Apr 2024 11:34:45 -0400 Message-ID: <20240417153450.3608097-3-pbonzini@redhat.com> In-Reply-To: <20240417153450.3608097-1-pbonzini@redhat.com> References: <20240417153450.3608097-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 From: Isaku Yamahata Add a new ioctl KVM_MAP_MEMORY in the KVM common code. It iterates on the memory range and calls the arch-specific function. Add stub arch function as a weak symbol. Suggested-by: Sean Christopherson Signed-off-by: Isaku Yamahata Reviewed-by: Rick Edgecombe Message-ID: <819322b8f25971f2b9933bfa4506e618508ad782.1712785629.git.isaku.yamahata@intel.com> Signed-off-by: Paolo Bonzini --- include/linux/kvm_host.h | 5 ++++ include/uapi/linux/kvm.h | 10 +++++++ virt/kvm/Kconfig | 3 ++ virt/kvm/kvm_main.c | 61 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 8dea11701ab2..2b0f0240a64c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -2478,4 +2478,9 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t gfn, void __user *src, long npages void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end); #endif +#ifdef CONFIG_KVM_GENERIC_MAP_MEMORY +int kvm_arch_vcpu_map_memory(struct kvm_vcpu *vcpu, + struct kvm_map_memory *mapping); +#endif + #endif diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 2190adbe3002..4d233f44c613 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -917,6 +917,7 @@ struct kvm_enable_cap { #define KVM_CAP_MEMORY_ATTRIBUTES 233 #define KVM_CAP_GUEST_MEMFD 234 #define KVM_CAP_VM_TYPES 235 +#define KVM_CAP_MAP_MEMORY 236 struct kvm_irq_routing_irqchip { __u32 irqchip; @@ -1548,4 +1549,13 @@ struct kvm_create_guest_memfd { __u64 reserved[6]; }; +#define KVM_MAP_MEMORY _IOWR(KVMIO, 0xd5, struct kvm_map_memory) + +struct kvm_map_memory { + __u64 base_address; + __u64 size; + __u64 flags; + __u64 padding[5]; +}; + #endif /* __LINUX_KVM_H */ diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig index 754c6c923427..1b94126622e8 100644 --- a/virt/kvm/Kconfig +++ b/virt/kvm/Kconfig @@ -67,6 +67,9 @@ config HAVE_KVM_INVALID_WAKEUPS config KVM_GENERIC_DIRTYLOG_READ_PROTECT bool +config KVM_GENERIC_MAP_MEMORY + bool + config KVM_COMPAT def_bool y depends on KVM && COMPAT && !(S390 || ARM64 || RISCV) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 38b498669ef9..350ead98e9a6 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -4379,6 +4379,47 @@ static int kvm_vcpu_ioctl_get_stats_fd(struct kvm_vcpu *vcpu) return fd; } +#ifdef CONFIG_KVM_GENERIC_MAP_MEMORY +static int kvm_vcpu_map_memory(struct kvm_vcpu *vcpu, + struct kvm_map_memory *mapping) +{ + int idx, r; + u64 full_size; + + if (mapping->flags) + return -EINVAL; + + if (!PAGE_ALIGNED(mapping->base_address) || + !PAGE_ALIGNED(mapping->size) || + mapping->base_address + mapping->size <= mapping->base_address) + return -EINVAL; + + vcpu_load(vcpu); + idx = srcu_read_lock(&vcpu->kvm->srcu); + + r = 0; + full_size = mapping->size; + while (mapping->size) { + if (signal_pending(current)) { + r = -EINTR; + break; + } + + r = kvm_arch_vcpu_map_memory(vcpu, mapping); + if (r) + break; + + cond_resched(); + } + + srcu_read_unlock(&vcpu->kvm->srcu, idx); + vcpu_put(vcpu); + + /* Return success if at least one page was mapped successfully. */ + return full_size == mapping->size ? r : 0; +} +#endif + static long kvm_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -4580,6 +4621,20 @@ static long kvm_vcpu_ioctl(struct file *filp, r = kvm_vcpu_ioctl_get_stats_fd(vcpu); break; } +#ifdef CONFIG_KVM_GENERIC_MAP_MEMORY + case KVM_MAP_MEMORY: { + struct kvm_map_memory mapping; + + r = -EFAULT; + if (copy_from_user(&mapping, argp, sizeof(mapping))) + break; + r = kvm_vcpu_map_memory(vcpu, &mapping); + /* Pass back leftover range. */ + if (copy_to_user(argp, &mapping, sizeof(mapping))) + r = -EFAULT; + break; + } +#endif default: r = kvm_arch_vcpu_ioctl(filp, ioctl, arg); } @@ -4863,6 +4918,12 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) #ifdef CONFIG_KVM_PRIVATE_MEM case KVM_CAP_GUEST_MEMFD: return !kvm || kvm_arch_has_private_mem(kvm); +#endif +#ifdef CONFIG_KVM_GENERIC_MAP_MEMORY + case KVM_CAP_MAP_MEMORY: + if (!kvm) + return 1; + /* Leave per-VM implementation to kvm_vm_ioctl_check_extension(). */ #endif default: break; From patchwork Wed Apr 17 15:34:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13633526 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9608147C64 for ; Wed, 17 Apr 2024 15:34:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368099; cv=none; b=OX8ctah8W3MPZNUGs+2yOtaidkYK8CSTd5OQWPoPOO38eicwN7g0/qhnYWh5nxmEVtUYSTSZ6OHN4K2JgDp3lt1dchfmpC1+VG9mQ9vt2L3uMtl07NfI5z/HPQBLAOCcTcrcJ0nCmRQ/JCMCFpuYeLEA1glkjZ8Kg5wwslYzGik= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368099; c=relaxed/simple; bh=rlBoMCC4//sfGrQFFIwHVDxKJN5+vVzVUBJTEepXgqw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WLFTc0LQdPb/OZmZDn0M1lavnOKsQV1rR2aZ4Ahn6UtibhoRO9dizIMDaoNzNqmKK/nLzAKnz4qmWBPVTOqBLW0xW6H81AwNIvi5tW3mMBgRsA8+epj/e67yCWI6AHUqI0frfNSjz5oXGciF5ZVR97qZIxvyLioEbALW3Z2UoLQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=DlR41oAr; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="DlR41oAr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713368095; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=E5+7UvXw2tljyq+ZcDpXUa1GgQHlyrzaHv6gQXx3TS8=; b=DlR41oArRnBxfM9MHRfBBGtYJ7SHvbARKxJKnXf6zciqjaDfKzLm8uVeRGRCRlMBJAjcDw 3VOe8yIRxsY/0l2HehMY5JZ9sxEM2I8N+blmi+uap2cD2X7pVay4I0xbceKCr/wRfNwBTv c6lLgRh5l+/ATgZziMpRqsOIU9ypFR0= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-32-JhPoMVDQPDui_ZWzoEHDaw-1; Wed, 17 Apr 2024 11:34:52 -0400 X-MC-Unique: JhPoMVDQPDui_ZWzoEHDaw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 000BA3C108C9; Wed, 17 Apr 2024 15:34:51 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id C33B2581CD; Wed, 17 Apr 2024 15:34:51 +0000 (UTC) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, xiaoyao.li@intel.com, binbin.wu@linux.intel.com, seanjc@google.com, rick.p.edgecombe@intel.com Subject: [PATCH 3/7] KVM: x86/mmu: Extract __kvm_mmu_do_page_fault() Date: Wed, 17 Apr 2024 11:34:46 -0400 Message-ID: <20240417153450.3608097-4-pbonzini@redhat.com> In-Reply-To: <20240417153450.3608097-1-pbonzini@redhat.com> References: <20240417153450.3608097-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 From: Isaku Yamahata Extract out __kvm_mmu_do_page_fault() from kvm_mmu_do_page_fault(). The inner function is to initialize struct kvm_page_fault and to call the fault handler, and the outer function handles updating stats and converting return code. KVM_MAP_MEMORY will call the KVM page fault handler. This patch makes the emulation_type always set irrelevant to the return code. kvm_mmu_page_fault() is the only caller of kvm_mmu_do_page_fault(), and references the value only when PF_RET_EMULATE is returned. Therefore, this adjustment doesn't affect functionality. No functional change intended. Suggested-by: Sean Christopherson Signed-off-by: Isaku Yamahata Message-ID: Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu/mmu_internal.h | 38 +++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_internal.h index e68a60974cf4..9baae6c223ee 100644 --- a/arch/x86/kvm/mmu/mmu_internal.h +++ b/arch/x86/kvm/mmu/mmu_internal.h @@ -287,8 +287,8 @@ static inline void kvm_mmu_prepare_memory_fault_exit(struct kvm_vcpu *vcpu, fault->is_private); } -static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, - u64 err, bool prefetch, int *emulation_type) +static inline int __kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + u64 err, bool prefetch, int *emulation_type) { struct kvm_page_fault fault = { .addr = cr2_or_gpa, @@ -318,6 +318,27 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, fault.slot = kvm_vcpu_gfn_to_memslot(vcpu, fault.gfn); } + if (IS_ENABLED(CONFIG_MITIGATION_RETPOLINE) && fault.is_tdp) + r = kvm_tdp_page_fault(vcpu, &fault); + else + r = vcpu->arch.mmu->page_fault(vcpu, &fault); + + if (r == RET_PF_EMULATE && fault.is_private) { + kvm_mmu_prepare_memory_fault_exit(vcpu, &fault); + r = -EFAULT; + } + + if (fault.write_fault_to_shadow_pgtable && emulation_type) + *emulation_type |= EMULTYPE_WRITE_PF_TO_SP; + + return r; +} + +static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + u64 err, bool prefetch, int *emulation_type) +{ + int r; + /* * Async #PF "faults", a.k.a. prefetch faults, are not faults from the * guest perspective and have already been counted at the time of the @@ -326,18 +347,7 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, if (!prefetch) vcpu->stat.pf_taken++; - if (IS_ENABLED(CONFIG_MITIGATION_RETPOLINE) && fault.is_tdp) - r = kvm_tdp_page_fault(vcpu, &fault); - else - r = vcpu->arch.mmu->page_fault(vcpu, &fault); - - if (r == RET_PF_EMULATE && fault.is_private) { - kvm_mmu_prepare_memory_fault_exit(vcpu, &fault); - return -EFAULT; - } - - if (fault.write_fault_to_shadow_pgtable && emulation_type) - *emulation_type |= EMULTYPE_WRITE_PF_TO_SP; + r = __kvm_mmu_do_page_fault(vcpu, cr2_or_gpa, err, prefetch, emulation_type); /* * Similar to above, prefetch faults aren't truly spurious, and the From patchwork Wed Apr 17 15:34:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13633531 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2F9B214901E for ; Wed, 17 Apr 2024 15:35:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368101; cv=none; b=RmSGKZxtUmV6CQZxcySdMDUFVcV4Ch2MuLTpub5Idz2Dxw69O2OAqCSak7+5XTdCZ+2CLZGECZp0js3m/Eqb7Lq1MokFe0gfdItCuBdmgoUjJCqiKOdZkHGeNug/OT4SoL1YMu5+d0PuNl5f7e93WvUTIREWmkd6FRL6kpJVmO0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368101; c=relaxed/simple; bh=81mARjUpw+KVyq4vQ1KQan74CjOK+s4dvQQ+ghYUVsU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tjkFB2bUd/vA/fyrIrRFsda+byZeH8C2X6DHAMmUosh2TqYJys1JNRfkYGD5//W67xhpTCBniRSbAG6/9EGzQMJbTzhMbSb0jhrklWPSDiKr6gXwsy/oQBCBDPwYlflerguuRjqbErbzl51WPt2K1UD5qKZ70EQhR0rCfqT1wOE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=QvJyz0LV; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="QvJyz0LV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713368099; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=otExSoiFgVMzLYgIYpvIwimsI5D4FF0c+uBWyLnFbGw=; b=QvJyz0LVVsBl2fyANuziDbrlGVXhOV5wErxt9RdVcyU+tRzRYDTutls7vpqUfFCyCi124i A1zFXSCzKZMB4xf1uSb8luW8jKJ4XeJ6+19x+QSvy7DfV7gfSGvVWU39HSrtqIDGlXdeUo M90wkJHw1MmPds654iE3IZ/MRaE+UFo= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-438-tFEeviQnP_64sUjVfisTNA-1; Wed, 17 Apr 2024 11:34:56 -0400 X-MC-Unique: tFEeviQnP_64sUjVfisTNA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 384B7188ACA1; Wed, 17 Apr 2024 15:34:52 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 082F0581DE; Wed, 17 Apr 2024 15:34:52 +0000 (UTC) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, xiaoyao.li@intel.com, binbin.wu@linux.intel.com, seanjc@google.com, rick.p.edgecombe@intel.com Subject: [PATCH 4/7] KVM: x86/mmu: Make __kvm_mmu_do_page_fault() return mapped level Date: Wed, 17 Apr 2024 11:34:47 -0400 Message-ID: <20240417153450.3608097-5-pbonzini@redhat.com> In-Reply-To: <20240417153450.3608097-1-pbonzini@redhat.com> References: <20240417153450.3608097-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 From: Isaku Yamahata The guest memory population logic will need to know what page size or level (4K, 2M, ...) is mapped. Signed-off-by: Isaku Yamahata Message-ID: Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu/mmu_internal.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_internal.h index 9baae6c223ee..b0a10f5a40dd 100644 --- a/arch/x86/kvm/mmu/mmu_internal.h +++ b/arch/x86/kvm/mmu/mmu_internal.h @@ -288,7 +288,8 @@ static inline void kvm_mmu_prepare_memory_fault_exit(struct kvm_vcpu *vcpu, } static inline int __kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, - u64 err, bool prefetch, int *emulation_type) + u64 err, bool prefetch, + int *emulation_type, u8 *level) { struct kvm_page_fault fault = { .addr = cr2_or_gpa, @@ -330,6 +331,8 @@ static inline int __kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gp if (fault.write_fault_to_shadow_pgtable && emulation_type) *emulation_type |= EMULTYPE_WRITE_PF_TO_SP; + if (level) + *level = fault.goal_level; return r; } @@ -347,7 +350,8 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, if (!prefetch) vcpu->stat.pf_taken++; - r = __kvm_mmu_do_page_fault(vcpu, cr2_or_gpa, err, prefetch, emulation_type); + r = __kvm_mmu_do_page_fault(vcpu, cr2_or_gpa, err, prefetch, + emulation_type, NULL); /* * Similar to above, prefetch faults aren't truly spurious, and the From patchwork Wed Apr 17 15:34:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13633525 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4CC67147C72 for ; Wed, 17 Apr 2024 15:34:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368098; cv=none; b=Lhzl5Pj6nfiM+7zb05QfgqJROGvnAkRzFbpSgYJC5KDoInG0x4SgzYot+tUwep+SgCrV6xZ16BLbCERpJsHWZ6SJ84RU38D4USGTfSQ8XJG6i3Ufzbn+bVF6oWtymW2Zn3fRga+kp+XoZ70URJJBKXan/BDkMGwgFtbYE7uC6GU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368098; c=relaxed/simple; bh=18C3fkjaGUjut87lyhCZwmA7W+1+Z8WNC7ozIOguMAY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=e1bNwgZ6a8HDYDVS5zNX+Bzp6LlsQ9m1mveeDUnx8hAQEiA2/hxdmoKv3LO7e7HqyjHMOr0KzlaKlK853cMwshj8Sc5cxulsB7n4tJfeM4x/JCQjcua6wJhztUYc/Dy4x+j+keMUcRQeMDMGoIp/FsFl4QmKFmTAn/RKYdmUUGU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=HdUkiF5e; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="HdUkiF5e" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713368096; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=T3Uwoo1D+A7Ab673wp0hlYFDcZEPH2tfTFOyRGJRlS0=; b=HdUkiF5eBnIHQHKD2xqCHmR4CGAsy01WLLucd5jOfn8NLmAqwt/1OgZvhjPzDahqgSAEMb dOHUCkEuLYCoJ/FzgkXQFU3v55PR+zrDqos6FVysnGyY2UFrgMJOQ1PQzX8rcHif5vLRz7 ocdKgla2HjdHoOu5Q/dzeHv1641PKIc= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-390-S1qZy3LON1i0HI-0c5KOUA-1; Wed, 17 Apr 2024 11:34:53 -0400 X-MC-Unique: S1qZy3LON1i0HI-0c5KOUA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 717CD811000; Wed, 17 Apr 2024 15:34:52 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 40BF1581DE; Wed, 17 Apr 2024 15:34:52 +0000 (UTC) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, xiaoyao.li@intel.com, binbin.wu@linux.intel.com, seanjc@google.com, rick.p.edgecombe@intel.com Subject: [PATCH 5/7] KVM: x86/mmu: Introduce kvm_tdp_map_page() to populate guest memory Date: Wed, 17 Apr 2024 11:34:48 -0400 Message-ID: <20240417153450.3608097-6-pbonzini@redhat.com> In-Reply-To: <20240417153450.3608097-1-pbonzini@redhat.com> References: <20240417153450.3608097-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 From: Isaku Yamahata Introduce a helper function to call the KVM fault handler. It allows a new ioctl to invoke the KVM fault handler to populate without seeing RET_PF_* enums or other KVM MMU internal definitions because RET_PF_* are internal to x86 KVM MMU. The implementation is restricted to two-dimensional paging for simplicity. The shadow paging uses GVA for faulting instead of L1 GPA. It makes the API difficult to use. Signed-off-by: Isaku Yamahata Message-ID: <9b866a0ae7147f96571c439e75429a03dcb659b6.1712785629.git.isaku.yamahata@intel.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.h | 3 +++ arch/x86/kvm/mmu/mmu.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index e8b620a85627..51ff4f67e115 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -183,6 +183,9 @@ static inline void kvm_mmu_refresh_passthrough_bits(struct kvm_vcpu *vcpu, __kvm_mmu_refresh_passthrough_bits(vcpu, mmu); } +int kvm_tdp_map_page(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code, + u8 *level); + /* * Check if a given access (described through the I/D, W/R and U/S bits of a * page fault error code pfec) causes a permission fault with the given PTE diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 7fbcfc97edcc..fb2149d16f8d 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -4646,6 +4646,38 @@ int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) return direct_page_fault(vcpu, fault); } +int kvm_tdp_map_page(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code, + u8 *level) +{ + int r; + + /* Restrict to TDP page fault. */ + if (vcpu->arch.mmu->page_fault != kvm_tdp_page_fault) + return -EOPNOTSUPP; + + r = __kvm_mmu_do_page_fault(vcpu, gpa, error_code, true, NULL, level); + if (r < 0) + return r; + + switch (r) { + case RET_PF_RETRY: + return -EAGAIN; + + case RET_PF_FIXED: + case RET_PF_SPURIOUS: + return 0; + + case RET_PF_EMULATE: + return -EINVAL; + + case RET_PF_CONTINUE: + case RET_PF_INVALID: + default: + WARN_ON_ONCE(r); + return -EIO; + } +} + static void nonpaging_init_context(struct kvm_mmu *context) { context->page_fault = nonpaging_page_fault; From patchwork Wed Apr 17 15:34:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13633528 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CBAB61482E0 for ; Wed, 17 Apr 2024 15:34:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368100; cv=none; b=K1WWN29JeTR0nC4g6Va7oFa6X9Jw5jb/D9/boChYXuWOX0b48GDr3n+UHgXch0W/4w6QMdm/pUliuwvDKtQCfkDS8Vgrs4aVDTfcUJnAniDJ3RpqgAsYI761jt9HoIPYNGjOi2mcr0Wm3ixwgrh8HciZBziFKdpSG41zpt6D39c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368100; c=relaxed/simple; bh=G4BeGUCOTVOkjx4yq6ODKlpxEE4XU7Y7irIUQ5bbs2g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OZkqNCjjFPNaG1uTCQ0DWeyZJUcY18bYsIRgcUYBcOFC6AnRn9Uex460lJvIvpP1QsTmapLA9ShCBNZ6BRPcTppMu9xpaxs13N6XXjStW21bk1cyKperxmVdbD3HFR/JT3Y2NfMiwYu2huBlC6xwd+LgnX/STau/4XNCyIqnJT4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=TWTl87f1; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="TWTl87f1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713368096; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Z/d1W9bLkoHDklV8ryGGFJMux2mNI4+NsiCtwVFElLs=; b=TWTl87f1PqTJIc/tn3BZOYNjcWSFptz1CRpcb1KprHIrVSPjJUH0gu5CtGIXRh/m0FxYs1 3CW2CFoSMugWXSXxH9Sx2z17/PDuDtqyt+uAiT6c0tCsjzRoEUxuQ4+ymusAonMtnsx+HP Ine4+PKgmdEDCPKHKAQ/zcD7aHtAz4Q= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-448-FMU6Mw0mOXiB4R0LUQNZSA-1; Wed, 17 Apr 2024 11:34:53 -0400 X-MC-Unique: FMU6Mw0mOXiB4R0LUQNZSA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id AA724188ACB0; Wed, 17 Apr 2024 15:34:52 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 79DF4581CD; Wed, 17 Apr 2024 15:34:52 +0000 (UTC) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, xiaoyao.li@intel.com, binbin.wu@linux.intel.com, seanjc@google.com, rick.p.edgecombe@intel.com Subject: [PATCH 6/7] KVM: x86: Implement kvm_arch_vcpu_map_memory() Date: Wed, 17 Apr 2024 11:34:49 -0400 Message-ID: <20240417153450.3608097-7-pbonzini@redhat.com> In-Reply-To: <20240417153450.3608097-1-pbonzini@redhat.com> References: <20240417153450.3608097-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 From: Isaku Yamahata Wire KVM_MAP_MEMORY ioctl to kvm_mmu_map_tdp_page() to populate guest memory. When KVM_CREATE_VCPU creates vCPU, it initializes the x86 KVM MMU part by kvm_mmu_create() and kvm_init_mmu(). vCPU is ready to invoke the KVM page fault handler. Signed-off-by: Isaku Yamahata Message-ID: <7138a3bc00ea8d3cbe0e59df15f8c22027005b59.1712785629.git.isaku.yamahata@intel.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/Kconfig | 1 + arch/x86/kvm/x86.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 7632fe6e4db9..e58360d368ec 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -44,6 +44,7 @@ config KVM select KVM_VFIO select HAVE_KVM_PM_NOTIFIER if PM select KVM_GENERIC_HARDWARE_ENABLING + select KVM_GENERIC_MAP_MEMORY help Support hosting fully virtualized guest machines using hardware virtualization extensions. You will need a fairly recent diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 83b8260443a3..f84c75c2a47f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4715,6 +4715,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_MEMORY_FAULT_INFO: r = 1; break; + case KVM_CAP_MAP_MEMORY: + r = tdp_enabled; + break; case KVM_CAP_EXIT_HYPERCALL: r = KVM_EXIT_HYPERCALL_VALID_MASK; break; @@ -5867,6 +5870,46 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, } } +int kvm_arch_vcpu_map_memory(struct kvm_vcpu *vcpu, + struct kvm_map_memory *mapping) +{ + u64 mapped, end, error_code = 0; + u8 level = PG_LEVEL_4K; + int r; + + /* + * Shadow paging uses GVA for kvm page fault. The first implementation + * supports GPA only to avoid confusion. + */ + if (!tdp_enabled) + return -EOPNOTSUPP; + + /* + * reload is efficient when called repeatedly, so we can do it on + * every iteration. + */ + kvm_mmu_reload(vcpu); + + if (kvm_arch_has_private_mem(vcpu->kvm) && + kvm_mem_is_private(vcpu->kvm, gpa_to_gfn(mapping->base_address))) + error_code |= PFERR_PRIVATE_ACCESS; + + r = kvm_tdp_map_page(vcpu, mapping->base_address, error_code, &level); + if (r) + return r; + + /* + * level can be more than the alignment of mapping->base_address if + * the mapping can use a huge page. + */ + end = (mapping->base_address & KVM_HPAGE_MASK(level)) + + KVM_HPAGE_SIZE(level); + mapped = min(mapping->size, end - mapping->base_address); + mapping->size -= mapped; + mapping->base_address += mapped; + return r; +} + long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { From patchwork Wed Apr 17 15:34:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13633527 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DF57A1482F1 for ; Wed, 17 Apr 2024 15:34:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368100; cv=none; b=DR12zUkQViUDdSmI1l2K3O/tPXVCHWYMrt0QZoQ0mTOojpbJN3N6gs50WzIITd8M3FedpkjroWP2b8iQ8NTEQMi9GLuR91v28UQVlkE4efLOiRY7ebzTVH0/PCymAkXPRBZPpzKF5yj4x79Vj/P9B4By/pY2LcEx/8jcNZm6934= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713368100; c=relaxed/simple; bh=2OBq+23pCM3PkNKzgJeo539rzBtPFjT7bbLCv5kFpa8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lAn7+C5+5+j1NRbGKTaZi29kqA9tbS0tltHhtxt5ArbmLWHP3sWI37R0wd1iX9+dxn9ZUIOMwx+mpxYQ3kYQn0hZTZvLKS/0DfUpKiy+W4EcFNy3T/9nmIcbVhqElKHPS9bcwQstCj/h0coLEAw99uMEwHxo4q2QlVq/X7COGRc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ZKLHA6y5; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ZKLHA6y5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713368097; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QOJHbzxI/eRU/siHQ5cJPVsyiTsUtZ2Sjfr3m4DsPPE=; b=ZKLHA6y5Em9jIkI007jwLsufIX5asPuJex3nfWPJDOcgY2h2Xar7FPpm83xYamxxIxefCI nZ4NP4pBAALjvOSzajRTp5ACyicvefPQAtlwfxIEtFhtLH1hqrrmoEZSd/h5kzTHpMSVHr VrBfYF9yaEnjDEK2XJeMPOHJyNz4yYI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-481-Xm1epxzaN_Oi-9_nzuTWtw-1; Wed, 17 Apr 2024 11:34:53 -0400 X-MC-Unique: Xm1epxzaN_Oi-9_nzuTWtw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E31B49C2F24; Wed, 17 Apr 2024 15:34:52 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id B2EC8581CD; Wed, 17 Apr 2024 15:34:52 +0000 (UTC) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, xiaoyao.li@intel.com, binbin.wu@linux.intel.com, seanjc@google.com, rick.p.edgecombe@intel.com Subject: [PATCH 7/7] KVM: selftests: x86: Add test for KVM_MAP_MEMORY Date: Wed, 17 Apr 2024 11:34:50 -0400 Message-ID: <20240417153450.3608097-8-pbonzini@redhat.com> In-Reply-To: <20240417153450.3608097-1-pbonzini@redhat.com> References: <20240417153450.3608097-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 From: Isaku Yamahata Add a test case to exercise KVM_MAP_MEMORY and run the guest to access the pre-populated area. It tests KVM_MAP_MEMORY ioctl for KVM_X86_DEFAULT_VM and KVM_X86_SW_PROTECTED_VM. Signed-off-by: Isaku Yamahata Message-ID: <32427791ef42e5efaafb05d2ac37fa4372715f47.1712785629.git.isaku.yamahata@intel.com> Signed-off-by: Paolo Bonzini --- tools/include/uapi/linux/kvm.h | 8 ++ tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/map_memory_test.c | 135 ++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 tools/testing/selftests/kvm/map_memory_test.c diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index c3308536482b..69a43c5ae33c 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h @@ -2227,4 +2227,12 @@ struct kvm_create_guest_memfd { __u64 reserved[6]; }; +#define KVM_MAP_MEMORY _IOWR(KVMIO, 0xd5, struct kvm_map_memory) + +struct kvm_map_memory { + __u64 base_address; + __u64 size; + __u64 flags; +}; + #endif /* __LINUX_KVM_H */ diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 871e2de3eb05..41def90f7dfb 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -144,6 +144,7 @@ TEST_GEN_PROGS_x86_64 += set_memory_region_test TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test TEST_GEN_PROGS_x86_64 += system_counter_offset_test +TEST_GEN_PROGS_x86_64 += map_memory_test # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86_64 += x86_64/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/map_memory_test.c b/tools/testing/selftests/kvm/map_memory_test.c new file mode 100644 index 000000000000..e52e33145f01 --- /dev/null +++ b/tools/testing/selftests/kvm/map_memory_test.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024, Intel, Inc + * + * Author: + * Isaku Yamahata + */ +#include + +#include +#include +#include + +/* Arbitrarily chosen values */ +#define TEST_SIZE (SZ_2M + PAGE_SIZE) +#define TEST_NPAGES (TEST_SIZE / PAGE_SIZE) +#define TEST_SLOT 10 + +static void guest_code(uint64_t base_gpa) +{ + volatile uint64_t val __used; + int i; + + for (i = 0; i < TEST_NPAGES; i++) { + uint64_t *src = (uint64_t *)(base_gpa + i * PAGE_SIZE); + + val = *src; + } + + GUEST_DONE(); +} + +static void map_memory(struct kvm_vcpu *vcpu, u64 base_address, u64 size, + bool should_succeed) +{ + struct kvm_map_memory mapping = { + .base_address = base_address, + .size = size, + .flags = 0, + }; + int ret; + + do { + ret = __vcpu_ioctl(vcpu, KVM_MAP_MEMORY, &mapping); + } while (ret >= 0 && mapping.size); + + if (should_succeed) + __TEST_ASSERT_VM_VCPU_IOCTL(!ret, "KVM_MAP_MEMORY", ret, vcpu->vm); + else + /* No memory slot causes RET_PF_EMULATE. it results in -EINVAL. */ + __TEST_ASSERT_VM_VCPU_IOCTL(ret && errno == EINVAL, + "KVM_MAP_MEMORY", ret, vcpu->vm); +} + +static void __test_map_memory(unsigned long vm_type, bool private) +{ + const struct vm_shape shape = { + .mode = VM_MODE_DEFAULT, + .type = vm_type, + }; + struct kvm_vcpu *vcpu; + struct kvm_run *run; + struct kvm_vm *vm; + struct ucall uc; + + uint64_t guest_test_phys_mem; + uint64_t guest_test_virt_mem; + uint64_t alignment, guest_page_size; + + vm = vm_create_shape_with_one_vcpu(shape, &vcpu, guest_code); + + alignment = guest_page_size = vm_guest_mode_params[VM_MODE_DEFAULT].page_size; + guest_test_phys_mem = (vm->max_gfn - TEST_NPAGES) * guest_page_size; +#ifdef __s390x__ + alignment = max(0x100000UL, guest_page_size); +#else + alignment = SZ_2M; +#endif + guest_test_phys_mem = align_down(guest_test_phys_mem, alignment); + guest_test_virt_mem = guest_test_phys_mem; + + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, + guest_test_phys_mem, TEST_SLOT, TEST_NPAGES, + private ? KVM_MEM_GUEST_MEMFD : 0); + virt_map(vm, guest_test_virt_mem, guest_test_phys_mem, TEST_NPAGES); + + if (private) + vm_mem_set_private(vm, guest_test_phys_mem, TEST_SIZE); + map_memory(vcpu, guest_test_phys_mem, SZ_2M, true); + map_memory(vcpu, guest_test_phys_mem + SZ_2M, PAGE_SIZE, true); + map_memory(vcpu, guest_test_phys_mem + TEST_SIZE, PAGE_SIZE, false); + + vcpu_args_set(vcpu, 1, guest_test_virt_mem); + vcpu_run(vcpu); + + run = vcpu->run; + TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, + "Wanted KVM_EXIT_IO, got exit reason: %u (%s)", + run->exit_reason, exit_reason_str(run->exit_reason)); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + break; + case UCALL_DONE: + break; + default: + TEST_FAIL("Unknown ucall 0x%lx.", uc.cmd); + break; + } + + kvm_vm_free(vm); +} + +static void test_map_memory(unsigned long vm_type, bool private) +{ + if (vm_type && !(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(vm_type))) { + pr_info("Skipping tests for vm_type 0x%lx\n", vm_type); + return; + } + + __test_map_memory(vm_type, private); +} + +int main(int argc, char *argv[]) +{ + TEST_REQUIRE(kvm_check_cap(KVM_CAP_MAP_MEMORY)); + + test_map_memory(0, false); +#ifdef __x86_64__ + test_map_memory(KVM_X86_SW_PROTECTED_VM, false); + test_map_memory(KVM_X86_SW_PROTECTED_VM, true); +#endif + return 0; +}