Re: [PATCH v8 30/46] KVM: selftests: Add helpers for calling ioctls on guest_memfd

From: Fuad Tabba

Date: Wed Jun 24 2026 - 15:27:19 EST


On Fri, 19 Jun 2026 at 01:32, Ackerley Tng via B4 Relay
<devnull+ackerleytng.google.com@xxxxxxxxxx> wrote:
>
> From: Sean Christopherson <seanjc@xxxxxxxxxx>
>
> Add helper functions to kvm_util.h to support calling ioctls, specifically
> KVM_SET_MEMORY_ATTRIBUTES2, on a guest_memfd file descriptor.
>
> Introduce gmem_ioctl() and __gmem_ioctl() macros, modeled after the
> existing vm_ioctl() helpers, to provide a standard way to call ioctls
> on a guest_memfd.
>
> Add gmem_set_memory_attributes() and its derivatives (gmem_set_private(),
> gmem_set_shared()) to set memory attributes on a guest_memfd region.
> Also provide "__" variants that return the ioctl error code instead of
> aborting the test. These helpers will be used by upcoming guest_memfd
> tests.
>
> To avoid code duplication, factor out the check for supported memory
> attributes into a new macro, TEST_ASSERT_SUPPORTED_ATTRIBUTES, and use
> it in both the existing vm_set_memory_attributes() and the new
> gmem_set_memory_attributes() helpers.
>
> Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
> Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>

Reviewed-by: Fuad Tabba <tabba@xxxxxxxxxx>

Cheers,
/fuad

> ---
> tools/testing/selftests/kvm/include/kvm_util.h | 94 +++++++++++++++++++++++---
> 1 file changed, 86 insertions(+), 8 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
> index 0cacf3698b259..323d06b5699ec 100644
> --- a/tools/testing/selftests/kvm/include/kvm_util.h
> +++ b/tools/testing/selftests/kvm/include/kvm_util.h
> @@ -392,6 +392,16 @@ static __always_inline void static_assert_is_vcpu(struct kvm_vcpu *vcpu) { }
> __TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (vcpu)->vm); \
> })
>
> +#define __gmem_ioctl(gmem_fd, cmd, arg) \
> + kvm_do_ioctl(gmem_fd, cmd, arg)
> +
> +#define gmem_ioctl(gmem_fd, cmd, arg) \
> +({ \
> + int ret = __gmem_ioctl(gmem_fd, cmd, arg); \
> + \
> + TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(#cmd, ret)); \
> +})
> +
> /*
> * Looks up and returns the value corresponding to the capability
> * (KVM_CAP_*) given by cap.
> @@ -418,8 +428,16 @@ static inline void vm_enable_cap(struct kvm_vm *vm, u32 cap, u64 arg0)
> vm_ioctl(vm, KVM_ENABLE_CAP, &enable_cap);
> }
>
> +/*
> + * KVM_SET_MEMORY_ATTRIBUTES{,2} overwrites _all_ attributes. These
> + * flows need significant enhancements to support multiple attributes.
> + */
> +#define TEST_ASSERT_SUPPORTED_ATTRIBUTES(attributes) \
> + TEST_ASSERT(!(attributes) || (attributes) == KVM_MEMORY_ATTRIBUTE_PRIVATE, \
> + "Update me to support multiple attributes!")
> +
> static inline void vm_set_memory_attributes(struct kvm_vm *vm, gpa_t gpa,
> - u64 size, u64 attributes)
> + size_t size, u64 attributes)
> {
> struct kvm_memory_attributes attr = {
> .attributes = attributes,
> @@ -428,17 +446,11 @@ static inline void vm_set_memory_attributes(struct kvm_vm *vm, gpa_t gpa,
> .flags = 0,
> };
>
> - /*
> - * KVM_SET_MEMORY_ATTRIBUTES overwrites _all_ attributes. These flows
> - * need significant enhancements to support multiple attributes.
> - */
> - TEST_ASSERT(!attributes || attributes == KVM_MEMORY_ATTRIBUTE_PRIVATE,
> - "Update me to support multiple attributes!");
> + TEST_ASSERT_SUPPORTED_ATTRIBUTES(attributes);
>
> vm_ioctl(vm, KVM_SET_MEMORY_ATTRIBUTES, &attr);
> }
>
> -
> static inline void vm_mem_set_private(struct kvm_vm *vm, gpa_t gpa,
> u64 size)
> {
> @@ -451,6 +463,72 @@ static inline void vm_mem_set_shared(struct kvm_vm *vm, gpa_t gpa,
> vm_set_memory_attributes(vm, gpa, size, 0);
> }
>
> +static inline int __gmem_set_memory_attributes(int fd, u64 offset,
> + size_t size, u64 attributes,
> + u64 *error_offset)
> +{
> + struct kvm_memory_attributes2 attr = {
> + .attributes = attributes,
> + .offset = offset,
> + .size = size,
> + .flags = 0,
> + .error_offset = 0,
> + };
> + int r;
> +
> + r = __gmem_ioctl(fd, KVM_SET_MEMORY_ATTRIBUTES2, &attr);
> +
> + /* Copy error_offset regardless of r so caller can check. */
> + if (error_offset)
> + *error_offset = attr.error_offset;
> +
> + return r;
> +}
> +
> +static inline int __gmem_set_private(int fd, u64 offset, size_t size,
> + u64 *error_offset)
> +{
> + return __gmem_set_memory_attributes(fd, offset, size,
> + KVM_MEMORY_ATTRIBUTE_PRIVATE,
> + error_offset);
> +}
> +
> +static inline int __gmem_set_shared(int fd, u64 offset, size_t size,
> + u64 *error_offset)
> +{
> + return __gmem_set_memory_attributes(fd, offset, size, 0,
> + error_offset);
> +}
> +
> +static inline void gmem_set_memory_attributes(int fd, u64 offset,
> + size_t size, u64 attributes)
> +{
> + struct kvm_memory_attributes2 attr = {
> + .attributes = attributes,
> + .offset = offset,
> + .size = size,
> + .flags = 0,
> + };
> +
> + TEST_ASSERT_SUPPORTED_ATTRIBUTES(attributes);
> +
> + __TEST_REQUIRE(kvm_check_cap(KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES) > 0,
> + "No valid attributes for guest_memfd ioctl!");
> +
> + gmem_ioctl(fd, KVM_SET_MEMORY_ATTRIBUTES2, &attr);
> +}
> +
> +static inline void gmem_set_private(int fd, u64 offset, size_t size)
> +{
> + gmem_set_memory_attributes(fd, offset, size,
> + KVM_MEMORY_ATTRIBUTE_PRIVATE);
> +}
> +
> +static inline void gmem_set_shared(int fd, u64 offset, size_t size)
> +{
> + gmem_set_memory_attributes(fd, offset, size, 0);
> +}
> +
> void vm_guest_mem_fallocate(struct kvm_vm *vm, gpa_t gpa, u64 size,
> bool punch_hole);
>
>
> --
> 2.55.0.rc0.738.g0c8ab3ebcc-goog
>
>