Track whether a guest_memfd-backed memslot supports shared memory within the memslot itself, using the flags field. The top half of memslot flags is reserved for internal use in KVM. Add a flag there to track shared memory support. This saves the caller from having to check the guest_memfd-backed file for this support, a potentially more expensive operation due to the need to get/put the file. Suggested-by: David Hildenbrand <david@xxxxxxxxxx> Signed-off-by: Fuad Tabba <tabba@xxxxxxxxxx> --- include/linux/kvm_host.h | 11 ++++++++++- virt/kvm/guest_memfd.c | 8 ++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index ba83547e62b0..edb3795a64b9 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -54,7 +54,8 @@ * used in kvm, other bits are visible for userspace which are defined in * include/uapi/linux/kvm.h. */ -#define KVM_MEMSLOT_INVALID (1UL << 16) +#define KVM_MEMSLOT_INVALID (1UL << 16) +#define KVM_MEMSLOT_SUPPORTS_SHARED (1UL << 17) /* * Bit 63 of the memslot generation number is an "update in-progress flag", @@ -2502,6 +2503,14 @@ static inline void kvm_prepare_memory_fault_exit(struct kvm_vcpu *vcpu, vcpu->run->memory_fault.flags |= KVM_MEMORY_EXIT_FLAG_PRIVATE; } +static inline bool kvm_gmem_memslot_supports_shared(const struct kvm_memory_slot *slot) +{ + if (!IS_ENABLED(CONFIG_KVM_GMEM_SHARED_MEM)) + return false; + + return slot->flags & KVM_MEMSLOT_SUPPORTS_SHARED; +} + #ifdef CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES static inline unsigned long kvm_get_memory_attributes(struct kvm *kvm, gfn_t gfn) { diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c index 5d34712f64fc..9ded8d5139ee 100644 --- a/virt/kvm/guest_memfd.c +++ b/virt/kvm/guest_memfd.c @@ -555,6 +555,7 @@ int kvm_gmem_bind(struct kvm *kvm, struct kvm_memory_slot *slot, loff_t size = slot->npages << PAGE_SHIFT; unsigned long start, end; struct kvm_gmem *gmem; + bool supports_shared; struct inode *inode; struct file *file; int r = -EINVAL; @@ -578,8 +579,9 @@ int kvm_gmem_bind(struct kvm *kvm, struct kvm_memory_slot *slot, offset + size > i_size_read(inode)) goto err; - if (kvm_gmem_supports_shared(inode) && - !kvm_arch_supports_gmem_shared_mem(kvm)) + supports_shared = kvm_gmem_supports_shared(inode); + + if (supports_shared && !kvm_arch_supports_gmem_shared_mem(kvm)) goto err; filemap_invalidate_lock(inode->i_mapping); @@ -600,6 +602,8 @@ int kvm_gmem_bind(struct kvm *kvm, struct kvm_memory_slot *slot, */ WRITE_ONCE(slot->gmem.file, file); slot->gmem.pgoff = start; + if (supports_shared) + slot->flags |= KVM_MEMSLOT_SUPPORTS_SHARED; xa_store_range(&gmem->bindings, start, end - 1, slot, GFP_KERNEL); filemap_invalidate_unlock(inode->i_mapping); -- 2.49.0.1164.gab81da1b16-goog