Kernel KVM virtualization development
 help / color / mirror / Atom feed
* [RFC PATCH v3 0/5] KVM: guest_memfd: Add KVM_LINK_GUEST_MEMFD ioctl
@ 2026-10-26  6:44 Tao Gong
  2026-10-26  6:44 ` [RFC PATCH v3 1/5] KVM: guest_memfd: Refactor out kvm_gmem_alloc_file() Tao Gong
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Tao Gong @ 2026-10-26  6:44 UTC (permalink / raw)
  To: kvm, Paolo Bonzini, Sean Christopherson
  Cc: Tao Gong, David Hildenbrand, Ackerley Tng, Ryan Afranji,
	Vishal Annapurve, Sagi Shahar, Jonathan Corbet, Shuah Khan,
	Randy Dunlap, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, linux-doc, linux-kernel,
	linux-kselftest

Hello,

This series adds KVM_LINK_GUEST_MEMFD, a VM ioctl that takes an existing
guest_memfd fd and returns a new guest_memfd fd, bound to the VM on which
the ioctl is invoked, that refers to the same underlying guest_memfd
inode.

It is v3 of the gmem linking RFC [1][2], rebased onto kvm-x86/coco and
reduced to the linking part: the prerequisites from RFC v2 are upstream
now, and the KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM memory context changes will
be posted as a follow-up series on top of this one.

Problem
-------

A guest_memfd is bound to the VM that created it: binding a memslot to
a guest_memfd requires the file's owning VM to be the memslot's VM, and
there is no way to reassign a guest_memfd instance to a different KVM
instance. Passing the fd to another process does not change that.

For VMs with private memory this is a hard limit. Private memory is not
accessible to the host, so it cannot be copied through userspace into a
new VM's guest_memfd. The only way to move a confidential VM to a new VM
instance on the same host (intra-host migration, e.g. to replace the
VMM) is for the new VM to take over the same memory in place.

Design
------

guest_memfd already splits state between the file and the inode: memslot
bindings and the owning VM belong to the file (struct gmem_file), while
the memory itself, its flags and (with in-place conversion) the
shared/private attributes belong to the inode (struct gmem_inode).
Linking creates another file for the same inode, so a second VM can bind
the same guest memory to its memslots without the memory being copied or
going through userspace.

Linking is only allowed between distinct, compatible VMs. On x86 both
VMs must have the same VM type, so that e.g. memory private to a TDX
guest can never be mapped into a non-TDX VM; the generic fallback
requires both VMs to agree on kvm_arch_has_private_mem(). These checks
are defensive; the underlying rule is that KVM must never create a
stage-2 mapping for a confidential VM to another confidential VM's
private memory (see the cutover question below). Linking therefore
does not make private memory shareable between VMs: a private page
remains usable only by the VM that owns it.

Use cases
---------

1. Intra-host migration of VMs with private memory, where the
   destination VM takes over the source VM's guest memory in place:

   a. Userspace passes the source VM's guest_memfd fd to the destination
      VM, e.g. over a Unix socket.
   b. The destination VM calls KVM_LINK_GUEST_MEMFD to get a new fd for
      the same inode, bound to the destination VM.
   c. The destination VM binds the new fd to its memslots with
      KVM_SET_USER_MEMORY_REGION2, at the same offsets as the source.
   d. The remaining VM state is moved with KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM
      (SEV only today; generalized by the follow-up series) and the
      destination VM is run as normal.

   Linking does not revoke the source VM's access; the source simply
   stops using the memory, so every private page keeps a single owner.

2. Sharing guest memory between non-confidential VMs. Both VMs bind the
   same inode at the same time, each through its own file, and the
   memory keeps its guest_memfd properties: neither VMM needs a
   userspace mapping of it, and inode-level operations such as a hole
   punch apply to every linked VM.

   A related use raised in discussion is Nitro Enclaves-style memory
   donation, where a guest gives part of its memory to a sibling VM on
   the same host ("nesting without real nesting").

Alternatives considered
-----------------------

* Passing the VM fd to the new VMM and adding a way to reset the VM
  while keeping its vCPUs and guest_memfds. A KVM VM is bound to the mm
  that created it (VM, vCPU and device ioctls from another process fail
  with -EIO), and its memslots and MMU notifier refer to that address
  space. Re-homing a VM would be considerably more invasive than
  creating a new VM and moving state into it, which is the model KVM
  already uses for SEV intra-host migration
  (KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM); linking extends that model to
  guest_memfd.

* Keeping the memory and its attributes in a "memory provider" and
  creating two independent guest_memfd instances on top of it. The
  guest_memfd inode already plays that role today (page cache,
  attributes and the list of files), so linking gets the same result
  without a new abstraction. If guest_memfd grows a provider layer,
  linking could be expressed on top of it.

Open questions
--------------

* Cutover: for confidential VMs, an explicit cutover that delinks the
  source VM's file at handover, instead of relying on the source to
  stop, may be required for security: it is what guarantees that a
  private page is never usable by two VMs when memory is transferred.
  That would be a separate operation on top of this series;
  non-confidential VMs probably do not need it.

* IOMMU and DMA: whether iommufd page tables and in-flight DMA keep
  working across a handover, and how they would be transferred, is not
  addressed here. The pages themselves stay alive for as long as any
  linked file exists.

* Conversions: with in-place conversion the shared/private attributes
  live on the inode, so a conversion by one VM applies to, and
  invalidates, every linked VM. That is the intended behavior for
  migration, where only one VM is live. Between confidential VMs it is
  also required: with today's hardware they can at best share their
  shared ranges.

Patches 1-2 add the ioctl, patch 3 advertises KVM_CAP_GUEST_MEMFD_LINK,
and patches 4-5 add selftests, including a test that transfers private
memory between two KVM_X86_SW_PROTECTED_VMs.

The series is based on kvm-x86/coco at commit ad06cf5338bc ("KVM:
guest_memfd: Avoid deadlock in error_remove_folio()").

Tested with the KVM selftests (guest_memfd_test, set_memory_region_test,
guest_memfd_conversions_test, private_mem_conversions_test,
private_mem_kvm_exits_test, private_mem_migrate_tests) on an Intel host,
both with and without kvm.gmem_in_place_conversion.

Changes from RFC v2 [2]:
+ Dropped the anon inode and guest_memfd inode patches, which are
  upstream now (anon_inode_make_secure_inode() and commit a63ca4236e67
  ("KVM: guest_memfd: Use guest mem inodes instead of anonymous
  inodes")).
+ Dropped the KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM memory context patches
  and their selftests, to be posted separately on top of this series.
+ Rebased onto kvm-x86/coco: uses struct gmem_file and the inode's
  gmem_file_list, and takes the mapping's invalidate_lock when adding a
  linked file to the list.
+ Renamed kvm_gmem_alloc_view() to kvm_gmem_alloc_file().
+ Only allow linking between compatible VMs (same VM type on x86).
+ Reject non-zero reserved fields and fds larger than INT_MAX.
+ Dropped the i_nlink increment, which had no matching decrement.
+ Take the inode reference before creating the linked file.
+ Added KVM_CAP_GUEST_MEMFD_LINK and gated the selftests on it.
+ Documented KVM_LINK_GUEST_MEMFD in Documentation/virt/kvm/api.rst.
+ Selftests: fixed the negative tests to exercise the intended checks,
  added tests for out-of-range fds, non-zero reserved fields and VM type
  mismatch, and made private_mem_migrate_tests work with in-place
  conversion.

[1] https://lore.kernel.org/all/cover.1691446946.git.ackerleytng@google.com/
[2] https://lore.kernel.org/all/cover.1747368092.git.afranji@google.com/

Ackerley Tng (4):
  KVM: guest_memfd: Refactor out kvm_gmem_alloc_file()
  KVM: guest_memfd: Add ioctl KVM_LINK_GUEST_MEMFD
  KVM: selftests: Add tests for KVM_LINK_GUEST_MEMFD ioctl
  KVM: selftests: Test transferring private memory to another VM

Vishal Annapurve (1):
  KVM: guest_memfd: Advertise support for KVM_LINK_GUEST_MEMFD

 Documentation/virt/kvm/api.rst                |  50 ++++++
 arch/x86/kvm/x86.c                            |  10 ++
 include/linux/kvm_host.h                      |   1 +
 include/uapi/linux/kvm.h                      |   9 ++
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../testing/selftests/kvm/guest_memfd_test.c  |  64 ++++++++
 .../testing/selftests/kvm/include/kvm_util.h  |  18 +++
 .../kvm/x86/private_mem_migrate_tests.c       | 118 ++++++++++++++
 virt/kvm/guest_memfd.c                        | 150 ++++++++++++++----
 virt/kvm/guest_memfd.h                        |   1 +
 virt/kvm/kvm_main.c                           |  12 ++
 11 files changed, 407 insertions(+), 27 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/x86/private_mem_migrate_tests.c


base-commit: ad06cf5338bc5501bd989584db6dc71972bb436a
-- 
2.56.0.257.gf7497c7d27-goog


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-26  7:42 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-26  6:44 [RFC PATCH v3 0/5] KVM: guest_memfd: Add KVM_LINK_GUEST_MEMFD ioctl Tao Gong
2026-10-26  6:44 ` [RFC PATCH v3 1/5] KVM: guest_memfd: Refactor out kvm_gmem_alloc_file() Tao Gong
2026-10-26  6:44 ` [RFC PATCH v3 2/5] KVM: guest_memfd: Add ioctl KVM_LINK_GUEST_MEMFD Tao Gong
2026-10-26  7:19   ` sashiko-bot
2026-10-26  6:44 ` [RFC PATCH v3 3/5] KVM: guest_memfd: Advertise support for KVM_LINK_GUEST_MEMFD Tao Gong
2026-10-26  7:35   ` sashiko-bot
2026-10-26  6:44 ` [RFC PATCH v3 4/5] KVM: selftests: Add tests for KVM_LINK_GUEST_MEMFD ioctl Tao Gong
2026-10-26  7:42   ` sashiko-bot
2026-10-26  6:44 ` [RFC PATCH v3 5/5] KVM: selftests: Test transferring private memory to another VM Tao Gong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox