On Mon, 31 Aug 2026 at 01:25, Ackerley Tng via B4 Relay <[email protected]> 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]>
Reviewed-by: Fuad Tabba <[email protected]> Cheers, /fuad > --- > 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; > > xa_store_range(&f->bindings, start, end - 1, slot, GFP_KERNEL); > > -- > 2.55.0.897.gb25b4bd76c-goog > >
