From: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
To: linux-coco@lists.linux.dev
Cc: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>,
Ackerley Tng <ackerleytng@google.com>,
David Woodhouse <dwmw2@infradead.org>,
David Hildenbrand <david@kernel.org>,
Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>,
Alexey Kardashevskiy <aik@amd.com>,
Xu Yilun <yilun.xu@linux.intel.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Steven Price <steven.price@arm.com>,
Fred Griffoul <griffoul@gmail.com>,
iommu@lists.linux.dev, kvm@vger.kernel.org,
patches@lists.linux.dev
Subject: [RFC PATCH v5 05/16] KVM: guest_memfd: Let providers validate attribute changes
Date: Thu, 12 Nov 2026 13:11:09 +0530 [thread overview]
Message-ID: <20261112074120.1570072-6-aneesh.kumar@kernel.org> (raw)
In-Reply-To: <20261112074120.1570072-1-aneesh.kumar@kernel.org>
Call prepare_attributes() before invalidating guest mappings or changing
file attributes. Remove host mappings first when converting to private,
so folio validation can check for outstanding references.
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
include/linux/guest_memfd.h | 9 ++++++++
virt/kvm/guest_memfd.c | 43 ++++++++++++++++++++++++-------------
2 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/include/linux/guest_memfd.h b/include/linux/guest_memfd.h
index d3b153a3d891..06f094a2fd49 100644
--- a/include/linux/guest_memfd.h
+++ b/include/linux/guest_memfd.h
@@ -42,6 +42,13 @@ struct guest_memfd_handle {
* @unlock: Release the provider lock taken by lock(). Called after guest
* invalidation ends and any successful attribute publication, with
* the inode invalidate lock still held.
+ * @prepare_attributes: Optional memory validation before conversion, under
+ * the inode invalidate lock for write, before taking
+ * the provider lock or starting guest invalidation. Host mappings have
+ * been removed for private conversion. Set @err_index on
+ * failure; it initially points to the range start. NULL
+ * selects folio validation for folio providers; for
+ * other providers, NULL skips this validation.
* @alloc_folio: Allocate an uninserted folio for a given index and NUMA policy.
* Must return a pointer to a struct folio on success, or an
* ERR_PTR() error code on failure. Must never return NULL.
@@ -77,6 +84,8 @@ struct guest_memfd_provider_operations {
void (*release)(void *provider);
void (*lock)(void *provider);
void (*unlock)(void *provider);
+ int (*prepare_attributes)(struct inode *inode, void *provider, pgoff_t start,
+ size_t nr_pages, u64 memory_attrs, pgoff_t *err_index);
struct folio *(*alloc_folio)(void *provider, pgoff_t index,
struct mempolicy *mpol);
void (*invalidate_folio)(void *provider, struct folio *folio);
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index ad9cc1bbe5d7..c69a8b7d046c 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -54,6 +54,8 @@ static int gmem_folio_get_pfn(struct inode *inode, void *provider, pgoff_t index
struct guest_memfd_handle *handle);
static int gmem_folio_lookup_pfn_range(struct inode *inode, void *provider,
pgoff_t index, unsigned long *pfn, size_t *nr_pages, u64 *pfn_attrs);
+static int gmem_folio_prepare_attributes(struct inode *inode, void *provider,
+ pgoff_t start, size_t nr_pages, u64 attrs, pgoff_t *err_index);
static __always_inline struct gmem_inode *GMEM_I(struct inode *inode)
{
@@ -91,6 +93,7 @@ static const struct guest_memfd_provider_operations gmem_native_provider_ops = {
.alloc_folio = gmem_native_alloc_folio,
.get_pfn = gmem_folio_get_pfn,
.lookup_pfn_range = gmem_folio_lookup_pfn_range,
+ .prepare_attributes = gmem_folio_prepare_attributes,
};
static bool gmem_provider_ops_valid(struct gmem_inode *gi,
@@ -136,6 +139,8 @@ static void gmem_provider_init_ops(struct gmem_inode *gi,
gi->provider_operations.get_pfn = gmem_folio_get_pfn;
gi->provider_operations.lookup_pfn_range = gmem_folio_lookup_pfn_range;
}
+ if (!ops->prepare_attributes)
+ gi->provider_operations.prepare_attributes = gmem_folio_prepare_attributes;
}
gi->provider_ops = &gi->provider_operations;
}
@@ -1095,6 +1100,16 @@ static bool kvm_gmem_has_outstanding_references(struct inode *inode,
return false;
}
+static int gmem_folio_prepare_attributes(struct inode *inode, void *provider,
+ pgoff_t start, size_t nr_pages, u64 attrs, pgoff_t *err_index)
+{
+ if ((attrs & KVM_MEMORY_ATTRIBUTE_PRIVATE) &&
+ kvm_gmem_has_outstanding_references(inode, start, nr_pages, err_index))
+ return -EAGAIN;
+
+ return 0;
+}
+
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
static void kvm_gmem_make_shared(struct inode *inode, pgoff_t start, pgoff_t end)
{
@@ -1169,6 +1184,7 @@ static int __kvm_gmem_set_attributes(struct inode *inode, pgoff_t start,
mt = &gi->attributes;
+ *err_index = start;
filemap_invalidate_lock(mapping);
if (kvm_gmem_range_has_attributes(inode, start, nr_pages, attrs))
@@ -1176,26 +1192,23 @@ static int __kvm_gmem_set_attributes(struct inode *inode, pgoff_t start,
mas_init(&mas, mt, start);
r = kvm_gmem_mas_preallocate(&mas, attrs, start, nr_pages);
- if (r) {
- *err_index = start;
+ if (r)
goto out;
- }
- if (to_private) {
- /*
- * Forcefully unmap the pages from all userspace page tables,
- * and then verify there are no outstanding references, e.g.
- * acquired via GUP or similar. Tell userspace to try again if
- * there are outstanding references and hope that whatever has
- * pinned the page will put its reference "soon".
- */
+ /*
+ * Before private conversion, forcefully unmap the pages from all userspace
+ * page tables. The folio provider then checks for outstanding references,
+ * e.g. from GUP, and returns -EAGAIN so userspace can retry after those
+ * references are released.
+ */
+ if (to_private)
unmap_mapping_pages(mapping, start, nr_pages, false);
- if (!kvm_gmem_is_pfn_mode(gi) &&
- kvm_gmem_has_outstanding_references(inode, start, nr_pages,
- err_index)) {
+ if (gi->provider_ops->prepare_attributes) {
+ r = gi->provider_ops->prepare_attributes(inode, gi->provider, start,
+ nr_pages, attrs, err_index);
+ if (r) {
mas_destroy(&mas);
- r = -EAGAIN;
goto out;
}
}
--
2.43.0
next prev parent reply other threads:[~2026-11-12 7:41 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 7:41 [RFC PATCH v5 00/16] KVM: guest_memfd: Add a common framework for device memory providers Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 01/16] KVM: guest_memfd: Add a handle for provider PFNs Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 02/16] KVM: guest_memfd: Get PFNs through common provider operations Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 03/16] KVM: guest_memfd: Let providers coordinate mapping changes Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 04/16] KVM: guest_memfd: Add provider PFN range lookup Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` Aneesh Kumar K.V (Arm) [this message]
2026-11-12 7:41 ` [RFC PATCH v5 06/16] KVM: guest_memfd: Share memory through provider " Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 07/16] KVM: guest_memfd: Release and revoke memory through provider operations Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 08/16] KVM: guest_memfd: Use provider operations for fallocate allocation Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 09/16] KVM: guest_memfd: Use provider operations for host mappings and faults Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 10/16] KVM: guest_memfd: Let providers prepare memory regions Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 11/16] KVM: guest_memfd: Pass KVM explicitly to provider attach Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 12/16] KVM: guest_memfd: Support devices through common provider operations Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 13/16] KVM: guest_memfd: Notify providers after private attribute updates Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 14/16] KVM: guest_memfd: Enable shared host mappings for device providers Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 15/16] KVM: guest_memfd: Notify providers during file release Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 16/16] KVM: guest_memfd: Invalidate mappings before memslot unbind Aneesh Kumar K.V (Arm)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261112074120.1570072-6-aneesh.kumar@kernel.org \
--to=aneesh.kumar@kernel.org \
--cc=ackerleytng@google.com \
--cc=aik@amd.com \
--cc=catalin.marinas@arm.com \
--cc=david@kernel.org \
--cc=dwmw2@infradead.org \
--cc=griffoul@gmail.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=kevin.tian@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=patches@lists.linux.dev \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
--cc=steven.price@arm.com \
--cc=suzuki.poulose@arm.com \
--cc=yilun.xu@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.