On Thu, 7 May 2026 at 21:22, Ackerley Tng via B4 Relay <[email protected]> wrote: > > From: Ackerley Tng <[email protected]> > > Before conversion, the range filter doesn't really matter: > > + For non-CoCo VMs that use guest_memfd, they have no mirrored tdp, so > KVM_DIRECT_ROOTS would have been invalidated anyway. > + CoCo VMs could not use INIT_SHARED, and there's no conversion support, so > always using KVM_FILTER_PRIVATE would have worked. > > Now with conversion support, update kvm_gmem_get_invalidate_filter to > inspect the memory attributes maple tree for a given range. > > Instead of determining the invalidation filter based on static inode > flags, iterate through the attributes maple tree for the specific range > being invalidated. This allows KVM to identify if the range contains > private pages, shared pages, or both, and set the filter bits > accordingly. > > Update kvm_gmem_invalidate_begin and kvm_gmem_release to pass the range > parameters to the filter helper to ensure invalidation accurately > targets the memory types present in the affected range. > > Signed-off-by: Ackerley Tng <[email protected]>
Reviewed-by: Fuad Tabba <[email protected]> Cheers, /fuad > --- > virt/kvm/guest_memfd.c | 27 ++++++++++++++++++++------- > 1 file changed, 20 insertions(+), 7 deletions(-) > > diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c > index 9f6eebfb68f6b..c9f155c2dc5c5 100644 > --- a/virt/kvm/guest_memfd.c > +++ b/virt/kvm/guest_memfd.c > @@ -193,12 +193,24 @@ static struct folio *kvm_gmem_get_folio(struct inode > *inode, pgoff_t index) > return folio; > } > > -static enum kvm_gfn_range_filter kvm_gmem_get_invalidate_filter(struct inode > *inode) > +static enum kvm_gfn_range_filter kvm_gmem_get_invalidate_filter( > + struct inode *inode, pgoff_t start, pgoff_t end) > { > - if (GMEM_I(inode)->flags & GUEST_MEMFD_FLAG_INIT_SHARED) > - return KVM_FILTER_SHARED; > + struct gmem_inode *gi = GMEM_I(inode); > + enum kvm_gfn_range_filter filter = 0; > + void *entry; > + > + lockdep_assert(mt_lock_is_held(&gi->attributes)); > + > + mt_for_each(&gi->attributes, entry, start, end - 1) { > + filter |= (xa_to_value(entry) & KVM_MEMORY_ATTRIBUTE_PRIVATE) > ? > + KVM_FILTER_PRIVATE : KVM_FILTER_SHARED; > + > + if (filter == (KVM_FILTER_PRIVATE | KVM_FILTER_SHARED)) > + break; > + } > > - return KVM_FILTER_PRIVATE; > + return filter; > } > > static void __kvm_gmem_invalidate_begin(struct gmem_file *f, pgoff_t start, > @@ -244,7 +256,7 @@ static void kvm_gmem_invalidate_begin(struct inode > *inode, pgoff_t start, > enum kvm_gfn_range_filter attr_filter; > struct gmem_file *f; > > - attr_filter = kvm_gmem_get_invalidate_filter(inode); > + attr_filter = kvm_gmem_get_invalidate_filter(inode, start, end); > > kvm_gmem_for_each_file(f, inode) > __kvm_gmem_invalidate_begin(f, start, end, attr_filter); > @@ -367,6 +379,7 @@ static long kvm_gmem_fallocate(struct file *file, int > mode, loff_t offset, > static int kvm_gmem_release(struct inode *inode, struct file *file) > { > struct gmem_file *f = file->private_data; > + enum kvm_gfn_range_filter filter; > struct kvm_memory_slot *slot; > struct kvm *kvm = f->kvm; > unsigned long index; > @@ -398,8 +411,8 @@ static int kvm_gmem_release(struct inode *inode, struct > file *file) > * memory, as its lifetime is associated with the inode, not the file. > */ > end = i_size_read(inode) >> PAGE_SHIFT; > - __kvm_gmem_invalidate_begin(f, 0, end, > - kvm_gmem_get_invalidate_filter(inode)); > + filter = kvm_gmem_get_invalidate_filter(inode, 0, end); > + __kvm_gmem_invalidate_begin(f, 0, end, filter); > __kvm_gmem_invalidate_end(f, 0, end); > > list_del(&f->entry); > > -- > 2.54.0.563.g4f69b47b94-goog > >
