Currently QEMU supports using guest_memfd internally (separately from user-specified memory backends) to handle private memory for confidential VMs. While KVM can switch between guest_memfd-backed private memory and non-guest_memfd-backed shared memory via KVM_SET_MEMORY_ATTRIBUTES, the memory in the guest_memfd inode can only ever be private memory. This is distinct from upcoming in-place conversion support, where guest_memfd inodes can contain both private/shared memory and can convert between the 2 in-place. To help distinguish between these 2 uses of guest_memfd, add a dedicated helper to handle the private-only uses of guest_memfd, and add some additional sanity checks with that use-case in mind. Signed-off-by: Michael Roth --- accel/kvm/kvm-all.c | 15 +++++++++++++++ accel/stubs/kvm-stub.c | 6 ++++++ include/system/kvm.h | 1 + system/physmem.c | 6 +++--- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 518baa35b9..15f237de4e 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -794,6 +794,11 @@ static int kvm_mem_flags(MemoryRegion *mr) } if (memory_region_has_guest_memfd_private(mr)) { assert(kvm_guest_memfd_supported); + /* + * memory_region_has_guest_memfd_private() is specifically pertaining to + * using guest_memfd to handle private memory use cases. + */ + assert(kvm_supported_memory_attributes & KVM_MEMORY_ATTRIBUTE_PRIVATE); flags |= KVM_MEM_GUEST_MEMFD; } return flags; @@ -4873,3 +4878,13 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp) return fd; } + +int kvm_create_guest_memfd_private(uint64_t size, Error **errp) +{ + if (!(kvm_supported_memory_attributes & KVM_MEMORY_ATTRIBUTE_PRIVATE)) { + error_setg(errp, "KVM does not support using guest_memfd for private memory"); + return -1; + } + + return kvm_create_guest_memfd(size, 0, errp); +} diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index acbd0785e0..9fe58efe91 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -145,6 +145,12 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp) return -ENOSYS; } +int kvm_create_guest_memfd_private(uint64_t size, Error **errp) +{ + error_setg(errp, "KVM is not enabled"); + return -ENOSYS; +} + bool kvm_private_memory_attribute_supported(void) { return false; diff --git a/include/system/kvm.h b/include/system/kvm.h index d29624034c..b1e43ddc93 100644 --- a/include/system/kvm.h +++ b/include/system/kvm.h @@ -548,6 +548,7 @@ void kvm_mark_guest_state_protected(void); bool kvm_hwpoisoned_mem(void); int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp); +int kvm_create_guest_memfd_private(uint64_t size, Error **errp); int kvm_set_memory_attributes_private(hwaddr start, uint64_t size); int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size); diff --git a/system/physmem.c b/system/physmem.c index f6dff18bbb..991f7bb815 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -2209,7 +2209,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) } new_block->guest_memfd_private = - kvm_create_guest_memfd(new_block->max_length, 0, errp); + kvm_create_guest_memfd_private(new_block->max_length, errp); if (new_block->guest_memfd_private < 0) { qemu_mutex_unlock_ramlist(); goto out_free; @@ -2839,8 +2839,8 @@ int ram_block_rebind(Error **errp) if (block->guest_memfd_private >= 0) { close(block->guest_memfd_private); } - block->guest_memfd_private = kvm_create_guest_memfd( - block->max_length, 0, errp); + block->guest_memfd_private = + kvm_create_guest_memfd_private(block->max_length, errp); if (block->guest_memfd_private < 0) { qemu_mutex_unlock_ramlist(); return -1; -- 2.43.0