Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: Alexandru Elisei <alexandru.elisei@arm.com>
To: Fuad Tabba <fuad.tabba@linux.dev>
Cc: kvm@vger.kernel.org, kvmarm@lists.linux.dev,
	Will Deacon <will@kernel.org>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Andre Przywara <andre.przywara@arm.com>,
	Oliver Upton <oliver.upton@linux.dev>,
	Marc Zyngier <maz@kernel.org>, Fuad Tabba <tabba@google.com>
Subject: Re: [PATCH kvmtool v1 5/5] arm64: Add --guest-memfd option to back guest RAM with guest_memfd
Date: Wed, 8 Jul 2026 14:02:42 +0100	[thread overview]
Message-ID: <ak5KcuSzEo7s9P1s@raptor> (raw)
In-Reply-To: <20260706083555.302972-6-fuad.tabba@linux.dev>

Hi Fuad,

Looks good me, two small things: it might be useful for debugging to first
check that KVM supports KVM_CAP_GUEST_MEMFD before checking
KVM_CAP_GUEST_MEMFD_FLAGS, and the file descriptor could be closed after it
is unmapped.

Thanks,
Alex

On Mon, Jul 06, 2026 at 09:35:55AM +0100, Fuad Tabba wrote:
> Back guest RAM with a guest_memfd created with GUEST_MEMFD_FLAG_MMAP
> and GUEST_MEMFD_FLAG_INIT_SHARED, mmapped MAP_SHARED to provide the
> userspace mapping.
> 
> Protected VMs need in-place shared/private conversion of guest_memfd,
> which the kernel does not support yet, so reject the combination of
> --protected and --guest-memfd.
> 
> Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
> ---
>  arm64/include/kvm/kvm-config-arch.h |  5 +++-
>  arm64/kvm.c                         | 38 +++++++++++++++++++++++------
>  include/kvm/kvm.h                   |  1 +
>  include/kvm/util.h                  |  1 +
>  kvm.c                               |  1 +
>  util/util.c                         | 34 ++++++++++++++++++++++++++
>  6 files changed, 71 insertions(+), 9 deletions(-)
> 
> diff --git a/arm64/include/kvm/kvm-config-arch.h b/arm64/include/kvm/kvm-config-arch.h
> index c2702d5..d8a8ef7 100644
> --- a/arm64/include/kvm/kvm-config-arch.h
> +++ b/arm64/include/kvm/kvm-config-arch.h
> @@ -20,6 +20,7 @@ struct kvm_config_arch {
>  	bool		no_pvtime;
>  	bool		psci;
>  	bool		protected;
> +	bool		guest_memfd;
>  };
>  
>  int irqchip_parser(const struct option *opt, const char *arg, int unset);
> @@ -73,6 +74,8 @@ int sve_vl_parser(const struct option *opt, const char *arg, int unset);
>  	OPT_BOOLEAN('\0', "e2h0", &(cfg)->e2h0,					\
>  		    "Create guest without VHE support"),			\
>  	OPT_BOOLEAN('\0', "protected", &(cfg)->protected,			\
> -			"Create a protected VM when pKVM is enabled"),
> +			"Create a protected VM when pKVM is enabled"),		\
> +	OPT_BOOLEAN('\0', "guest-memfd", &(cfg)->guest_memfd,			\
> +			"Use guest_memfd to back guest RAM"),
>  
>  #endif /* ARM_COMMON__KVM_CONFIG_ARCH_H */
> diff --git a/arm64/kvm.c b/arm64/kvm.c
> index fb0b98d..b594578 100644
> --- a/arm64/kvm.c
> +++ b/arm64/kvm.c
> @@ -49,9 +49,14 @@ void kvm__init_ram(struct kvm *kvm)
>  	kvm->arch.ram_alloc_size = kvm->ram_size;
>  	if (!kvm->cfg.hugetlbfs_path)
>  		kvm->arch.ram_alloc_size += SZ_2M;
> -	kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm,
> -						kvm->cfg.hugetlbfs_path,
> -						kvm->arch.ram_alloc_size);
> +
> +	if (kvm->cfg.arch.guest_memfd)
> +		kvm->arch.ram_alloc_start =
> +			mmap_guest_memfd(kvm, kvm->arch.ram_alloc_size);
> +	else
> +		kvm->arch.ram_alloc_start =
> +			mmap_anon_or_hugetlbfs(kvm, kvm->cfg.hugetlbfs_path,
> +					       kvm->arch.ram_alloc_size);
>  
>  	if (kvm->arch.ram_alloc_start == MAP_FAILED)
>  		die("Failed to map %lld bytes for guest memory (%d)",
> @@ -60,17 +65,25 @@ void kvm__init_ram(struct kvm *kvm)
>  	kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start,
>  					SZ_2M);
>  
> -	madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> -		MADV_MERGEABLE);
> +	if (!kvm->cfg.arch.guest_memfd) {
> +		madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> +			MADV_MERGEABLE);
>  
> -	madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> -		MADV_HUGEPAGE);
> +		madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> +			MADV_HUGEPAGE);
> +	}
>  
>  	phys_start	= kvm->cfg.ram_addr;
>  	phys_size	= kvm->ram_size;
>  	host_mem	= kvm->ram_start;
>  
> -	err = kvm__register_ram(kvm, phys_start, phys_size, host_mem);
> +	if (kvm->cfg.arch.guest_memfd)
> +		err = kvm__register_ram_guest_memfd(kvm, phys_start,
> +						    phys_size, host_mem,
> +						    kvm->ram_guest_memfd,
> +						    host_mem - kvm->arch.ram_alloc_start);
> +	else
> +		err = kvm__register_ram(kvm, phys_start, phys_size, host_mem);
>  	if (err)
>  		die("Failed to register %lld bytes of memory at physical "
>  		    "address 0x%llx [err %d]", phys_size, phys_start, err);
> @@ -468,6 +481,15 @@ void kvm__arch_validate_cfg(struct kvm *kvm)
>  	if (kvm->cfg.arch.e2h0 && !kvm->cfg.arch.nested_virt)
>  		pr_warning("--e2h0 requires --nested, ignoring");
>  
> +	if (kvm->cfg.arch.guest_memfd) {
> +		/* Requires in-place shared/private conversion of guest_memfd. */
> +		if (kvm->cfg.arch.protected)
> +			die("Protected VMs do not yet support guest_memfd");
> +
> +		if (kvm->cfg.hugetlbfs_path)
> +			die("guest_memfd cannot be backed by hugetlbfs");
> +	}
> +
>  	if (kvm->cfg.arch.protected) {
>  		if (kvm->cfg.ram_size &&
>  		    kvm->cfg.ram_size < DMA_MEM_REGION_SIZE) {
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index 5e7b5eb..95dc52f 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -90,6 +90,7 @@ struct kvm {
>  	u64			ram_size;	/* Guest memory size, in bytes */
>  	void			*ram_start;
>  	u64			ram_pagesize;
> +	int			ram_guest_memfd; /* guest_memfd backing RAM, -1 if none */
>  	struct mutex		mem_banks_lock;
>  	struct list_head	mem_banks;
>  
> diff --git a/include/kvm/util.h b/include/kvm/util.h
> index a6dba11..9e23431 100644
> --- a/include/kvm/util.h
> +++ b/include/kvm/util.h
> @@ -148,5 +148,6 @@ static inline int pow2_size(unsigned long x)
>  struct kvm;
>  void *mmap_hugetlbfs(struct kvm *kvm, const char *htlbfs_path, u64 size);
>  void *mmap_anon_or_hugetlbfs(struct kvm *kvm, const char *hugetlbfs_path, u64 size);
> +void *mmap_guest_memfd(struct kvm *kvm, u64 size);
>  
>  #endif /* KVM__UTIL_H */
> diff --git a/kvm.c b/kvm.c
> index 3d05756..a400dd2 100644
> --- a/kvm.c
> +++ b/kvm.c
> @@ -162,6 +162,7 @@ struct kvm *kvm__new(void)
>  	mutex_init(&kvm->mem_banks_lock);
>  	kvm->sys_fd = -1;
>  	kvm->vm_fd = -1;
> +	kvm->ram_guest_memfd = -1;
>  
>  #ifdef KVM_BRLOCK_DEBUG
>  	kvm->brlock_sem = (pthread_rwlock_t) PTHREAD_RWLOCK_INITIALIZER;
> diff --git a/util/util.c b/util/util.c
> index 05d49c4..c60fe02 100644
> --- a/util/util.c
> +++ b/util/util.c
> @@ -6,7 +6,9 @@
>  #include "kvm/util.h"
>  
>  #include <kvm/kvm.h>
> +#include <linux/kvm.h>
>  #include <linux/magic.h>	/* For HUGETLBFS_MAGIC */
> +#include <sys/ioctl.h>
>  #include <sys/mman.h>
>  #include <sys/stat.h>
>  #include <sys/statfs.h>
> @@ -169,3 +171,35 @@ void *mmap_anon_or_hugetlbfs(struct kvm *kvm, const char *hugetlbfs_path, u64 si
>  		return mmap(NULL, size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
>  	}
>  }
> +
> +/*
> + * Map guest RAM backed by a guest_memfd. The file descriptor must stay open
> + * for the lifetime of the VM: closing it invalidates the memslot bindings.
> + */
> +void *mmap_guest_memfd(struct kvm *kvm, u64 size)
> +{
> +	u64 flags = GUEST_MEMFD_FLAG_MMAP | GUEST_MEMFD_FLAG_INIT_SHARED;
> +	struct kvm_create_guest_memfd gmem = {
> +		.size	= size,
> +		.flags	= flags,
> +	};
> +	void *addr;
> +	int ret;
> +
> +	ret = ioctl(kvm->vm_fd, KVM_CHECK_EXTENSION, KVM_CAP_GUEST_MEMFD_FLAGS);
> +	if (ret < 0 || ((u64)ret & flags) != flags)
> +		die("kernel does not support guest_memfd with mmap");
> +
> +	ret = ioctl(kvm->vm_fd, KVM_CREATE_GUEST_MEMFD, &gmem);
> +	if (ret < 0)
> +		die_perror("KVM_CREATE_GUEST_MEMFD");
> +
> +	addr = mmap(NULL, size, PROT_RW, MAP_SHARED, ret, 0);
> +	if (addr == MAP_FAILED)
> +		die_perror("guest_memfd mmap");
> +
> +	kvm->ram_guest_memfd = ret;
> +	kvm->ram_pagesize = getpagesize();
> +
> +	return addr;
> +}
> -- 
> 2.39.5
> 

  parent reply	other threads:[~2026-07-08 13:02 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-06  8:35 [PATCH kvmtool v1 0/5] Add guest_memfd support for arm64 Fuad Tabba
2026-07-06  8:35 ` [PATCH kvmtool v1 1/5] Initialize the return value in kvm__for_each_mem_bank() Fuad Tabba
2026-07-06  8:35 ` [PATCH kvmtool v1 2/5] Remove newline from end of die() aborts Fuad Tabba
2026-07-06 10:53   ` Suzuki K Poulose
2026-07-06 10:57     ` Fuad Tabba
2026-07-06  8:35 ` [PATCH kvmtool v1 3/5] Use kvm_userspace_memory_region2 for all memory registration Fuad Tabba
2026-07-06 10:23   ` Suzuki K Poulose
2026-07-06 10:41     ` Fuad Tabba
2026-07-06 10:46       ` Will Deacon
2026-07-06 10:47         ` Fuad Tabba
2026-07-06 10:57     ` Alexandru Elisei
2026-07-06 10:59       ` Fuad Tabba
2026-07-06  8:35 ` [PATCH kvmtool v1 4/5] Add guest_memfd support to kvm__register_mem() Fuad Tabba
2026-07-06 11:00   ` Suzuki K Poulose
2026-07-06 11:13     ` Suzuki K Poulose
2026-07-06 11:25       ` Fuad Tabba
2026-07-06 12:34         ` Suzuki K Poulose
2026-07-06  8:35 ` [PATCH kvmtool v1 5/5] arm64: Add --guest-memfd option to back guest RAM with guest_memfd Fuad Tabba
2026-07-06 11:18   ` Suzuki K Poulose
2026-07-06 11:24     ` Fuad Tabba
2026-07-08 13:02   ` Alexandru Elisei [this message]
2026-07-08 15:59     ` Fuad Tabba

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ak5KcuSzEo7s9P1s@raptor \
    --to=alexandru.elisei@arm.com \
    --cc=andre.przywara@arm.com \
    --cc=fuad.tabba@linux.dev \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=maz@kernel.org \
    --cc=oliver.upton@linux.dev \
    --cc=suzuki.poulose@arm.com \
    --cc=tabba@google.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox