[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250401161106.790710-29-pbonzini@redhat.com>
Date: Tue, 1 Apr 2025 18:11:05 +0200
From: Paolo Bonzini <pbonzini@...hat.com>
To: linux-kernel@...r.kernel.org,
kvm@...r.kernel.org
Cc: roy.hopkins@...e.com,
seanjc@...gle.com,
thomas.lendacky@....com,
ashish.kalra@....com,
michael.roth@....com,
jroedel@...e.de,
nsaenz@...zon.com,
anelkz@...zon.de,
James.Bottomley@...senPartnership.com
Subject: [PATCH 28/29] selftests: kvm: add plane infrastructure
Allow creating plane and vCPU-plane file descriptors, and close them
when the VM is freed. Rewrite the previous test using the new
infrastructure (separate for easier review).
Signed-off-by: Paolo Bonzini <pbonzini@...hat.com>
---
.../testing/selftests/kvm/include/kvm_util.h | 48 ++++++++++++++
tools/testing/selftests/kvm/lib/kvm_util.c | 65 ++++++++++++++++++-
tools/testing/selftests/kvm/plane_test.c | 21 +++---
3 files changed, 119 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 373912464fb4..c1dfe071357e 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -67,6 +67,20 @@ struct kvm_vcpu {
uint32_t dirty_gfns_count;
};
+struct kvm_plane {
+ struct list_head list;
+ uint32_t id;
+ int fd;
+ struct kvm_vm *vm;
+};
+
+struct kvm_plane_vcpu {
+ struct list_head list;
+ uint32_t id;
+ int fd;
+ struct kvm_vcpu *plane0;
+};
+
struct userspace_mem_regions {
struct rb_root gpa_tree;
struct rb_root hva_tree;
@@ -93,6 +107,8 @@ struct kvm_vm {
unsigned int va_bits;
uint64_t max_gfn;
struct list_head vcpus;
+ struct list_head planes;
+ struct list_head plane_vcpus;
struct userspace_mem_regions regions;
struct sparsebit *vpages_valid;
struct sparsebit *vpages_mapped;
@@ -338,6 +354,21 @@ do { \
__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm); \
})
+static __always_inline void static_assert_is_plane(struct kvm_plane *plane) { }
+
+#define __plane_ioctl(plane, cmd, arg) \
+({ \
+ static_assert_is_plane(plane); \
+ kvm_do_ioctl((plane)->fd, cmd, arg); \
+})
+
+#define plane_ioctl(plane, cmd, arg) \
+({ \
+ int ret = __plane_ioctl(plane, cmd, arg); \
+ \
+ __TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (plane)->vm); \
+})
+
static __always_inline void static_assert_is_vcpu(struct kvm_vcpu *vcpu) { }
#define __vcpu_ioctl(vcpu, cmd, arg) \
@@ -353,6 +384,21 @@ static __always_inline void static_assert_is_vcpu(struct kvm_vcpu *vcpu) { }
__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (vcpu)->vm); \
})
+static __always_inline void static_assert_is_plane_vcpu(struct kvm_plane_vcpu *plane_vcpu) { }
+
+#define __plane_vcpu_ioctl(plane_vcpu, cmd, arg) \
+({ \
+ static_assert_is_plane_vcpu(plane_vcpu); \
+ kvm_do_ioctl((plane_vcpu)->fd, cmd, arg); \
+})
+
+#define plane_vcpu_ioctl(plane_vcpu, cmd, arg) \
+({ \
+ int ret = __plane_vcpu_ioctl(plane_vcpu, cmd, arg); \
+ \
+ __TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (plane_vcpu)->plane0->vm); \
+})
+
/*
* Looks up and returns the value corresponding to the capability
* (KVM_CAP_*) given by cap.
@@ -601,6 +647,8 @@ void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags);
void vm_mem_region_move(struct kvm_vm *vm, uint32_t slot, uint64_t new_gpa);
void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot);
struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id);
+struct kvm_plane *vm_plane_add(struct kvm_vm *vm, int plane_id);
+struct kvm_plane_vcpu *__vm_plane_vcpu_add(struct kvm_vcpu *vcpu, struct kvm_plane *plane);
void vm_populate_vaddr_bitmap(struct kvm_vm *vm);
vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min);
vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min);
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 815bc45dd8dc..a2f233945e1c 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -279,6 +279,8 @@ struct kvm_vm *____vm_create(struct vm_shape shape)
TEST_ASSERT(vm != NULL, "Insufficient Memory");
INIT_LIST_HEAD(&vm->vcpus);
+ INIT_LIST_HEAD(&vm->planes);
+ INIT_LIST_HEAD(&vm->plane_vcpus);
vm->regions.gpa_tree = RB_ROOT;
vm->regions.hva_tree = RB_ROOT;
hash_init(vm->regions.slot_hash);
@@ -757,10 +759,22 @@ static void vm_vcpu_rm(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
void kvm_vm_release(struct kvm_vm *vmp)
{
- struct kvm_vcpu *vcpu, *tmp;
+ struct kvm_vcpu *vcpu, *tmp_vcpu;
+ struct kvm_plane_vcpu *plane_vcpu, *tmp_plane_vcpu;
+ struct kvm_plane *plane, *tmp_plane;
int ret;
- list_for_each_entry_safe(vcpu, tmp, &vmp->vcpus, list)
+ list_for_each_entry_safe(plane_vcpu, tmp_plane_vcpu, &vmp->plane_vcpus, list) {
+ close(plane_vcpu->fd);
+ free(plane_vcpu);
+ }
+
+ list_for_each_entry_safe(plane, tmp_plane, &vmp->planes, list) {
+ close(plane->fd);
+ free(plane);
+ }
+
+ list_for_each_entry_safe(vcpu, tmp_vcpu, &vmp->vcpus, list)
vm_vcpu_rm(vmp, vcpu);
ret = close(vmp->fd);
@@ -1314,6 +1328,52 @@ static bool vcpu_exists(struct kvm_vm *vm, uint32_t vcpu_id)
return false;
}
+/*
+ * Adds a virtual CPU to the VM specified by vm with the ID given by vcpu_id.
+ * No additional vCPU setup is done. Returns the vCPU.
+ */
+struct kvm_plane *vm_plane_add(struct kvm_vm *vm, int plane_id)
+{
+ struct kvm_plane *plane;
+
+ /* Allocate and initialize new vcpu structure. */
+ plane = calloc(1, sizeof(*plane));
+ TEST_ASSERT(plane != NULL, "Insufficient Memory");
+
+ plane->fd = __vm_ioctl(vm, KVM_CREATE_PLANE, (void *)(unsigned long)plane_id);
+ TEST_ASSERT_VM_VCPU_IOCTL(plane->fd >= 0, KVM_CREATE_PLANE, plane->fd, vm);
+ plane->vm = vm;
+ plane->id = plane_id;
+
+ /* Add to linked-list of extra-plane VCPUs. */
+ list_add(&plane->list, &vm->planes);
+
+ return plane;
+}
+
+/*
+ * Adds a virtual CPU to the VM specified by vm with the ID given by vcpu_id.
+ * No additional vCPU setup is done. Returns the vCPU.
+ */
+struct kvm_plane_vcpu *__vm_plane_vcpu_add(struct kvm_vcpu *vcpu, struct kvm_plane *plane)
+{
+ struct kvm_plane_vcpu *plane_vcpu;
+
+ /* Allocate and initialize new vcpu structure. */
+ plane_vcpu = calloc(1, sizeof(*plane_vcpu));
+ TEST_ASSERT(plane_vcpu != NULL, "Insufficient Memory");
+
+ plane_vcpu->fd = __plane_ioctl(plane, KVM_CREATE_VCPU_PLANE, (void *)(unsigned long)vcpu->fd);
+ TEST_ASSERT_VM_VCPU_IOCTL(plane_vcpu->fd >= 0, KVM_CREATE_VCPU_PLANE, plane_vcpu->fd, plane->vm);
+ plane_vcpu->id = vcpu->id;
+ plane_vcpu->plane0 = vcpu;
+
+ /* Add to linked-list of extra-plane VCPUs. */
+ list_add(&plane_vcpu->list, &plane->vm->plane_vcpus);
+
+ return plane_vcpu;
+}
+
/*
* Adds a virtual CPU to the VM specified by vm with the ID given by vcpu_id.
* No additional vCPU setup is done. Returns the vCPU.
@@ -2021,6 +2081,7 @@ static struct exit_reason {
KVM_EXIT_STRING(NOTIFY),
KVM_EXIT_STRING(LOONGARCH_IOCSR),
KVM_EXIT_STRING(MEMORY_FAULT),
+ KVM_EXIT_STRING(PLANE_EVENT),
};
/*
diff --git a/tools/testing/selftests/kvm/plane_test.c b/tools/testing/selftests/kvm/plane_test.c
index 43c8de13490a..9cf3ab76b3cd 100644
--- a/tools/testing/selftests/kvm/plane_test.c
+++ b/tools/testing/selftests/kvm/plane_test.c
@@ -47,20 +47,19 @@ void test_create_plane(void)
{
struct kvm_vm *vm;
struct kvm_vcpu *vcpu;
- int r, planefd, plane_vcpufd;
+ struct kvm_plane *plane;
+ int r;
vm = vm_create_barebones();
vcpu = __vm_vcpu_add(vm, 0);
- planefd = __vm_ioctl(vm, KVM_CREATE_PLANE, (void *)(unsigned long)1);
- TEST_ASSERT(planefd >= 0, "Creating new plane, got error: %d",
- errno);
+ plane = vm_plane_add(vm, 1);
- r = ioctl(planefd, KVM_CHECK_EXTENSION, KVM_CAP_PLANES);
+ r = __plane_ioctl(plane, KVM_CHECK_EXTENSION, (void *)(unsigned long)KVM_CAP_PLANES);
TEST_ASSERT(r == 0,
"Checking KVM_CHECK_EXTENSION(KVM_CAP_PLANES). ret: %d", r);
- r = ioctl(planefd, KVM_CHECK_EXTENSION, KVM_CAP_CHECK_EXTENSION_VM);
+ r = __plane_ioctl(plane, KVM_CHECK_EXTENSION, (void *)(unsigned long)KVM_CAP_CHECK_EXTENSION_VM);
TEST_ASSERT(r == 1,
"Checking KVM_CHECK_EXTENSION(KVM_CAP_CHECK_EXTENSION_VM). ret: %d", r);
@@ -69,22 +68,18 @@ void test_create_plane(void)
"Creating existing plane, expecting EEXIST. ret: %d, errno: %d",
r, errno);
- plane_vcpufd = ioctl(planefd, KVM_CREATE_VCPU_PLANE, (void *)(unsigned long)vcpu->fd);
- TEST_ASSERT(plane_vcpufd >= 0, "Creating vCPU for plane 1, got error: %d", errno);
+ __vm_plane_vcpu_add(vcpu, plane);
- r = ioctl(planefd, KVM_CREATE_VCPU_PLANE, (void *)(unsigned long)vcpu->fd);
+ r = __plane_ioctl(plane, KVM_CREATE_VCPU_PLANE, (void *)(unsigned long)vcpu->fd);
TEST_ASSERT(r == -1 && errno == EEXIST,
"Creating vCPU again for plane 1. ret: %d, errno: %d",
r, errno);
- r = ioctl(planefd, KVM_RUN, (void *)(unsigned long)0);
+ r = __plane_ioctl(plane, KVM_RUN, (void *)(unsigned long)0);
TEST_ASSERT(r == -1 && errno == ENOTTY,
"Running plane vCPU again for plane 1. ret: %d, errno: %d",
r, errno);
- close(plane_vcpufd);
- close(planefd);
-
kvm_vm_free(vm);
ksft_test_result_pass("basic planefd and plane_vcpufd operation\n");
}
--
2.49.0
Powered by blists - more mailing lists