From: Sean Christopherson <[email protected]>

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 <[email protected]>
Signed-off-by: Ackerley Tng <[email protected]>
---
 tools/testing/selftests/kvm/include/kvm_util.h | 98 +++++++++++++++++++++++---
 1 file changed, 90 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/kvm/include/kvm_util.h 
b/tools/testing/selftests/kvm/include/kvm_util.h
index fb54694e6568b..62d917a2d2b19 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,76 @@ 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, loff_t offset,
+                                              size_t size, u64 attributes,
+                                              loff_t *error_offset,
+                                              u64 flags)
+{
+       struct kvm_memory_attributes2 attr = {
+               .attributes = attributes,
+               .offset = offset,
+               .size = size,
+               .flags = flags,
+               .error_offset = error_offset ? *error_offset : 0,
+       };
+       int r;
+
+       TEST_ASSERT_SUPPORTED_ATTRIBUTES(attributes);
+
+       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, loff_t offset, size_t size,
+                                    loff_t *error_offset, u64 flags)
+{
+       return __gmem_set_memory_attributes(fd, offset, size,
+                                           KVM_MEMORY_ATTRIBUTE_PRIVATE,
+                                           error_offset, flags);
+}
+
+static inline int __gmem_set_shared(int fd, loff_t offset, size_t size,
+                                   loff_t *error_offset, u64 flags)
+{
+       return __gmem_set_memory_attributes(fd, offset, size, 0,
+                                           error_offset, flags);
+}
+
+static inline void gmem_set_memory_attributes(int fd, loff_t offset,
+                                             size_t size, u64 attributes,
+                                             u64 flags)
+{
+       struct kvm_memory_attributes2 attr = {
+               .attributes = attributes,
+               .offset = offset,
+               .size = size,
+               .flags = flags,
+       };
+
+       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, loff_t offset, size_t size, u64 
flags)
+{
+       gmem_set_memory_attributes(fd, offset, size,
+                                  KVM_MEMORY_ATTRIBUTE_PRIVATE, flags);
+}
+
+static inline void gmem_set_shared(int fd, loff_t offset, size_t size, u64 
flags)
+{
+       gmem_set_memory_attributes(fd, offset, size, 0, flags);
+}
+
 void vm_guest_mem_fallocate(struct kvm_vm *vm, gpa_t gpa, u64 size,
                            bool punch_hole);
 

-- 
2.54.0.545.g6539524ca2-goog



Reply via email to