Here's a follow-up from my RFC series last year:
https://lore.kernel.org/lkml/20221004093131.40392-1-thuth@redhat.com/T/
Basic idea of this series is now to use the kselftest_harness.h framework to get TAP output in the tests, so that it is easier for the user to see what is going on, and e.g. to be able to detect whether a certain test is part of the test binary or not (which is useful when tests get extended in the course of time).
Thomas Huth (4): KVM: selftests: Rename the ASSERT_EQ macro KVM: selftests: x86: Use TAP interface in the sync_regs test KVM: selftests: x86: Use TAP interface in the fix_hypercall test KVM: selftests: x86: Use TAP interface in the userspace_msr_exit test
.../selftests/kvm/aarch64/aarch32_id_regs.c | 8 +- .../selftests/kvm/aarch64/page_fault_test.c | 10 +- .../testing/selftests/kvm/include/test_util.h | 4 +- tools/testing/selftests/kvm/lib/kvm_util.c | 2 +- .../selftests/kvm/max_guest_memory_test.c | 2 +- tools/testing/selftests/kvm/s390x/cmma_test.c | 62 +++++----- tools/testing/selftests/kvm/s390x/memop.c | 6 +- tools/testing/selftests/kvm/s390x/tprot.c | 4 +- .../x86_64/dirty_log_page_splitting_test.c | 18 +-- .../x86_64/exit_on_emulation_failure_test.c | 2 +- .../selftests/kvm/x86_64/fix_hypercall_test.c | 16 ++- .../kvm/x86_64/nested_exceptions_test.c | 12 +- .../kvm/x86_64/recalc_apic_map_test.c | 6 +- .../selftests/kvm/x86_64/sync_regs_test.c | 113 +++++++++++++++--- .../selftests/kvm/x86_64/tsc_msrs_test.c | 32 ++--- .../kvm/x86_64/userspace_msr_exit_test.c | 19 +-- .../vmx_exception_with_invalid_guest_state.c | 2 +- .../selftests/kvm/x86_64/vmx_pmu_caps_test.c | 3 +- .../selftests/kvm/x86_64/xapic_state_test.c | 8 +- .../selftests/kvm/x86_64/xen_vmcall_test.c | 20 ++-- 20 files changed, 218 insertions(+), 131 deletions(-)
There is already an ASSERT_EQ macro in the file tools/testing/selftests/kselftest_harness.h, so we currently can't include test_util.h from the KVM selftests together with that file. Rename the macro in the KVM selftests to TEST_ASSERT_EQ to avoid the problem - it is also more similar to the other macros in test_util.h that way.
Suggested-by: Sean Christopherson seanjc@google.com Signed-off-by: Thomas Huth thuth@redhat.com --- .../selftests/kvm/aarch64/aarch32_id_regs.c | 8 +-- .../selftests/kvm/aarch64/page_fault_test.c | 10 +-- .../testing/selftests/kvm/include/test_util.h | 4 +- tools/testing/selftests/kvm/lib/kvm_util.c | 2 +- .../selftests/kvm/max_guest_memory_test.c | 2 +- tools/testing/selftests/kvm/s390x/cmma_test.c | 62 +++++++++---------- tools/testing/selftests/kvm/s390x/memop.c | 6 +- tools/testing/selftests/kvm/s390x/tprot.c | 4 +- .../x86_64/dirty_log_page_splitting_test.c | 18 +++--- .../x86_64/exit_on_emulation_failure_test.c | 2 +- .../kvm/x86_64/nested_exceptions_test.c | 12 ++-- .../kvm/x86_64/recalc_apic_map_test.c | 6 +- .../selftests/kvm/x86_64/tsc_msrs_test.c | 32 +++++----- .../vmx_exception_with_invalid_guest_state.c | 2 +- .../selftests/kvm/x86_64/vmx_pmu_caps_test.c | 3 +- .../selftests/kvm/x86_64/xapic_state_test.c | 8 +-- .../selftests/kvm/x86_64/xen_vmcall_test.c | 20 +++--- 17 files changed, 101 insertions(+), 100 deletions(-)
diff --git a/tools/testing/selftests/kvm/aarch64/aarch32_id_regs.c b/tools/testing/selftests/kvm/aarch64/aarch32_id_regs.c index 4951ac53d1f88..b90580840b228 100644 --- a/tools/testing/selftests/kvm/aarch64/aarch32_id_regs.c +++ b/tools/testing/selftests/kvm/aarch64/aarch32_id_regs.c @@ -98,7 +98,7 @@ static void test_user_raz_wi(struct kvm_vcpu *vcpu) uint64_t val;
vcpu_get_reg(vcpu, reg_id, &val); - ASSERT_EQ(val, 0); + TEST_ASSERT_EQ(val, 0);
/* * Expect the ioctl to succeed with no effect on the register @@ -107,7 +107,7 @@ static void test_user_raz_wi(struct kvm_vcpu *vcpu) vcpu_set_reg(vcpu, reg_id, BAD_ID_REG_VAL);
vcpu_get_reg(vcpu, reg_id, &val); - ASSERT_EQ(val, 0); + TEST_ASSERT_EQ(val, 0); } }
@@ -127,14 +127,14 @@ static void test_user_raz_invariant(struct kvm_vcpu *vcpu) uint64_t val;
vcpu_get_reg(vcpu, reg_id, &val); - ASSERT_EQ(val, 0); + TEST_ASSERT_EQ(val, 0);
r = __vcpu_set_reg(vcpu, reg_id, BAD_ID_REG_VAL); TEST_ASSERT(r < 0 && errno == EINVAL, "unexpected KVM_SET_ONE_REG error: r=%d, errno=%d", r, errno);
vcpu_get_reg(vcpu, reg_id, &val); - ASSERT_EQ(val, 0); + TEST_ASSERT_EQ(val, 0); } }
diff --git a/tools/testing/selftests/kvm/aarch64/page_fault_test.c b/tools/testing/selftests/kvm/aarch64/page_fault_test.c index df10f1ffa20d9..e5bb8767d2cb5 100644 --- a/tools/testing/selftests/kvm/aarch64/page_fault_test.c +++ b/tools/testing/selftests/kvm/aarch64/page_fault_test.c @@ -318,7 +318,7 @@ static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg,
TEST_ASSERT(uffd_mode == UFFDIO_REGISTER_MODE_MISSING, "The only expected UFFD mode is MISSING"); - ASSERT_EQ(addr, (uint64_t)args->hva); + TEST_ASSERT_EQ(addr, (uint64_t)args->hva);
pr_debug("uffd fault: addr=%p write=%d\n", (void *)addr, !!(flags & UFFD_PAGEFAULT_FLAG_WRITE)); @@ -432,7 +432,7 @@ static void mmio_on_test_gpa_handler(struct kvm_vm *vm, struct kvm_run *run) region = vm_get_mem_region(vm, MEM_REGION_TEST_DATA); hva = (void *)region->region.userspace_addr;
- ASSERT_EQ(run->mmio.phys_addr, region->region.guest_phys_addr); + TEST_ASSERT_EQ(run->mmio.phys_addr, region->region.guest_phys_addr);
memcpy(hva, run->mmio.data, run->mmio.len); events.mmio_exits += 1; @@ -631,9 +631,9 @@ static void setup_default_handlers(struct test_desc *test)
static void check_event_counts(struct test_desc *test) { - ASSERT_EQ(test->expected_events.uffd_faults, events.uffd_faults); - ASSERT_EQ(test->expected_events.mmio_exits, events.mmio_exits); - ASSERT_EQ(test->expected_events.fail_vcpu_runs, events.fail_vcpu_runs); + TEST_ASSERT_EQ(test->expected_events.uffd_faults, events.uffd_faults); + TEST_ASSERT_EQ(test->expected_events.mmio_exits, events.mmio_exits); + TEST_ASSERT_EQ(test->expected_events.fail_vcpu_runs, events.fail_vcpu_runs); }
static void print_test_banner(enum vm_guest_mode mode, struct test_params *p) diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h index a6e9f215ce700..e734e52d8a3a6 100644 --- a/tools/testing/selftests/kvm/include/test_util.h +++ b/tools/testing/selftests/kvm/include/test_util.h @@ -53,11 +53,11 @@ void test_assert(bool exp, const char *exp_str, #define TEST_ASSERT(e, fmt, ...) \ test_assert((e), #e, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
-#define ASSERT_EQ(a, b) do { \ +#define TEST_ASSERT_EQ(a, b) do { \ typeof(a) __a = (a); \ typeof(b) __b = (b); \ TEST_ASSERT(__a == __b, \ - "ASSERT_EQ(%s, %s) failed.\n" \ + "TEST_ASSERT_EQ(%s, %s) failed.\n" \ "\t%s is %#lx\n" \ "\t%s is %#lx", \ #a, #b, #a, (unsigned long) __a, #b, (unsigned long) __b); \ diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 9741a7ff6380f..3170d7a4520be 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -994,7 +994,7 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm, if (src_type == VM_MEM_SRC_ANONYMOUS_THP) alignment = max(backing_src_pagesz, alignment);
- ASSERT_EQ(guest_paddr, align_up(guest_paddr, backing_src_pagesz)); + TEST_ASSERT_EQ(guest_paddr, align_up(guest_paddr, backing_src_pagesz));
/* Add enough memory to align up if necessary */ if (alignment > 1) diff --git a/tools/testing/selftests/kvm/max_guest_memory_test.c b/tools/testing/selftests/kvm/max_guest_memory_test.c index feaf2be20ff25..6628dc4dda89f 100644 --- a/tools/testing/selftests/kvm/max_guest_memory_test.c +++ b/tools/testing/selftests/kvm/max_guest_memory_test.c @@ -55,7 +55,7 @@ static void rendezvous_with_boss(void) static void run_vcpu(struct kvm_vcpu *vcpu) { vcpu_run(vcpu); - ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE); + TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE); }
static void *vcpu_worker(void *data) diff --git a/tools/testing/selftests/kvm/s390x/cmma_test.c b/tools/testing/selftests/kvm/s390x/cmma_test.c index 1d73e78e8fa77..c8e0a6495a63a 100644 --- a/tools/testing/selftests/kvm/s390x/cmma_test.c +++ b/tools/testing/selftests/kvm/s390x/cmma_test.c @@ -237,8 +237,8 @@ static void test_get_cmma_basic(void)
/* GET_CMMA_BITS without CMMA enabled should fail */ rc = vm_get_cmma_bits(vm, 0, &errno_out); - ASSERT_EQ(rc, -1); - ASSERT_EQ(errno_out, ENXIO); + TEST_ASSERT_EQ(rc, -1); + TEST_ASSERT_EQ(errno_out, ENXIO);
enable_cmma(vm); vcpu = vm_vcpu_add(vm, 1, guest_do_one_essa); @@ -247,31 +247,31 @@ static void test_get_cmma_basic(void)
/* GET_CMMA_BITS without migration mode and without peeking should fail */ rc = vm_get_cmma_bits(vm, 0, &errno_out); - ASSERT_EQ(rc, -1); - ASSERT_EQ(errno_out, EINVAL); + TEST_ASSERT_EQ(rc, -1); + TEST_ASSERT_EQ(errno_out, EINVAL);
/* GET_CMMA_BITS without migration mode and with peeking should work */ rc = vm_get_cmma_bits(vm, KVM_S390_CMMA_PEEK, &errno_out); - ASSERT_EQ(rc, 0); - ASSERT_EQ(errno_out, 0); + TEST_ASSERT_EQ(rc, 0); + TEST_ASSERT_EQ(errno_out, 0);
enable_dirty_tracking(vm); enable_migration_mode(vm);
/* GET_CMMA_BITS with invalid flags */ rc = vm_get_cmma_bits(vm, 0xfeedc0fe, &errno_out); - ASSERT_EQ(rc, -1); - ASSERT_EQ(errno_out, EINVAL); + TEST_ASSERT_EQ(rc, -1); + TEST_ASSERT_EQ(errno_out, EINVAL);
kvm_vm_free(vm); }
static void assert_exit_was_hypercall(struct kvm_vcpu *vcpu) { - ASSERT_EQ(vcpu->run->exit_reason, 13); - ASSERT_EQ(vcpu->run->s390_sieic.icptcode, 4); - ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0x8300); - ASSERT_EQ(vcpu->run->s390_sieic.ipb, 0x5010000); + TEST_ASSERT_EQ(vcpu->run->exit_reason, 13); + TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, 4); + TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0x8300); + TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipb, 0x5010000); }
static void test_migration_mode(void) @@ -283,8 +283,8 @@ static void test_migration_mode(void)
/* enabling migration mode on a VM without memory should fail */ rc = __enable_migration_mode(vm); - ASSERT_EQ(rc, -1); - ASSERT_EQ(errno, EINVAL); + TEST_ASSERT_EQ(rc, -1); + TEST_ASSERT_EQ(errno, EINVAL); TEST_ASSERT(!is_migration_mode_on(vm), "migration mode should still be off"); errno = 0;
@@ -304,8 +304,8 @@ static void test_migration_mode(void)
/* migration mode when memslots have dirty tracking off should fail */ rc = __enable_migration_mode(vm); - ASSERT_EQ(rc, -1); - ASSERT_EQ(errno, EINVAL); + TEST_ASSERT_EQ(rc, -1); + TEST_ASSERT_EQ(errno, EINVAL); TEST_ASSERT(!is_migration_mode_on(vm), "migration mode should still be off"); errno = 0;
@@ -314,7 +314,7 @@ static void test_migration_mode(void)
/* enabling migration mode should work now */ rc = __enable_migration_mode(vm); - ASSERT_EQ(rc, 0); + TEST_ASSERT_EQ(rc, 0); TEST_ASSERT(is_migration_mode_on(vm), "migration mode should be on"); errno = 0;
@@ -350,7 +350,7 @@ static void test_migration_mode(void) */ vm_mem_region_set_flags(vm, TEST_DATA_TWO_MEMSLOT, KVM_MEM_LOG_DIRTY_PAGES); rc = __enable_migration_mode(vm); - ASSERT_EQ(rc, 0); + TEST_ASSERT_EQ(rc, 0); TEST_ASSERT(is_migration_mode_on(vm), "migration mode should be on"); errno = 0;
@@ -394,9 +394,9 @@ static void assert_all_slots_cmma_dirty(struct kvm_vm *vm) }; memset(cmma_value_buf, 0xff, sizeof(cmma_value_buf)); vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, &args); - ASSERT_EQ(args.count, MAIN_PAGE_COUNT); - ASSERT_EQ(args.remaining, TEST_DATA_PAGE_COUNT); - ASSERT_EQ(args.start_gfn, 0); + TEST_ASSERT_EQ(args.count, MAIN_PAGE_COUNT); + TEST_ASSERT_EQ(args.remaining, TEST_DATA_PAGE_COUNT); + TEST_ASSERT_EQ(args.start_gfn, 0);
/* ...and then - after a hole - the TEST_DATA memslot should follow */ args = (struct kvm_s390_cmma_log){ @@ -407,9 +407,9 @@ static void assert_all_slots_cmma_dirty(struct kvm_vm *vm) }; memset(cmma_value_buf, 0xff, sizeof(cmma_value_buf)); vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, &args); - ASSERT_EQ(args.count, TEST_DATA_PAGE_COUNT); - ASSERT_EQ(args.start_gfn, TEST_DATA_START_GFN); - ASSERT_EQ(args.remaining, 0); + TEST_ASSERT_EQ(args.count, TEST_DATA_PAGE_COUNT); + TEST_ASSERT_EQ(args.start_gfn, TEST_DATA_START_GFN); + TEST_ASSERT_EQ(args.remaining, 0);
/* ...and nothing else should be there */ args = (struct kvm_s390_cmma_log){ @@ -420,9 +420,9 @@ static void assert_all_slots_cmma_dirty(struct kvm_vm *vm) }; memset(cmma_value_buf, 0xff, sizeof(cmma_value_buf)); vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, &args); - ASSERT_EQ(args.count, 0); - ASSERT_EQ(args.start_gfn, 0); - ASSERT_EQ(args.remaining, 0); + TEST_ASSERT_EQ(args.count, 0); + TEST_ASSERT_EQ(args.start_gfn, 0); + TEST_ASSERT_EQ(args.remaining, 0); }
/** @@ -498,11 +498,11 @@ static void assert_cmma_dirty(u64 first_dirty_gfn, u64 dirty_gfn_count, const struct kvm_s390_cmma_log *res) { - ASSERT_EQ(res->start_gfn, first_dirty_gfn); - ASSERT_EQ(res->count, dirty_gfn_count); + TEST_ASSERT_EQ(res->start_gfn, first_dirty_gfn); + TEST_ASSERT_EQ(res->count, dirty_gfn_count); for (size_t i = 0; i < dirty_gfn_count; i++) - ASSERT_EQ(cmma_value_buf[0], 0x0); /* stable state */ - ASSERT_EQ(cmma_value_buf[dirty_gfn_count], 0xff); /* not touched */ + TEST_ASSERT_EQ(cmma_value_buf[0], 0x0); /* stable state */ + TEST_ASSERT_EQ(cmma_value_buf[dirty_gfn_count], 0xff); /* not touched */ }
static void test_get_skip_holes(void) diff --git a/tools/testing/selftests/kvm/s390x/memop.c b/tools/testing/selftests/kvm/s390x/memop.c index 8e4b94d7b8dd9..de73dc0309051 100644 --- a/tools/testing/selftests/kvm/s390x/memop.c +++ b/tools/testing/selftests/kvm/s390x/memop.c @@ -281,8 +281,8 @@ enum stage { if (uc.cmd == UCALL_ABORT) { \ REPORT_GUEST_ASSERT_2(uc, "hints: %lu, %lu"); \ } \ - ASSERT_EQ(uc.cmd, UCALL_SYNC); \ - ASSERT_EQ(uc.args[1], __stage); \ + TEST_ASSERT_EQ(uc.cmd, UCALL_SYNC); \ + TEST_ASSERT_EQ(uc.args[1], __stage); \ }) \
static void prepare_mem12(void) @@ -808,7 +808,7 @@ static void test_termination(void) HOST_SYNC(t.vcpu, STAGE_IDLED); MOP(t.vm, ABSOLUTE, READ, &teid, sizeof(teid), GADDR(prefix + 168)); /* Bits 56, 60, 61 form a code, 0 being the only one allowing for termination */ - ASSERT_EQ(teid & teid_mask, 0); + TEST_ASSERT_EQ(teid & teid_mask, 0);
kvm_vm_free(t.kvm_vm); } diff --git a/tools/testing/selftests/kvm/s390x/tprot.c b/tools/testing/selftests/kvm/s390x/tprot.c index a9a0b76e5fa45..40d3ea16c052f 100644 --- a/tools/testing/selftests/kvm/s390x/tprot.c +++ b/tools/testing/selftests/kvm/s390x/tprot.c @@ -191,8 +191,8 @@ static void guest_code(void) get_ucall(__vcpu, &uc); \ if (uc.cmd == UCALL_ABORT) \ REPORT_GUEST_ASSERT_2(uc, "hints: %lu, %lu"); \ - ASSERT_EQ(uc.cmd, UCALL_SYNC); \ - ASSERT_EQ(uc.args[1], __stage); \ + TEST_ASSERT_EQ(uc.cmd, UCALL_SYNC); \ + TEST_ASSERT_EQ(uc.args[1], __stage); \ })
#define HOST_SYNC(vcpu, stage) \ diff --git a/tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c b/tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c index beb7e2c102113..634c6bfcd5720 100644 --- a/tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c +++ b/tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c @@ -72,7 +72,7 @@ static void vcpu_worker(struct memstress_vcpu_args *vcpu_args)
vcpu_run(vcpu);
- ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_SYNC); + TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_SYNC);
vcpu_last_completed_iteration[vcpu_idx] = current_iteration;
@@ -179,12 +179,12 @@ static void run_test(enum vm_guest_mode mode, void *unused) * with that capability. */ if (dirty_log_manual_caps) { - ASSERT_EQ(stats_clear_pass[0].hugepages, 0); - ASSERT_EQ(stats_clear_pass[0].pages_4k, total_4k_pages); - ASSERT_EQ(stats_dirty_logging_enabled.hugepages, stats_populated.hugepages); + TEST_ASSERT_EQ(stats_clear_pass[0].hugepages, 0); + TEST_ASSERT_EQ(stats_clear_pass[0].pages_4k, total_4k_pages); + TEST_ASSERT_EQ(stats_dirty_logging_enabled.hugepages, stats_populated.hugepages); } else { - ASSERT_EQ(stats_dirty_logging_enabled.hugepages, 0); - ASSERT_EQ(stats_dirty_logging_enabled.pages_4k, total_4k_pages); + TEST_ASSERT_EQ(stats_dirty_logging_enabled.hugepages, 0); + TEST_ASSERT_EQ(stats_dirty_logging_enabled.pages_4k, total_4k_pages); }
/* @@ -192,9 +192,9 @@ static void run_test(enum vm_guest_mode mode, void *unused) * memory again, the page counts should be the same as they were * right after initial population of memory. */ - ASSERT_EQ(stats_populated.pages_4k, stats_repopulated.pages_4k); - ASSERT_EQ(stats_populated.pages_2m, stats_repopulated.pages_2m); - ASSERT_EQ(stats_populated.pages_1g, stats_repopulated.pages_1g); + TEST_ASSERT_EQ(stats_populated.pages_4k, stats_repopulated.pages_4k); + TEST_ASSERT_EQ(stats_populated.pages_2m, stats_repopulated.pages_2m); + TEST_ASSERT_EQ(stats_populated.pages_1g, stats_repopulated.pages_1g); }
static void help(char *name) diff --git a/tools/testing/selftests/kvm/x86_64/exit_on_emulation_failure_test.c b/tools/testing/selftests/kvm/x86_64/exit_on_emulation_failure_test.c index e334844d6e1d7..6c2e5e0ceb1f7 100644 --- a/tools/testing/selftests/kvm/x86_64/exit_on_emulation_failure_test.c +++ b/tools/testing/selftests/kvm/x86_64/exit_on_emulation_failure_test.c @@ -35,7 +35,7 @@ int main(int argc, char *argv[]) vcpu_run(vcpu); handle_flds_emulation_failure_exit(vcpu); vcpu_run(vcpu); - ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE); + TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE);
kvm_vm_free(vm); return 0; diff --git a/tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c b/tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c index 6502aa23c2f84..5f074a6da90cd 100644 --- a/tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c +++ b/tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c @@ -247,12 +247,12 @@ int main(int argc, char *argv[])
/* Verify the pending events comes back out the same as it went in. */ vcpu_events_get(vcpu, &events); - ASSERT_EQ(events.flags & KVM_VCPUEVENT_VALID_PAYLOAD, - KVM_VCPUEVENT_VALID_PAYLOAD); - ASSERT_EQ(events.exception.pending, true); - ASSERT_EQ(events.exception.nr, SS_VECTOR); - ASSERT_EQ(events.exception.has_error_code, true); - ASSERT_EQ(events.exception.error_code, SS_ERROR_CODE); + TEST_ASSERT_EQ(events.flags & KVM_VCPUEVENT_VALID_PAYLOAD, + KVM_VCPUEVENT_VALID_PAYLOAD); + TEST_ASSERT_EQ(events.exception.pending, true); + TEST_ASSERT_EQ(events.exception.nr, SS_VECTOR); + TEST_ASSERT_EQ(events.exception.has_error_code, true); + TEST_ASSERT_EQ(events.exception.error_code, SS_ERROR_CODE);
/* * Run for real with the pending #SS, L1 should get a VM-Exit due to diff --git a/tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c b/tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c index 4c416ebe7d66d..cbc92a862ea9c 100644 --- a/tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c +++ b/tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c @@ -57,7 +57,7 @@ int main(void) for (i = 0; i < KVM_MAX_VCPUS; i++) vcpu_set_msr(vcpus[i], MSR_IA32_APICBASE, LAPIC_X2APIC);
- ASSERT_EQ(pthread_create(&thread, NULL, race, vcpus[0]), 0); + TEST_ASSERT_EQ(pthread_create(&thread, NULL, race, vcpus[0]), 0);
vcpuN = vcpus[KVM_MAX_VCPUS - 1]; for (t = time(NULL) + TIMEOUT; time(NULL) < t;) { @@ -65,8 +65,8 @@ int main(void) vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_DISABLED); }
- ASSERT_EQ(pthread_cancel(thread), 0); - ASSERT_EQ(pthread_join(thread, NULL), 0); + TEST_ASSERT_EQ(pthread_cancel(thread), 0); + TEST_ASSERT_EQ(pthread_join(thread, NULL), 0);
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c b/tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c index c9f67702f657f..9265965bd2cd3 100644 --- a/tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c +++ b/tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c @@ -103,39 +103,39 @@ int main(void) vm = vm_create_with_one_vcpu(&vcpu, guest_code);
val = 0; - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
/* Guest: writes to MSR_IA32_TSC affect both MSRs. */ run_vcpu(vcpu, 1); val = 1ull * GUEST_STEP; - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
/* Guest: writes to MSR_IA32_TSC_ADJUST affect both MSRs. */ run_vcpu(vcpu, 2); val = 2ull * GUEST_STEP; - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
/* * Host: writes to MSR_IA32_TSC set the host-side offset * and therefore do not change MSR_IA32_TSC_ADJUST. */ vcpu_set_msr(vcpu, MSR_IA32_TSC, HOST_ADJUST + val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val); run_vcpu(vcpu, 3);
/* Host: writes to MSR_IA32_TSC_ADJUST do not modify the TSC. */ vcpu_set_msr(vcpu, MSR_IA32_TSC_ADJUST, UNITY * 123456); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val); - ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_TSC_ADJUST), UNITY * 123456); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val); + TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_TSC_ADJUST), UNITY * 123456);
/* Restore previous value. */ vcpu_set_msr(vcpu, MSR_IA32_TSC_ADJUST, val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
/* * Guest: writes to MSR_IA32_TSC_ADJUST do not destroy the @@ -143,8 +143,8 @@ int main(void) */ run_vcpu(vcpu, 4); val = 3ull * GUEST_STEP; - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
/* * Guest: writes to MSR_IA32_TSC affect both MSRs, so the host-side @@ -152,8 +152,8 @@ int main(void) */ run_vcpu(vcpu, 5); val = 4ull * GUEST_STEP; - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val); - ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val - HOST_ADJUST); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val); + TEST_ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val - HOST_ADJUST);
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c b/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c index be0bdb8c6f78c..a9b827c69f32c 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c @@ -50,7 +50,7 @@ static void set_timer(void) timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 200; timer.it_interval = timer.it_value; - ASSERT_EQ(setitimer(ITIMER_REAL, &timer, NULL), 0); + TEST_ASSERT_EQ(setitimer(ITIMER_REAL, &timer, NULL), 0); }
static void set_or_clear_invalid_guest_state(struct kvm_vcpu *vcpu, bool set) diff --git a/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c b/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c index 4c90f76930f99..34efd57c2b32f 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c @@ -103,7 +103,8 @@ static void test_guest_wrmsr_perf_capabilities(union perf_capabilities host_cap) TEST_FAIL("Unexpected ucall: %lu", uc.cmd); }
- ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES), host_cap.capabilities); + TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES), + host_cap.capabilities);
vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
diff --git a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c index 396c13f42457d..ab75b873a4ad8 100644 --- a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c +++ b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c @@ -65,17 +65,17 @@ static void ____test_icr(struct xapic_vcpu *x, uint64_t val) vcpu_ioctl(vcpu, KVM_SET_LAPIC, &xapic);
vcpu_run(vcpu); - ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); - ASSERT_EQ(uc.args[1], val); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); + TEST_ASSERT_EQ(uc.args[1], val);
vcpu_ioctl(vcpu, KVM_GET_LAPIC, &xapic); icr = (u64)(*((u32 *)&xapic.regs[APIC_ICR])) | (u64)(*((u32 *)&xapic.regs[APIC_ICR2])) << 32; if (!x->is_x2apic) { val &= (-1u | (0xffull << (32 + 24))); - ASSERT_EQ(icr, val & ~APIC_ICR_BUSY); + TEST_ASSERT_EQ(icr, val & ~APIC_ICR_BUSY); } else { - ASSERT_EQ(icr & ~APIC_ICR_BUSY, val & ~APIC_ICR_BUSY); + TEST_ASSERT_EQ(icr & ~APIC_ICR_BUSY, val & ~APIC_ICR_BUSY); } }
diff --git a/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c b/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c index c94cde3b523f2..e149d0574961c 100644 --- a/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c +++ b/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c @@ -108,16 +108,16 @@ int main(int argc, char *argv[]) vcpu_run(vcpu);
if (run->exit_reason == KVM_EXIT_XEN) { - ASSERT_EQ(run->xen.type, KVM_EXIT_XEN_HCALL); - ASSERT_EQ(run->xen.u.hcall.cpl, 0); - ASSERT_EQ(run->xen.u.hcall.longmode, 1); - ASSERT_EQ(run->xen.u.hcall.input, INPUTVALUE); - ASSERT_EQ(run->xen.u.hcall.params[0], ARGVALUE(1)); - ASSERT_EQ(run->xen.u.hcall.params[1], ARGVALUE(2)); - ASSERT_EQ(run->xen.u.hcall.params[2], ARGVALUE(3)); - ASSERT_EQ(run->xen.u.hcall.params[3], ARGVALUE(4)); - ASSERT_EQ(run->xen.u.hcall.params[4], ARGVALUE(5)); - ASSERT_EQ(run->xen.u.hcall.params[5], ARGVALUE(6)); + TEST_ASSERT_EQ(run->xen.type, KVM_EXIT_XEN_HCALL); + TEST_ASSERT_EQ(run->xen.u.hcall.cpl, 0); + TEST_ASSERT_EQ(run->xen.u.hcall.longmode, 1); + TEST_ASSERT_EQ(run->xen.u.hcall.input, INPUTVALUE); + TEST_ASSERT_EQ(run->xen.u.hcall.params[0], ARGVALUE(1)); + TEST_ASSERT_EQ(run->xen.u.hcall.params[1], ARGVALUE(2)); + TEST_ASSERT_EQ(run->xen.u.hcall.params[2], ARGVALUE(3)); + TEST_ASSERT_EQ(run->xen.u.hcall.params[3], ARGVALUE(4)); + TEST_ASSERT_EQ(run->xen.u.hcall.params[4], ARGVALUE(5)); + TEST_ASSERT_EQ(run->xen.u.hcall.params[5], ARGVALUE(6)); run->xen.u.hcall.result = RETVALUE; continue; }
On 12/7/23 09:59, Thomas Huth wrote:
There is already an ASSERT_EQ macro in the file tools/testing/selftests/kselftest_harness.h, so we currently can't include test_util.h from the KVM selftests together with that file. Rename the macro in the KVM selftests to TEST_ASSERT_EQ to avoid the problem - it is also more similar to the other macros in test_util.h that way.
Suggested-by: Sean Christopherson seanjc@google.com Signed-off-by: Thomas Huth thuth@redhat.com
.../selftests/kvm/aarch64/aarch32_id_regs.c | 8 +-- .../selftests/kvm/aarch64/page_fault_test.c | 10 +-- .../testing/selftests/kvm/include/test_util.h | 4 +- tools/testing/selftests/kvm/lib/kvm_util.c | 2 +- .../selftests/kvm/max_guest_memory_test.c | 2 +- tools/testing/selftests/kvm/s390x/cmma_test.c | 62 +++++++++---------- tools/testing/selftests/kvm/s390x/memop.c | 6 +- tools/testing/selftests/kvm/s390x/tprot.c | 4 +- .../x86_64/dirty_log_page_splitting_test.c | 18 +++--- .../x86_64/exit_on_emulation_failure_test.c | 2 +- .../kvm/x86_64/nested_exceptions_test.c | 12 ++-- .../kvm/x86_64/recalc_apic_map_test.c | 6 +- .../selftests/kvm/x86_64/tsc_msrs_test.c | 32 +++++----- .../vmx_exception_with_invalid_guest_state.c | 2 +- .../selftests/kvm/x86_64/vmx_pmu_caps_test.c | 3 +- .../selftests/kvm/x86_64/xapic_state_test.c | 8 +-- .../selftests/kvm/x86_64/xen_vmcall_test.c | 20 +++--- 17 files changed, 101 insertions(+), 100 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé philmd@linaro.org
The sync_regs test currently does not have any output (unless one of the TEST_ASSERT statement fails), so it's hard to say for a user whether a certain new sub-test has been included in the binary or not. Let's make this a little bit more user-friendly and include some TAP output via the kselftest_harness.h interface. To be able to use the interface, we have to break up the huge main() function here in more fine grained parts - then we can use the TEST_F() macro to define the individual tests. Since these are run with a separate VM now, we have also to make sure to create the expected state at the beginning of each test, so some parts grow a little bit - which should be OK considering that the individual tests are more self-contained now.
Suggested-by: David Matlack dmatlack@google.com Signed-off-by: Thomas Huth thuth@redhat.com --- .../selftests/kvm/x86_64/sync_regs_test.c | 113 +++++++++++++++--- 1 file changed, 98 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c index 2da89fdc2471a..e1359a4a07fea 100644 --- a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c +++ b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c @@ -16,6 +16,7 @@ #include <string.h> #include <sys/ioctl.h>
+#include "kselftest_harness.h" #include "test_util.h" #include "kvm_util.h" #include "processor.h" @@ -80,23 +81,24 @@ static void compare_vcpu_events(struct kvm_vcpu_events *left, #define TEST_SYNC_FIELDS (KVM_SYNC_X86_REGS|KVM_SYNC_X86_SREGS|KVM_SYNC_X86_EVENTS) #define INVALID_SYNC_FIELD 0x80000000
-int main(int argc, char *argv[]) -{ - struct kvm_vcpu *vcpu; +FIXTURE(sync_regs_test) { struct kvm_vm *vm; - struct kvm_run *run; - struct kvm_regs regs; - struct kvm_sregs sregs; - struct kvm_vcpu_events events; - int rv, cap; + struct kvm_vcpu *vcpu; +};
- cap = kvm_check_cap(KVM_CAP_SYNC_REGS); - TEST_REQUIRE((cap & TEST_SYNC_FIELDS) == TEST_SYNC_FIELDS); - TEST_REQUIRE(!(cap & INVALID_SYNC_FIELD)); +FIXTURE_SETUP(sync_regs_test) { + self->vm = vm_create_with_one_vcpu(&self->vcpu, guest_code); +}
- vm = vm_create_with_one_vcpu(&vcpu, guest_code); +FIXTURE_TEARDOWN(sync_regs_test) { + kvm_vm_free(self->vm); +}
- run = vcpu->run; +TEST_F(sync_regs_test, read_invalid) +{ + struct kvm_vcpu *vcpu = self->vcpu; + struct kvm_run *run = vcpu->run; + int rv;
/* Request reading invalid register set from VCPU. */ run->kvm_valid_regs = INVALID_SYNC_FIELD; @@ -112,6 +114,13 @@ int main(int argc, char *argv[]) "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n", rv); run->kvm_valid_regs = 0; +} + +TEST_F(sync_regs_test, set_invalid) +{ + struct kvm_vcpu *vcpu = self->vcpu; + struct kvm_run *run = vcpu->run; + int rv;
/* Request setting invalid register set into VCPU. */ run->kvm_dirty_regs = INVALID_SYNC_FIELD; @@ -127,11 +136,22 @@ int main(int argc, char *argv[]) "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n", rv); run->kvm_dirty_regs = 0; +} + +TEST_F(sync_regs_test, req_and_verify_all_valid) +{ + struct kvm_vcpu *vcpu = self->vcpu; + struct kvm_run *run = vcpu->run; + struct kvm_vcpu_events events; + struct kvm_sregs sregs; + struct kvm_regs regs; + int rv;
/* Request and verify all valid register sets. */ /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */ run->kvm_valid_regs = TEST_SYNC_FIELDS; rv = _vcpu_run(vcpu); + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
vcpu_regs_get(vcpu, ®s); @@ -142,6 +162,22 @@ int main(int argc, char *argv[])
vcpu_events_get(vcpu, &events); compare_vcpu_events(&events, &run->s.regs.events); +} + +TEST_F(sync_regs_test, set_and_verify_various) +{ + struct kvm_vcpu *vcpu = self->vcpu; + struct kvm_run *run = vcpu->run; + struct kvm_vcpu_events events; + struct kvm_sregs sregs; + struct kvm_regs regs; + int rv; + + /* Run once to get register set */ + run->kvm_valid_regs = TEST_SYNC_FIELDS; + rv = _vcpu_run(vcpu); + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Set and verify various register values. */ run->s.regs.regs.rbx = 0xBAD1DEA; @@ -151,6 +187,7 @@ int main(int argc, char *argv[]) run->kvm_valid_regs = TEST_SYNC_FIELDS; run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS; rv = _vcpu_run(vcpu); + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xBAD1DEA + 1, "rbx sync regs value incorrect 0x%llx.", @@ -167,6 +204,13 @@ int main(int argc, char *argv[])
vcpu_events_get(vcpu, &events); compare_vcpu_events(&events, &run->s.regs.events); +} + +TEST_F(sync_regs_test, clear_kvm_dirty_regs_bits) +{ + struct kvm_vcpu *vcpu = self->vcpu; + struct kvm_run *run = vcpu->run; + int rv;
/* Clear kvm_dirty_regs bits, verify new s.regs values are * overwritten with existing guest values. @@ -175,10 +219,25 @@ int main(int argc, char *argv[]) run->kvm_dirty_regs = 0; run->s.regs.regs.rbx = 0xDEADBEEF; rv = _vcpu_run(vcpu); + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx != 0xDEADBEEF, "rbx sync regs value incorrect 0x%llx.", run->s.regs.regs.rbx); +} + +TEST_F(sync_regs_test, clear_kvm_valid_and_dirty_regs) +{ + struct kvm_vcpu *vcpu = self->vcpu; + struct kvm_run *run = vcpu->run; + struct kvm_regs regs; + int rv; + + /* Run once to get register set */ + run->kvm_valid_regs = TEST_SYNC_FIELDS; + rv = _vcpu_run(vcpu); + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Clear kvm_valid_regs bits and kvm_dirty_bits. * Verify s.regs values are not overwritten with existing guest values @@ -187,9 +246,11 @@ int main(int argc, char *argv[]) run->kvm_valid_regs = 0; run->kvm_dirty_regs = 0; run->s.regs.regs.rbx = 0xAAAA; + vcpu_regs_get(vcpu, ®s); regs.rbx = 0xBAC0; vcpu_regs_set(vcpu, ®s); rv = _vcpu_run(vcpu); + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xAAAA, "rbx sync regs value incorrect 0x%llx.", @@ -198,6 +259,20 @@ int main(int argc, char *argv[]) TEST_ASSERT(regs.rbx == 0xBAC0 + 1, "rbx guest value incorrect 0x%llx.", regs.rbx); +} + +TEST_F(sync_regs_test, clear_kvm_valid_regs_bits) +{ + struct kvm_vcpu *vcpu = self->vcpu; + struct kvm_run *run = vcpu->run; + struct kvm_regs regs; + int rv; + + /* Run once to get register set */ + run->kvm_valid_regs = TEST_SYNC_FIELDS; + rv = _vcpu_run(vcpu); + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten * with existing guest values but that guest values are overwritten @@ -207,6 +282,7 @@ int main(int argc, char *argv[]) run->kvm_dirty_regs = TEST_SYNC_FIELDS; run->s.regs.regs.rbx = 0xBBBB; rv = _vcpu_run(vcpu); + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xBBBB, "rbx sync regs value incorrect 0x%llx.", @@ -215,8 +291,15 @@ int main(int argc, char *argv[]) TEST_ASSERT(regs.rbx == 0xBBBB + 1, "rbx guest value incorrect 0x%llx.", regs.rbx); +} + +int main(int argc, char *argv[]) +{ + int cap;
- kvm_vm_free(vm); + cap = kvm_check_cap(KVM_CAP_SYNC_REGS); + TEST_REQUIRE((cap & TEST_SYNC_FIELDS) == TEST_SYNC_FIELDS); + TEST_REQUIRE(!(cap & INVALID_SYNC_FIELD));
- return 0; + return test_harness_run(argc, argv); }
On Wed, Jul 12, 2023, Thomas Huth wrote:
The sync_regs test currently does not have any output (unless one of the TEST_ASSERT statement fails), so it's hard to say for a user whether a certain new sub-test has been included in the binary or not. Let's make this a little bit more user-friendly and include some TAP output via the kselftest_harness.h interface. To be able to use the interface, we have to break up the huge main() function here in more fine grained parts - then we can use the TEST_F() macro to define the individual tests. Since these are run with a separate VM now, we have also to make sure to create the expected state at the beginning of each test, so some parts grow a little bit - which should be OK considering that the individual tests are more self-contained now.
Suggested-by: David Matlack dmatlack@google.com Signed-off-by: Thomas Huth thuth@redhat.com
.../selftests/kvm/x86_64/sync_regs_test.c | 113 +++++++++++++++---
FYI, there's an in-flight patch[*] to expand this test's coverage, and I plan on grabbing that in some form before this one (sorry). Let me know if there are any tweaks that can be done to Michal's patch to make it easier to convert the test to tap.
I'll also try to get Michal's patch into kvm-x86/next sooner than later so that you can use that as the basic.
Oh, and no need to post "KVM: selftests: Rename the ASSERT_EQ macro" in the next version, I'm planning on grabbing that one straightaway.
[*] https://lore.kernel.org/all/20230728001606.2275586-3-mhal@rbox.co
1 file changed, 98 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c index 2da89fdc2471a..e1359a4a07fea 100644 --- a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c +++ b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c @@ -16,6 +16,7 @@ #include <string.h> #include <sys/ioctl.h> +#include "kselftest_harness.h" #include "test_util.h" #include "kvm_util.h" #include "processor.h" @@ -80,23 +81,24 @@ static void compare_vcpu_events(struct kvm_vcpu_events *left, #define TEST_SYNC_FIELDS (KVM_SYNC_X86_REGS|KVM_SYNC_X86_SREGS|KVM_SYNC_X86_EVENTS) #define INVALID_SYNC_FIELD 0x80000000 -int main(int argc, char *argv[]) -{
- struct kvm_vcpu *vcpu;
+FIXTURE(sync_regs_test) { struct kvm_vm *vm;
- struct kvm_run *run;
- struct kvm_regs regs;
- struct kvm_sregs sregs;
- struct kvm_vcpu_events events;
- int rv, cap;
- struct kvm_vcpu *vcpu;
+};
- cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
- TEST_REQUIRE((cap & TEST_SYNC_FIELDS) == TEST_SYNC_FIELDS);
- TEST_REQUIRE(!(cap & INVALID_SYNC_FIELD));
+FIXTURE_SETUP(sync_regs_test) {
- self->vm = vm_create_with_one_vcpu(&self->vcpu, guest_code);
+}
- vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+FIXTURE_TEARDOWN(sync_regs_test) {
- kvm_vm_free(self->vm);
+}
- run = vcpu->run;
+TEST_F(sync_regs_test, read_invalid) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- int rv;
/* Request reading invalid register set from VCPU. */ run->kvm_valid_regs = INVALID_SYNC_FIELD; @@ -112,6 +114,13 @@ int main(int argc, char *argv[]) "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n", rv); run->kvm_valid_regs = 0; +}
+TEST_F(sync_regs_test, set_invalid) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- int rv;
/* Request setting invalid register set into VCPU. */ run->kvm_dirty_regs = INVALID_SYNC_FIELD; @@ -127,11 +136,22 @@ int main(int argc, char *argv[]) "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n", rv); run->kvm_dirty_regs = 0; +}
+TEST_F(sync_regs_test, req_and_verify_all_valid) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- struct kvm_vcpu_events events;
- struct kvm_sregs sregs;
- struct kvm_regs regs;
- int rv;
/* Request and verify all valid register sets. */ /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */ run->kvm_valid_regs = TEST_SYNC_FIELDS; rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
Just use vcpu_run() instead of _vcpu_run(). And please post that as a separate patch, I think/hope it will make the conversion-to-tap patch smaller.
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); vcpu_regs_get(vcpu, ®s); @@ -142,6 +162,22 @@ int main(int argc, char *argv[]) vcpu_events_get(vcpu, &events); compare_vcpu_events(&events, &run->s.regs.events); +}
+TEST_F(sync_regs_test, set_and_verify_various) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- struct kvm_vcpu_events events;
- struct kvm_sregs sregs;
- struct kvm_regs regs;
- int rv;
- /* Run once to get register set */
- run->kvm_valid_regs = TEST_SYNC_FIELDS;
- rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
Same comment here.
- TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Set and verify various register values. */ run->s.regs.regs.rbx = 0xBAD1DEA; @@ -151,6 +187,7 @@ int main(int argc, char *argv[]) run->kvm_valid_regs = TEST_SYNC_FIELDS; run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS; rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
And here.
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xBAD1DEA + 1, "rbx sync regs value incorrect 0x%llx.", @@ -167,6 +204,13 @@ int main(int argc, char *argv[]) vcpu_events_get(vcpu, &events); compare_vcpu_events(&events, &run->s.regs.events); +}
+TEST_F(sync_regs_test, clear_kvm_dirty_regs_bits) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- int rv;
/* Clear kvm_dirty_regs bits, verify new s.regs values are * overwritten with existing guest values. @@ -175,10 +219,25 @@ int main(int argc, char *argv[]) run->kvm_dirty_regs = 0; run->s.regs.regs.rbx = 0xDEADBEEF; rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
Here too.
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx != 0xDEADBEEF, "rbx sync regs value incorrect 0x%llx.", run->s.regs.regs.rbx); +}
+TEST_F(sync_regs_test, clear_kvm_valid_and_dirty_regs) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- struct kvm_regs regs;
- int rv;
- /* Run once to get register set */
- run->kvm_valid_regs = TEST_SYNC_FIELDS;
- rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
At least you're consistent :-)
- TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Clear kvm_valid_regs bits and kvm_dirty_bits. * Verify s.regs values are not overwritten with existing guest values @@ -187,9 +246,11 @@ int main(int argc, char *argv[]) run->kvm_valid_regs = 0; run->kvm_dirty_regs = 0; run->s.regs.regs.rbx = 0xAAAA;
- vcpu_regs_get(vcpu, ®s);
Can you split this change to its own patch too? I'm pretty sure that change stands on its own, and slotting it in here made me do a double-take.
regs.rbx = 0xBAC0; vcpu_regs_set(vcpu, ®s); rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xAAAA, "rbx sync regs value incorrect 0x%llx.",
@@ -198,6 +259,20 @@ int main(int argc, char *argv[]) TEST_ASSERT(regs.rbx == 0xBAC0 + 1, "rbx guest value incorrect 0x%llx.", regs.rbx); +}
+TEST_F(sync_regs_test, clear_kvm_valid_regs_bits) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- struct kvm_regs regs;
- int rv;
- /* Run once to get register set */
- run->kvm_valid_regs = TEST_SYNC_FIELDS;
- rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
Once more, with feeling!
- TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten * with existing guest values but that guest values are overwritten @@ -207,6 +282,7 @@ int main(int argc, char *argv[]) run->kvm_dirty_regs = TEST_SYNC_FIELDS; run->s.regs.regs.rbx = 0xBBBB; rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
Heh.
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xBBBB, "rbx sync regs value incorrect 0x%llx.", @@ -215,8 +291,15 @@ int main(int argc, char *argv[]) TEST_ASSERT(regs.rbx == 0xBBBB + 1, "rbx guest value incorrect 0x%llx.", regs.rbx); +}
+int main(int argc, char *argv[]) +{
- int cap;
- kvm_vm_free(vm);
- cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
- TEST_REQUIRE((cap & TEST_SYNC_FIELDS) == TEST_SYNC_FIELDS);
- TEST_REQUIRE(!(cap & INVALID_SYNC_FIELD));
- return 0;
- return test_harness_run(argc, argv);
}
2.39.3
On Wed, Aug 02, 2023, Sean Christopherson wrote:
Oh, and no need to post "KVM: selftests: Rename the ASSERT_EQ macro" in the next version, I'm planning on grabbing that one straightaway.
After paging this all back in...
I would much prefer that we implement the KVM specific macros[*], e.g. KVM_ONE_VCPU_TEST(), and build on top of those. I'm definitely ok doing a "slow" conversion, i.e. starting with a few easy tests. IIRC at some point I said I strongly preferred an all-or-nothing approach, but realistically I don't think we'll make progress anytime soon if we try to boil the ocean.
But I do think we should spend the time to implement the infrastructure right away. We may end up having to tweak the infrastructure down the road, e.g. to convert other tests, but I would rather do that then convert some tests twice.
[*] https://lore.kernel.org/all/Y2v+B3xxYKJSM%2FfH@google.com
On 02/08/2023 23.31, Sean Christopherson wrote:
On Wed, Aug 02, 2023, Sean Christopherson wrote:
Oh, and no need to post "KVM: selftests: Rename the ASSERT_EQ macro" in the next version, I'm planning on grabbing that one straightaway.
After paging this all back in...
I would much prefer that we implement the KVM specific macros[*], e.g. KVM_ONE_VCPU_TEST(), and build on top of those. I'm definitely ok doing a "slow" conversion, i.e. starting with a few easy tests. IIRC at some point I said I strongly preferred an all-or-nothing approach, but realistically I don't think we'll make progress anytime soon if we try to boil the ocean.
At least I don't have enough spare time to do such a big conversion all at once - I'm only occasionally looking at the KVM selftests, mostly for s390x, and I also lack the knowledge how to test all those x86 tests. So don't expect such a big conversion from me, all I can provide is a small patch here or there.
But I do think we should spend the time to implement the infrastructure right away. We may end up having to tweak the infrastructure down the road, e.g. to convert other tests, but I would rather do that then convert some tests twice.
[*] https://lore.kernel.org/all/Y2v+B3xxYKJSM%2FfH@google.com
Sorry, I somehow completely missed that KVM_ONE_VCPU_TEST suggestion when picking up the series up again after working on other stuff for more than half a year. I'll try to incorporate this into the next version.
(the other patches don't need a fixture, so I think they shouldn't be affected by this?)
Thomas
On 02/08/2023 21.55, Sean Christopherson wrote:
On Wed, Jul 12, 2023, Thomas Huth wrote:
The sync_regs test currently does not have any output (unless one of the TEST_ASSERT statement fails), so it's hard to say for a user whether a certain new sub-test has been included in the binary or not. Let's make this a little bit more user-friendly and include some TAP output via the kselftest_harness.h interface. To be able to use the interface, we have to break up the huge main() function here in more fine grained parts - then we can use the TEST_F() macro to define the individual tests. Since these are run with a separate VM now, we have also to make sure to create the expected state at the beginning of each test, so some parts grow a little bit - which should be OK considering that the individual tests are more self-contained now.
Suggested-by: David Matlack dmatlack@google.com Signed-off-by: Thomas Huth thuth@redhat.com
.../selftests/kvm/x86_64/sync_regs_test.c | 113 +++++++++++++++---
FYI, there's an in-flight patch[*] to expand this test's coverage, and I plan on grabbing that in some form before this one (sorry). Let me know if there are any tweaks that can be done to Michal's patch to make it easier to convert the test to tap.
I'll also try to get Michal's patch into kvm-x86/next sooner than later so that you can use that as the basic.
Ok, I'll wait 'til the dust settles and then redo my patch (there is no hurry for this, and I'm only doing it in my spare minutes).
Any chance that you could already take at least the other conversion patches from my series?
...
+TEST_F(sync_regs_test, req_and_verify_all_valid) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- struct kvm_vcpu_events events;
- struct kvm_sregs sregs;
- struct kvm_regs regs;
- int rv;
/* Request and verify all valid register sets. */ /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */ run->kvm_valid_regs = TEST_SYNC_FIELDS; rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
Just use vcpu_run() instead of _vcpu_run(). And please post that as a separate patch, I think/hope it will make the conversion-to-tap patch smaller.
Ok, makes sense.
+TEST_F(sync_regs_test, clear_kvm_valid_and_dirty_regs) +{
- struct kvm_vcpu *vcpu = self->vcpu;
- struct kvm_run *run = vcpu->run;
- struct kvm_regs regs;
- int rv;
- /* Run once to get register set */
- run->kvm_valid_regs = TEST_SYNC_FIELDS;
- rv = _vcpu_run(vcpu);
- TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
At least you're consistent :-)
Just copy-n-pasting the preexistent code ;-)
- TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Clear kvm_valid_regs bits and kvm_dirty_bits. * Verify s.regs values are not overwritten with existing guest values @@ -187,9 +246,11 @@ int main(int argc, char *argv[]) run->kvm_valid_regs = 0; run->kvm_dirty_regs = 0; run->s.regs.regs.rbx = 0xAAAA;
- vcpu_regs_get(vcpu, ®s);
Can you split this change to its own patch too? I'm pretty sure that change stands on its own, and slotting it in here made me do a double-take.
Ok.
Thomas
Use the kselftest_harness.h interface in this test to get TAP output, so that it is easier for the user to see what the test is doing.
Signed-off-by: Thomas Huth thuth@redhat.com --- .../selftests/kvm/x86_64/fix_hypercall_test.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c b/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c index 0f728f05ea82f..7621942a072ec 100644 --- a/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c +++ b/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c @@ -9,6 +9,7 @@ #include <linux/stringify.h> #include <stdint.h>
+#include "kselftest_harness.h" #include "apic.h" #include "test_util.h" #include "kvm_util.h" @@ -126,10 +127,19 @@ static void test_fix_hypercall(bool disable_quirk) enter_guest(vcpu); }
-int main(void) +TEST(fix_hypercall) { - TEST_REQUIRE(kvm_check_cap(KVM_CAP_DISABLE_QUIRKS2) & KVM_X86_QUIRK_FIX_HYPERCALL_INSN); - test_fix_hypercall(false); +} + +TEST(fix_hypercall_disable_quirk) +{ test_fix_hypercall(true); } + +int main(int argc, char *argv[]) +{ + TEST_REQUIRE(kvm_check_cap(KVM_CAP_DISABLE_QUIRKS2) & KVM_X86_QUIRK_FIX_HYPERCALL_INSN); + + return test_harness_run(argc, argv); +}
Use the kselftest_harness.h interface in this test to get TAP output, so that it is easier for the user to see what the test is doing.
Signed-off-by: Thomas Huth thuth@redhat.com --- .../kvm/x86_64/userspace_msr_exit_test.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c b/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c index 3533dc2fbfeeb..9843528bba0c6 100644 --- a/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c +++ b/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c @@ -8,6 +8,7 @@ #define _GNU_SOURCE /* for program_invocation_short_name */ #include <sys/ioctl.h>
+#include "kselftest_harness.h" #include "test_util.h" #include "kvm_util.h" #include "vmx.h" @@ -527,7 +528,7 @@ static void run_guest_then_process_ucall_done(struct kvm_vcpu *vcpu) process_ucall_done(vcpu); }
-static void test_msr_filter_allow(void) +TEST(msr_filter_allow) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; @@ -646,7 +647,7 @@ static void handle_wrmsr(struct kvm_run *run) } }
-static void test_msr_filter_deny(void) +TEST(msr_filter_deny) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; @@ -693,7 +694,7 @@ static void test_msr_filter_deny(void) kvm_vm_free(vm); }
-static void test_msr_permission_bitmap(void) +TEST(msr_permission_bitmap) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; @@ -786,7 +787,7 @@ static void run_msr_filter_flag_test(struct kvm_vm *vm) }
/* Test that attempts to write to the unused bits in a flag fails. */ -static void test_user_exit_msr_flags(void) +TEST(user_exit_msr_flags) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; @@ -804,13 +805,5 @@ static void test_user_exit_msr_flags(void)
int main(int argc, char *argv[]) { - test_msr_filter_allow(); - - test_msr_filter_deny(); - - test_msr_permission_bitmap(); - - test_user_exit_msr_flags(); - - return 0; + return test_harness_run(argc, argv); }
On 12/7/23 09:59, Thomas Huth wrote:
Use the kselftest_harness.h interface in this test to get TAP output, so that it is easier for the user to see what the test is doing.
Signed-off-by: Thomas Huth thuth@redhat.com
.../kvm/x86_64/userspace_msr_exit_test.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé philmd@linaro.org
On Wed, 12 Jul 2023 09:59:06 +0200, Thomas Huth wrote:
Here's a follow-up from my RFC series last year:
https://lore.kernel.org/lkml/20221004093131.40392-1-thuth@redhat.com/T/
Basic idea of this series is now to use the kselftest_harness.h framework to get TAP output in the tests, so that it is easier for the user to see what is going on, and e.g. to be able to detect whether a certain test is part of the test binary or not (which is useful when tests get extended in the course of time).
[...]
Applied patch 1 to kvm-x86 selftests, thanks!
[1/4] KVM: selftests: Rename the ASSERT_EQ macro https://github.com/kvm-x86/linux/commit/6d85f51a1f08
-- https://github.com/kvm-x86/linux/tree/next https://github.com/kvm-x86/linux/tree/fixes
linux-kselftest-mirror@lists.linaro.org