(This is just the POC code to use gmem with hugetlb.) Try with hugetlb first when hugetlb is supported by gmem. If hugetlb cannot afford the requested memory size and returns -ENOMEM, fallback to create gmem withtout hugetlb.
The hugetlb size is hardcoded as GUESTMEM_HUGETLB_FLAG_2MB. I'm not sure if it will be better if gmem can report the supported hugetlb size. But look at the current implementation of memfd, it just tries with the requested hugetlb size from user and fail when not supported. Hence gmem can do the same way without the supported size being enuemrated. For a upstreamable solution, the hugetlb support of gmem can be implemented as "hugetlb" and "hugetlbsize" properties of memory-backend-guestmemfd as similar of memory-backend-memfd. (It requires memory-backed-guestmemfd introduced for in-place conversion gmem at first) Signed-off-by: Xiaoyao Li <xiaoyao...@intel.com> --- accel/kvm/kvm-all.c | 3 ++- accel/stubs/kvm-stub.c | 1 + include/system/kvm.h | 1 + system/physmem.c | 13 +++++++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 609537738d38..2d18e961714e 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -106,6 +106,7 @@ static bool kvm_immediate_exit; static uint64_t kvm_supported_memory_attributes; static bool kvm_guest_memfd_supported; bool kvm_guest_memfd_inplace_supported; +bool kvm_guest_memfd_hugetlb_supported; static hwaddr kvm_max_slot_size = ~0; static const KVMCapabilityInfo kvm_required_capabilites[] = { @@ -2808,6 +2809,7 @@ static int kvm_init(AccelState *as, MachineState *ms) kvm_guest_memfd_inplace_supported = kvm_check_extension(s, KVM_CAP_GMEM_SHARED_MEM) && kvm_check_extension(s, KVM_CAP_GMEM_CONVERSION); + kvm_guest_memfd_hugetlb_supported = kvm_check_extension(s, KVM_CAP_GMEM_HUGETLB); kvm_pre_fault_memory_supported = kvm_vm_check_extension(s, KVM_CAP_PRE_FAULT_MEMORY); if (s->kernel_irqchip_split == ON_OFF_AUTO_AUTO) { @@ -4536,7 +4538,6 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp) fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_GUEST_MEMFD, &guest_memfd); if (fd < 0) { error_setg_errno(errp, errno, "Error creating KVM guest_memfd"); - return -1; } return fd; diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index bf0ccae27b62..fbc1d7c4e9b5 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -25,6 +25,7 @@ bool kvm_allowed; bool kvm_readonly_mem_allowed; bool kvm_msi_use_devid; bool kvm_guest_memfd_inplace_supported; +bool kvm_guest_memfd_hugetlb_supported; void kvm_flush_coalesced_mmio_buffer(void) { diff --git a/include/system/kvm.h b/include/system/kvm.h index 32f2be5f92e1..d1d79510ee26 100644 --- a/include/system/kvm.h +++ b/include/system/kvm.h @@ -44,6 +44,7 @@ extern bool kvm_readonly_mem_allowed; extern bool kvm_msi_use_devid; extern bool kvm_pre_fault_memory_supported; extern bool kvm_guest_memfd_inplace_supported; +extern bool kvm_guest_memfd_hugetlb_supported; #define kvm_enabled() (kvm_allowed) /** diff --git a/system/physmem.c b/system/physmem.c index 955480685310..ea1c27ea2b99 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1940,8 +1940,21 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) GUEST_MEMFD_FLAG_INIT_PRIVATE; } + if (kvm_guest_memfd_hugetlb_supported) { + new_block->guest_memfd_flags |= GUEST_MEMFD_FLAG_HUGETLB | + GUESTMEM_HUGETLB_FLAG_2MB; + } + + new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length, + new_block->guest_memfd_flags, &err); + if (new_block->guest_memfd == -ENOMEM) { + error_free(err); + new_block->guest_memfd_flags &= ~(GUEST_MEMFD_FLAG_HUGETLB | + GUESTMEM_HUGETLB_FLAG_2MB); + } new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length, new_block->guest_memfd_flags, errp); + if (new_block->guest_memfd < 0) { qemu_mutex_unlock_ramlist(); goto out_free; -- 2.43.0