Yan Zhao <[email protected]> writes: > On Sun, Aug 30, 2026 at 05:25:13PM -0700, Ackerley Tng via B4 Relay wrote: >> From: Ackerley Tng <[email protected]> >> >> If a guest_memfd memslot is created but the guest_memfd does not have the >> GUEST_MEMFD_FLAG_MMAP set, KVM still fulfils guest faults by looking up the >> memslot's userspace_addr. >> >> Set KVM_MEMSLOT_GMEM_ONLY if in-place conversion is enabled so that the >> guest_memfd's memory will be used for both shared and private memory. With >> in-place conversion, guest_memfd will be the only backing memory for the >> memslot. >> >> No validation is performed to require userspace_addr to be a mapping from >> the associated guest_memfd because even after validation, userspace is free >> to remap something else at the provided userspace_addr. >> >> userspace_addr will still be used by functions like kvm_read_guest(), and >> if userspace_addr does not match up with the corresponding memory in the >> memslot's guest_memfd (whether userspace_addr points to the wrong offset or >> some non-guest_memfd memory, etc), that is a user error. >> >> Requiring both shared and private memory to come from the only associated >> guest_memfd simplifies invalidation in stage 2 page tables. On a PUNCH_HOLE >> operation on a guest_memfd, the invalidation is now guaranteed to be >> invalidating only memory mapped from the given guest_memfd. >> >> Suggested-by: Sean Christopherson <[email protected]> >> Signed-off-by: Ackerley Tng <[email protected]> >> --- >> Documentation/virt/kvm/api.rst | 22 ++++++++++++++-------- >> virt/kvm/guest_memfd.c | 2 +- >> 2 files changed, 15 insertions(+), 9 deletions(-) >> >> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst >> index 90a29424c54c8..668886f50024d 100644 >> --- a/Documentation/virt/kvm/api.rst >> +++ b/Documentation/virt/kvm/api.rst >> @@ -6381,10 +6381,16 @@ mapping for userspace_addr is not required to be >> valid/populated at the time of >> KVM_SET_USER_MEMORY_REGION2, e.g. shared memory can be lazily >> mapped/allocated >> on-demand. >> >> -When mapping a gfn into the guest, KVM selects shared vs. private, i.e >> consumes >> -userspace_addr vs. guest_memfd, based on the state in guest_memfd, which is >> the >> -sole authority on private vs. shared memory. See >> :ref:`KVM_CREATE_GUEST_MEMFD` >> -to find out more about the creation-time shared/private status. >> +When mapping a gfn into the guest, guest faults are always serviced from >> +guest_memfd regardless of whether memory is shared or private. KVM >> determines >> +shared vs. private based on the state in guest_memfd, which is the sole >> +authority on private vs. shared memory. See :ref:`KVM_CREATE_GUEST_MEMFD` >> to >> +find out more about the creation-time shared/private status. >> + >> +userspace_addr is expected to be the mmap()-ed address corresponding to the >> +right offset within the guest_memfd. Any mismatch between userspace_addr and >> +guest_memfd is not validated and is a user error. userspace_addr is only >> used >> +for host-side guest accesses such as kvm_read_guest(). >> >> If in-place conversion is disabled, KVM selects shared vs. private, i.e >> consumes >> userspace_addr vs. guest_memfd, based on the gfn's >> KVM_MEMORY_ATTRIBUTE_PRIVATE >> @@ -6490,10 +6496,10 @@ specified via KVM_CREATE_GUEST_MEMFD. Currently >> defined flags: >> page tables. Private memory cannot. >> ============================ >> ================================================ >> >> -When the KVM MMU performs a PFN lookup to service a guest fault and the >> backing >> -guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be >> -consumed from guest_memfd, regardless of whether it is a shared or a private >> -fault. >> +When the KVM MMU performs a PFN lookup to service a guest fault, the fault >> will >> +always be consumed from guest_memfd, regardless of whether it is a shared >> or a >> +private fault (unless in-place conversion is disabled and the backing >> +guest_memfd does not have the GUEST_MEMFD_FLAG_MMAP flag set). >> >> See KVM_SET_USER_MEMORY_REGION2 for additional details. >> >> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c >> index 0afe1468d2d9d..e41802944756b 100644 >> --- a/virt/kvm/guest_memfd.c >> +++ b/virt/kvm/guest_memfd.c >> @@ -746,7 +746,7 @@ int kvm_gmem_bind(struct kvm *kvm, struct >> kvm_memory_slot *slot, >> */ >> WRITE_ONCE(slot->gmem.file, file); >> slot->gmem.pgoff = start; >> - if (kvm_gmem_supports_mmap(inode)) >> + if (gmem_in_place_conversion || kvm_gmem_supports_mmap(inode)) >> slot->flags |= KVM_MEMSLOT_GMEM_ONLY; > I like this change, which actually enforces in-place conversion -- when > gmem_in_place_conversion is true, if userspace sets slot->userspace_addr to a > different backend, the host and guest will no longer be able to access the > same > backend. > > However, since gmem_in_place_conversion is globally and statically specified, > it > essentially disables the coexistence of VMs using out-of-place conversions > when > gmem_in_place_conversion is true. Previously, VMs using out-of-place > conversions > could still boot successfully as long as they switched to using per-gmem > memory > attributes. Is this change intended? >
Yes, this is intended. gmem_in_place_conversion is intended to be global for the entire host. > On a separate note, is kvm_gmem_supports_mmap() still a necessary requirement > for setting KVM_MEMSLOT_GMEM_ONLY? When gmem_in_place_conversion is false, if > userspace mmap()s the gmem but sets slot->userspace_addr to a different > backend, > should the KVM_MEMSLOT_GMEM_ONLY flag still be set? > Before this patch, requesting an MMAP-able gmem will set KVM_MEMSLOT_GMEM_ONLY, so if we change that behavior, we'd be breaking the existing contract. If userspace requests an MMAP-able gmem and then sets up slot->userspace_addr to something else, I think that should be considered user error? MMAP-able => use gmem for all faults has been a thing since before this patch. Just like how there's no good way to check and maintain the validity of the mapped memory behind slot->userspace_addr in relation to the provided guest_memfd, the mapping can't be used to determine whether to set KVM_MEMSLOT_GMEM_ONLY either. >> >> xa_store_range(&f->bindings, start, end - 1, slot, GFP_KERNEL); >> >> -- >> 2.55.0.897.gb25b4bd76c-goog >> >>
