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 03/16] KVM: guest_memfd: Let providers coordinate mapping changes
Date: Thu, 12 Nov 2026 13:11:07 +0530 [thread overview]
Message-ID: <20261112074120.1570072-4-aneesh.kumar@kernel.org> (raw)
In-Reply-To: <20261112074120.1570072-1-aneesh.kumar@kernel.org>
Add optional paired lock() and unlock() callbacks so providers can prevent
memory changes during guest invalidation and attribute conversion. Reject
providers that supply only one callback.
Take the provider lock with the inode invalidate lock held for write,
before guest invalidation. Release it after invalidation and any
successful attribute publication. Use the same locking for revocation
and final inode cleanup.
This lock is separate from the lock taken by get_pfn() for an individual
PFN. Existing providers can omit both callbacks.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: kvm@vger.kernel.org
Cc: patches@lists.linux.dev
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
include/linux/guest_memfd.h | 8 ++++++
virt/kvm/guest_memfd.c | 50 +++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/include/linux/guest_memfd.h b/include/linux/guest_memfd.h
index 3d84fd0adec1..b63ca59773f9 100644
--- a/include/linux/guest_memfd.h
+++ b/include/linux/guest_memfd.h
@@ -36,6 +36,12 @@ struct guest_memfd_handle {
* @attach: Attach to a resource file, perform filesystem-specific validation,
* and return an opaque provider context.
* @release: Release provider context and unpin any resources.
+ * @lock: Optional provider lock for mapping and attribute changes. Called
+ * with the inode invalidate lock held for write, before guest
+ * invalidation starts.
+ * @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.
* @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.
@@ -66,6 +72,8 @@ struct guest_memfd_handle {
struct guest_memfd_provider_operations {
void *(*attach)(struct inode *gmem_inode, struct file *resource_file);
void (*release)(void *provider);
+ void (*lock)(void *provider);
+ void (*unlock)(void *provider);
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 026a7bd0fe76..5fda14a53488 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -96,6 +96,9 @@ static bool gmem_provider_ops_valid(struct gmem_inode *gi,
if (!ops || !ops->attach)
return false;
+ if (!!ops->lock != !!ops->unlock)
+ return false;
+
if (ops == &gmem_native_provider_ops)
return !kvm_gmem_is_pfn_mode(gi);
@@ -269,6 +272,42 @@ static void gmem_provider_put_pfn_range(struct gmem_inode *gi, pgoff_t index,
gi->provider_ops->put_pfn_range(gi->provider, index, nr_pages);
}
+/**
+ * gmem_provider_lock_updates - Take the provider lock for memory updates
+ * @gi: guest_memfd inode containing the attached provider
+ *
+ * Prevent providers from moving or reassigning memory during guest
+ * invalidation, attribute conversion/publication, revocation, unbinding and
+ * final cleanup. Pair with gmem_provider_unlock_updates(). Providers
+ * requiring no additional locking may omit both lock() and unlock().
+ *
+ * This is separate from locking inside get_pfn(); it neither acquires a PFN
+ * reference nor pairs with gmem_unlock_handle().
+ *
+ * Caller holds the inode invalidate lock for write through
+ * gmem_provider_unlock_updates().
+ */
+static void gmem_provider_lock_updates(struct gmem_inode *gi)
+{
+ if (gi->provider_ops && gi->provider_ops->lock)
+ gi->provider_ops->lock(gi->provider);
+}
+
+/**
+ * gmem_provider_unlock_updates - Release the provider lock for memory updates
+ * @gi: guest_memfd inode passed to gmem_provider_lock_updates()
+ *
+ * Release the provider lock after guest invalidation and any attribute
+ * publication are complete. This does not unlock or put an individual PFN reference.
+ *
+ * Caller holds the inode invalidate lock for write.
+ */
+static void gmem_provider_unlock_updates(struct gmem_inode *gi)
+{
+ if (gi->provider_ops && gi->provider_ops->unlock)
+ gi->provider_ops->unlock(gi->provider);
+}
+
static void gmem_provider_release(struct gmem_inode *gi)
{
if (gi->provider_ops && gi->provider_ops->release)
@@ -506,6 +545,7 @@ static int __kvm_gmem_revoke(struct inode *inode, pgoff_t start,
{
enum kvm_gfn_range_filter filter = kvm_gmem_get_all_gfns_filter(inode);
pgoff_t max_pages = i_size_read(inode) >> PAGE_SHIFT;
+ struct gmem_inode *gi = GMEM_I(inode);
loff_t offset, len;
pgoff_t end;
@@ -526,6 +566,8 @@ static int __kvm_gmem_revoke(struct inode *inode, pgoff_t start,
*/
filemap_invalidate_lock(inode->i_mapping);
+ gmem_provider_lock_updates(gi);
+
kvm_gmem_invalidate_start(inode, start, end, filter);
if (kvm_gmem_is_pfn_mode(GMEM_I(inode))) {
@@ -543,6 +585,7 @@ static int __kvm_gmem_revoke(struct inode *inode, pgoff_t start,
}
kvm_gmem_invalidate_end(inode, start, end);
+ gmem_provider_unlock_updates(gi);
filemap_invalidate_unlock(inode->i_mapping);
@@ -1118,6 +1161,8 @@ static int __kvm_gmem_set_attributes(struct inode *inode, pgoff_t start,
* checks and can proceed to do guest-breaking changes.
*/
+ gmem_provider_lock_updates(gi);
+
filter = to_private ? KVM_FILTER_SHARED : KVM_FILTER_PRIVATE;
kvm_gmem_invalidate_start(inode, start, end, filter);
@@ -1127,6 +1172,7 @@ static int __kvm_gmem_set_attributes(struct inode *inode, pgoff_t start,
mas_store_prealloc(&mas, xa_mk_value(attrs));
kvm_gmem_invalidate_end(inode, start, end);
+ gmem_provider_unlock_updates(gi);
out:
filemap_invalidate_unlock(mapping);
return r;
@@ -1793,8 +1839,12 @@ static void kvm_gmem_destroy_inode(struct inode *inode)
if (gi->provider_ops && kvm_gmem_is_pfn_mode(gi)) {
pgoff_t nr_pages = i_size_read(inode) >> PAGE_SHIFT;
+ filemap_invalidate_lock(inode->i_mapping);
+ gmem_provider_lock_updates(gi);
kvm_gmem_pfn_reclaim(gi, 0, nr_pages);
gmem_provider_put_pfn_range(gi, 0, nr_pages);
+ gmem_provider_unlock_updates(gi);
+ filemap_invalidate_unlock(inode->i_mapping);
}
gmem_provider_release(gi);
--
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 ` Aneesh Kumar K.V (Arm) [this message]
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 ` [RFC PATCH v5 05/16] KVM: guest_memfd: Let providers validate attribute changes Aneesh Kumar K.V (Arm)
2026-11-12 7:41 ` [RFC PATCH v5 06/16] KVM: guest_memfd: Share memory through provider range lookup 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-4-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox