Currently QEMU supports using guest_memfd internally (separately from user-specified memory backends) to handle private memory for confidential VMs, and as a result has checks for guest_memfd support merged with checks to see if KVM can handle mapping private memory (as determined by KVM_MEMORY_ATTRIBUTE_PRIVATE).
Future QEMU support will allow using guest_memfd not just for private memory, but as mmap()'able memory that can be used by non-confidential guests as well. In prep for this, split the checks for guest_memfd out from the check for KVM_MEMORY_ATTRIBUTE_PRIVATE, and rename the current kvm_create_guest_memfd() to kvm_create_guest_memfd_private() to self-document current behavior/expectations and disambiguate from future helpers intended for creating a guest_memfd to handle non-private/shared memory. While there, fix up the missing error_setg() handling in the stub functions. Signed-off-by: Michael Roth <[email protected]> --- accel/kvm/kvm-all.c | 20 +++++++++++++++++--- accel/stubs/kvm-stub.c | 3 ++- include/system/kvm.h | 2 +- include/system/memory.h | 5 +++-- system/physmem.c | 8 ++++---- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 585f1cea35..02911ff6e3 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -795,6 +795,11 @@ static int kvm_mem_flags(MemoryRegion *mr) } if (memory_region_has_guest_memfd(mr)) { assert(kvm_guest_memfd_supported); + /* + * memory_region_has_guest_memfd() 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; @@ -3066,8 +3071,7 @@ static int kvm_init(AccelState *as, MachineState *ms) kvm_supported_memory_attributes = kvm_vm_check_extension(s, KVM_CAP_MEMORY_ATTRIBUTES); kvm_guest_memfd_supported = kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD) && - kvm_vm_check_extension(s, KVM_CAP_USER_MEMORY2) && - (kvm_supported_memory_attributes & KVM_MEMORY_ATTRIBUTE_PRIVATE); + kvm_vm_check_extension(s, KVM_CAP_USER_MEMORY2); kvm_pre_fault_memory_supported = kvm_vm_check_extension(s, KVM_CAP_PRE_FAULT_MEMORY); if (s->kernel_irqchip_split == ON_OFF_AUTO_AUTO) { @@ -4854,7 +4858,7 @@ void kvm_mark_guest_state_protected(void) kvm_state->guest_state_protected = true; } -int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp) +static int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp) { int fd; struct kvm_create_guest_memfd guest_memfd = { @@ -4875,3 +4879,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 c4617caac6..1940bcbd2c 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -139,7 +139,8 @@ bool kvm_hwpoisoned_mem(void) return false; } -int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp) +int kvm_create_guest_memfd_private(uint64_t size, Error **errp) { + error_setg(errp, "guest_memfd is not supported for this configuration"); return -ENOSYS; } diff --git a/include/system/kvm.h b/include/system/kvm.h index 5fa33eddda..aeb0c7ca8f 100644 --- a/include/system/kvm.h +++ b/include/system/kvm.h @@ -561,7 +561,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/include/system/memory.h b/include/system/memory.h index 1417132f6d..24c68720aa 100644 --- a/include/system/memory.h +++ b/include/system/memory.h @@ -1745,9 +1745,10 @@ bool memory_region_is_protected(const MemoryRegion *mr); /** * memory_region_has_guest_memfd: check whether a memory region has guest_memfd - * associated + * associated with it for handling private memory * - * Returns %true if a memory region's ram_block has valid guest_memfd assigned. + * Returns %true if a memory region's ram_block has valid guest_memfd assigned + * for handling private memory. * * @mr: the memory region being queried */ diff --git a/system/physmem.c b/system/physmem.c index 7bcbf87573..04c7c38721 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -2202,8 +2202,8 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) goto out_free; } - new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length, - 0, errp); + new_block->guest_memfd = kvm_create_guest_memfd_private(new_block->max_length, + errp); if (new_block->guest_memfd < 0) { qemu_mutex_unlock_ramlist(); goto out_free; @@ -2835,8 +2835,8 @@ int ram_block_rebind(Error **errp) if (block->guest_memfd >= 0) { close(block->guest_memfd); } - block->guest_memfd = kvm_create_guest_memfd(block->max_length, - 0, errp); + block->guest_memfd = kvm_create_guest_memfd_private(block->max_length, + errp); if (block->guest_memfd < 0) { qemu_mutex_unlock_ramlist(); return -1; -- 2.43.0
