mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
KVM selftests changes for 7.2
- Randomize the dirty log test's delay when reaping the bitmap on the first
pass, as always waiting only 1ms hid a KVM RISC-V bug as the test reaped the
bitmap before KVM could build up enough state to hit the bug.
- A pile of one-off fixes and cleanups.
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEKTobbabEP7vbhhN9OlYIJqCjN/0FAmorQNUACgkQOlYIJqCj
N/3E2RAAqSMg2+iYYbfkjFw5kFafSDb7IWFxK4SWNWeh5C8jkfCrrviWTMOewTR8
C7YtKCMGK8iCZQfmB3jhenTEoQJEcICJn4JOUNK2RkNcC/BuNlKlM/C8dX0x29xk
m1XWZdLgwjmZr7LydzVGMgdhJdcdxK/WV/71vvFYze4Jxim4lnnTM3VoMbjj8FuS
6FdMvKbclD6Mbfx1/wvYNndl6J9Y0fhKZbsj6tpAxDmXH/Pw9zx8b49znioV4HsD
k3GE76w4Xe/cIgHwbXWTUmpf1s2Ou8ZO8ju+02u3gUz6UpIj2gbcV0mhu327EhyT
IPlepblusG6hzJAXwfmb6D8u/aXg2VfZdSsiLNNhgisNtLnakFjxdKg0ViSnKS+3
UZ49TWmPwyZ92JEC7paluB1PKv7n+GiJBfyLAU9lV7x4rXHn+nseW/ZPJ2Rvdq5n
HsLlG9smz5Q7ea8AI8yHaGYQpTbw48t52hnNqLdt0mU5Tj027nNNWVP72s+Jhc/j
N+1juth6qszxh7gLMD00AgxRtTKRpGMMV9zbieuQTg+mhmUrk5lJsCuk+su9TCzT
/UjGrmRmz2TKtA9MQ0xckA3ysR519WYdBn9EHhiQLLfLd5V01LTo0FERMovjfjyH
JUYKcyFhiZqbVqCNsloIGTv3/N3jOwxKzMhuFrmuGT9+NCyC5Fk=
=nMTy
-----END PGP SIGNATURE-----
Merge tag 'kvm-x86-selftests-7.2' of https://github.com/kvm-x86/linux into HEAD
KVM selftests changes for 7.2
- Randomize the dirty log test's delay when reaping the bitmap on the first
pass, as always waiting only 1ms hid a KVM RISC-V bug as the test reaped the
bitmap before KVM could build up enough state to hit the bug.
- A pile of one-off fixes and cleanups.
This commit is contained in:
commit
b02a4f8c42
|
|
@ -694,7 +694,17 @@ static void run_test(enum vm_guest_mode mode, void *arg)
|
|||
pthread_create(&vcpu_thread, NULL, vcpu_worker, vcpu);
|
||||
|
||||
for (iteration = 1; iteration <= p->iterations; iteration++) {
|
||||
unsigned long i;
|
||||
unsigned long i, reap_i;
|
||||
|
||||
/*
|
||||
* Select a random point in the time interval to reap the dirty
|
||||
* bitmap/ring while the guest is running, i.e. randomize how
|
||||
* long the guest gets to initially run and thus how many pages
|
||||
* it can dirty, before collecting the dirty bitmap/ring. See
|
||||
* the loop below for details.
|
||||
*/
|
||||
reap_i = random() % p->interval;
|
||||
printf("Reaping after a %lu ms delay\n", reap_i);
|
||||
|
||||
sync_global_to_guest(vm, iteration);
|
||||
|
||||
|
|
@ -729,13 +739,17 @@ static void run_test(enum vm_guest_mode mode, void *arg)
|
|||
* that's effectively blocked. Collecting while the
|
||||
* guest is running also verifies KVM doesn't lose any
|
||||
* state.
|
||||
*
|
||||
*/
|
||||
if (i < reap_i)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* For bitmap modes, KVM overwrites the entire bitmap,
|
||||
* i.e. collecting the bitmaps is destructive. Collect
|
||||
* the bitmap only on the first pass, otherwise this
|
||||
* test would lose track of dirty pages.
|
||||
* the bitmap while the guest is running only once,
|
||||
* otherwise this test would lose track of dirty pages.
|
||||
*/
|
||||
if (i && host_log_mode != LOG_MODE_DIRTY_RING)
|
||||
if (i > reap_i && host_log_mode != LOG_MODE_DIRTY_RING)
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
|
@ -745,7 +759,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
|
|||
* the ring on every pass would make it unlikely the
|
||||
* vCPU would ever fill the fing).
|
||||
*/
|
||||
if (i && !READ_ONCE(dirty_ring_vcpu_ring_full))
|
||||
if (i > reap_i && !READ_ONCE(dirty_ring_vcpu_ring_full))
|
||||
continue;
|
||||
|
||||
log_mode_collect_dirty_pages(vcpu, TEST_MEM_SLOT_INDEX,
|
||||
|
|
|
|||
|
|
@ -89,4 +89,10 @@ __KVM_SYSCALL_DEFINE(fallocate, 4, int, fd, int, mode, loff_t, offset, loff_t, l
|
|||
__KVM_SYSCALL_DEFINE(ftruncate, 2, unsigned int, fd, off_t, length);
|
||||
__KVM_SYSCALL_DEFINE(madvise, 3, void *, addr, size_t, length, int, advice);
|
||||
|
||||
#define kvm_free_fd(fd) \
|
||||
do { \
|
||||
kvm_close(fd); \
|
||||
(fd) = -1; \
|
||||
} while (0)
|
||||
|
||||
#endif /* SELFTEST_KVM_SYSCALLS_H */
|
||||
|
|
|
|||
|
|
@ -876,7 +876,7 @@ static inline int vcpu_get_stats_fd(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
int fd = __vcpu_ioctl(vcpu, KVM_GET_STATS_FD, NULL);
|
||||
|
||||
TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_CHECK_EXTENSION, fd, vcpu->vm);
|
||||
TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_GET_STATS_FD, fd, vcpu->vm);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ static ssize_t get_module_param(const char *module_name, const char *param,
|
|||
int fd, r;
|
||||
|
||||
/* Verify KVM is loaded, to provide a more helpful SKIP message. */
|
||||
close(open_kvm_dev_path_or_exit());
|
||||
fd = open_kvm_dev_path_or_exit();
|
||||
kvm_free_fd(fd);
|
||||
|
||||
r = snprintf(path, path_size, "/sys/module/%s/parameters/%s",
|
||||
module_name, param);
|
||||
|
|
@ -90,8 +91,7 @@ static ssize_t get_module_param(const char *module_name, const char *param,
|
|||
TEST_ASSERT(bytes_read > 0, "read(%s) returned %ld, wanted %ld bytes",
|
||||
path, bytes_read, buffer_size);
|
||||
|
||||
r = close(fd);
|
||||
TEST_ASSERT(!r, "close(%s) failed", path);
|
||||
kvm_free_fd(fd);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ unsigned int kvm_check_cap(long cap)
|
|||
ret = __kvm_ioctl(kvm_fd, KVM_CHECK_EXTENSION, (void *)cap);
|
||||
TEST_ASSERT(ret >= 0, KVM_IOCTL_ERROR(KVM_CHECK_EXTENSION, ret));
|
||||
|
||||
close(kvm_fd);
|
||||
kvm_free_fd(kvm_fd);
|
||||
|
||||
return (unsigned int)ret;
|
||||
}
|
||||
|
|
@ -747,8 +747,7 @@ static void kvm_stats_release(struct kvm_binary_stats *stats)
|
|||
stats->desc = NULL;
|
||||
}
|
||||
|
||||
kvm_close(stats->fd);
|
||||
stats->fd = -1;
|
||||
kvm_free_fd(stats->fd);
|
||||
}
|
||||
|
||||
__weak void vcpu_arch_free(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -777,7 +776,7 @@ static void vm_vcpu_rm(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
|
|||
|
||||
kvm_munmap(vcpu->run, vcpu_mmap_sz());
|
||||
|
||||
kvm_close(vcpu->fd);
|
||||
kvm_free_fd(vcpu->fd);
|
||||
kvm_stats_release(&vcpu->stats);
|
||||
|
||||
list_del(&vcpu->list);
|
||||
|
|
@ -793,8 +792,8 @@ void kvm_vm_release(struct kvm_vm *vmp)
|
|||
list_for_each_entry_safe(vcpu, tmp, &vmp->vcpus, list)
|
||||
vm_vcpu_rm(vmp, vcpu);
|
||||
|
||||
kvm_close(vmp->fd);
|
||||
kvm_close(vmp->kvm_fd);
|
||||
kvm_free_fd(vmp->fd);
|
||||
kvm_free_fd(vmp->kvm_fd);
|
||||
|
||||
/* Free cached stats metadata and close FD */
|
||||
kvm_stats_release(&vmp->stats);
|
||||
|
|
@ -815,10 +814,10 @@ static void __vm_mem_region_delete(struct kvm_vm *vm,
|
|||
if (region->fd >= 0) {
|
||||
/* There's an extra map when using shared memory. */
|
||||
kvm_munmap(region->mmap_alias, region->mmap_size);
|
||||
close(region->fd);
|
||||
kvm_free_fd(region->fd);
|
||||
}
|
||||
if (region->region.guest_memfd >= 0)
|
||||
close(region->region.guest_memfd);
|
||||
if ((int)region->region.guest_memfd >= 0)
|
||||
kvm_free_fd(region->region.guest_memfd);
|
||||
|
||||
free(region);
|
||||
}
|
||||
|
|
@ -1311,7 +1310,7 @@ static size_t vcpu_mmap_sz(void)
|
|||
TEST_ASSERT(ret >= 0 && ret >= sizeof(struct kvm_run),
|
||||
KVM_IOCTL_ERROR(KVM_GET_VCPU_MMAP_SIZE, ret));
|
||||
|
||||
close(dev_fd);
|
||||
kvm_free_fd(dev_fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ struct sync_area {
|
|||
*/
|
||||
static_assert(ATOMIC_BOOL_LOCK_FREE == 2, "atomic bool is not lockless");
|
||||
|
||||
static int wait_timeout = 10;
|
||||
static sem_t vcpu_ready;
|
||||
|
||||
static bool map_unmap_verify;
|
||||
|
|
@ -418,7 +419,7 @@ static bool _guest_should_exit(void)
|
|||
*/
|
||||
static noinline void host_perform_sync(struct sync_area *sync)
|
||||
{
|
||||
alarm(10);
|
||||
alarm(wait_timeout);
|
||||
|
||||
atomic_store_explicit(&sync->sync_flag, true, memory_order_release);
|
||||
while (atomic_load_explicit(&sync->sync_flag, memory_order_acquire))
|
||||
|
|
@ -900,7 +901,7 @@ static void help(char *name, struct test_args *targs)
|
|||
{
|
||||
int ctr;
|
||||
|
||||
pr_info("usage: %s [-h] [-v] [-d] [-s slots] [-f first_test] [-e last_test] [-l test_length] [-r run_count]\n",
|
||||
pr_info("usage: %s [-h] [-v] [-d] [-s slots] [-f first_test] [-e last_test] [-l test_length] [-r run_count] [-t wait_timeout]\n",
|
||||
name);
|
||||
pr_info(" -h: print this help screen.\n");
|
||||
pr_info(" -v: enable verbose mode (not for benchmarking).\n");
|
||||
|
|
@ -916,6 +917,8 @@ static void help(char *name, struct test_args *targs)
|
|||
targs->seconds);
|
||||
pr_info(" -r: specify the number of runs per test (currently: %i)\n",
|
||||
targs->runs);
|
||||
pr_info(" -t: specify the number of seconds for host wait timeout (currently: %i)\n",
|
||||
wait_timeout);
|
||||
|
||||
pr_info("\nAvailable tests:\n");
|
||||
for (ctr = 0; ctr < NTESTS; ctr++)
|
||||
|
|
@ -964,7 +967,7 @@ static bool parse_args(int argc, char *argv[],
|
|||
u32 max_mem_slots;
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "hvdqs:f:e:l:r:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "hvdqs:f:e:l:r:t:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
default:
|
||||
|
|
@ -1007,6 +1010,9 @@ static bool parse_args(int argc, char *argv[],
|
|||
case 'r':
|
||||
targs->runs = atoi_positive("Runs per test", optarg);
|
||||
break;
|
||||
case 't':
|
||||
wait_timeout = atoi_positive("Host wait timeout", optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ struct msr_data {
|
|||
bool fault_expected;
|
||||
bool write;
|
||||
u64 write_val;
|
||||
bool reset_expected;
|
||||
};
|
||||
|
||||
struct hcall_data {
|
||||
|
|
@ -267,14 +268,9 @@ static void guest_test_msrs_access(void)
|
|||
case 16:
|
||||
msr->idx = HV_X64_MSR_RESET;
|
||||
msr->write = true;
|
||||
/*
|
||||
* TODO: the test only writes '0' to HV_X64_MSR_RESET
|
||||
* at the moment, writing some other value there will
|
||||
* trigger real vCPU reset and the code is not prepared
|
||||
* to handle it yet.
|
||||
*/
|
||||
msr->write_val = 0;
|
||||
msr->write_val = 1;
|
||||
msr->fault_expected = false;
|
||||
msr->reset_expected = true;
|
||||
break;
|
||||
|
||||
case 17:
|
||||
|
|
@ -457,7 +453,7 @@ static void guest_test_msrs_access(void)
|
|||
msr->fault_expected = true;
|
||||
break;
|
||||
case 45:
|
||||
/* MSR is vailable when CPUID feature bit is set */
|
||||
/* MSR is available when CPUID feature bit is set */
|
||||
if (!has_invtsc)
|
||||
goto next_stage;
|
||||
vcpu_set_cpuid_feature(vcpu, HV_ACCESS_TSC_INVARIANT);
|
||||
|
|
@ -497,6 +493,15 @@ static void guest_test_msrs_access(void)
|
|||
msr->idx, msr->write ? "write" : "read");
|
||||
|
||||
vcpu_run(vcpu);
|
||||
|
||||
if (msr->reset_expected) {
|
||||
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SYSTEM_EVENT);
|
||||
TEST_ASSERT(vcpu->run->system_event.type == KVM_SYSTEM_EVENT_RESET,
|
||||
"Expected reset system event, got type %u",
|
||||
vcpu->run->system_event.type);
|
||||
goto next_stage;
|
||||
}
|
||||
|
||||
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
|
||||
|
||||
switch (get_ucall(vcpu, &uc)) {
|
||||
|
|
|
|||
|
|
@ -141,17 +141,6 @@ static void swap_two_test_pages(gpa_t pte_gva1, gpa_t pte_gva2)
|
|||
*(u64 *)pte_gva2 = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: replace the silly NOP loop with a proper udelay() implementation.
|
||||
*/
|
||||
static inline void do_delay(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 1000000; i++)
|
||||
asm volatile("nop");
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare to test: 'disable' workers by setting the expectation to '0',
|
||||
* clear hypercall input page and then swap two test pages.
|
||||
|
|
@ -169,7 +158,7 @@ static inline void prepare_to_test(struct test_data *data)
|
|||
wmb();
|
||||
|
||||
/* Make sure workers have enough time to notice */
|
||||
do_delay();
|
||||
udelay(100);
|
||||
|
||||
/* Swap test page mappings */
|
||||
swap_two_test_pages(data->test_pages_pte[0], data->test_pages_pte[1]);
|
||||
|
|
@ -189,7 +178,7 @@ static inline void post_test(struct test_data *data, u64 exp1, u64 exp2)
|
|||
set_expected_val((void *)data->test_pages, exp2, WORKER_VCPU_ID_2);
|
||||
|
||||
/* Make sure workers have enough time to test */
|
||||
do_delay();
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
#define TESTVAL1 0x0101010101010101
|
||||
|
|
|
|||
|
|
@ -255,7 +255,6 @@ KVM_ONE_VCPU_TEST(sync_regs_test, req_and_verify_all_valid, guest_code)
|
|||
struct kvm_regs regs;
|
||||
|
||||
/* 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;
|
||||
vcpu_run(vcpu);
|
||||
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user