Skip to content

Commit cb6c691

Browse files
committed
KVM: selftests: Provide a global pseudo-RNG instance for all tests
Add a global guest_random_state instance, i.e. a pseudo-RNG, so that an RNG is available for *all* tests. This will allow randomizing behavior in core library code, e.g. x86 will utilize the pRNG to conditionally force emulation of writes from within common guest code. To allow for deterministic runs, and to be compatible with existing tests, allow tests to override the seed used to initialize the pRNG. Note, the seed *must* be overwritten before a VM is created in order for the seed to take effect, though it's perfectly fine for a test to initialize multiple VMs with different seeds. And as evidenced by memstress_guest_code(), it's also a-ok to instantiate more RNGs using the global seed (or a modified version of it). The goal of the global RNG is purely to ensure that _a_ source of random numbers is available, it doesn't have to be the _only_ RNG. Link: https://lore.kernel.org/r/20240314185459.2439072-2-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 730cfa4 commit cb6c691

File tree

6 files changed

+23
-29
lines changed

6 files changed

+23
-29
lines changed

tools/testing/selftests/kvm/dirty_log_perf_test.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ struct test_params {
132132
enum vm_mem_backing_src_type backing_src;
133133
int slots;
134134
uint32_t write_percent;
135-
uint32_t random_seed;
136135
bool random_access;
137136
};
138137

@@ -156,8 +155,6 @@ static void run_test(enum vm_guest_mode mode, void *arg)
156155
p->slots, p->backing_src,
157156
p->partition_vcpu_memory_access);
158157

159-
pr_info("Random seed: %u\n", p->random_seed);
160-
memstress_set_random_seed(vm, p->random_seed);
161158
memstress_set_write_percent(vm, p->write_percent);
162159

163160
guest_num_pages = (nr_vcpus * guest_percpu_mem_size) >> vm->page_shift;
@@ -346,11 +343,13 @@ int main(int argc, char *argv[])
346343
.partition_vcpu_memory_access = true,
347344
.backing_src = DEFAULT_VM_MEM_SRC,
348345
.slots = 1,
349-
.random_seed = 1,
350346
.write_percent = 100,
351347
};
352348
int opt;
353349

350+
/* Override the seed to be deterministic by default. */
351+
guest_random_seed = 1;
352+
354353
dirty_log_manual_caps =
355354
kvm_check_cap(KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
356355
dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
@@ -395,7 +394,7 @@ int main(int argc, char *argv[])
395394
p.phys_offset = strtoull(optarg, NULL, 0);
396395
break;
397396
case 'r':
398-
p.random_seed = atoi_positive("Random seed", optarg);
397+
guest_random_seed = atoi_positive("Random seed", optarg);
399398
break;
400399
case 's':
401400
p.backing_src = parse_backing_src_type(optarg);

tools/testing/selftests/kvm/dirty_log_test.c

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
static uint64_t host_page_size;
7474
static uint64_t guest_page_size;
7575
static uint64_t guest_num_pages;
76-
static uint64_t random_array[TEST_PAGES_PER_LOOP];
7776
static uint64_t iteration;
7877

7978
/*
@@ -112,13 +111,12 @@ static void guest_code(void)
112111
while (true) {
113112
for (i = 0; i < TEST_PAGES_PER_LOOP; i++) {
114113
addr = guest_test_virt_mem;
115-
addr += (READ_ONCE(random_array[i]) % guest_num_pages)
114+
addr += (guest_random_u64(&guest_rng) % guest_num_pages)
116115
* guest_page_size;
117116
addr = align_down(addr, host_page_size);
118117
*(uint64_t *)addr = READ_ONCE(iteration);
119118
}
120119

121-
/* Tell the host that we need more random numbers */
122120
GUEST_SYNC(1);
123121
}
124122
}
@@ -505,20 +503,10 @@ static void log_mode_after_vcpu_run(struct kvm_vcpu *vcpu, int ret, int err)
505503
mode->after_vcpu_run(vcpu, ret, err);
506504
}
507505

508-
static void generate_random_array(uint64_t *guest_array, uint64_t size)
509-
{
510-
uint64_t i;
511-
512-
for (i = 0; i < size; i++)
513-
guest_array[i] = random();
514-
}
515-
516506
static void *vcpu_worker(void *data)
517507
{
518508
int ret;
519509
struct kvm_vcpu *vcpu = data;
520-
struct kvm_vm *vm = vcpu->vm;
521-
uint64_t *guest_array;
522510
uint64_t pages_count = 0;
523511
struct kvm_signal_mask *sigmask = alloca(offsetof(struct kvm_signal_mask, sigset)
524512
+ sizeof(sigset_t));
@@ -537,11 +525,8 @@ static void *vcpu_worker(void *data)
537525
sigemptyset(sigset);
538526
sigaddset(sigset, SIG_IPI);
539527

540-
guest_array = addr_gva2hva(vm, (vm_vaddr_t)random_array);
541-
542528
while (!READ_ONCE(host_quit)) {
543529
/* Clear any existing kick signals */
544-
generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
545530
pages_count += TEST_PAGES_PER_LOOP;
546531
/* Let the guest dirty the random pages */
547532
ret = __vcpu_run(vcpu);

tools/testing/selftests/kvm/include/memstress.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ struct kvm_vm *memstress_create_vm(enum vm_guest_mode mode, int nr_vcpus,
6262
void memstress_destroy_vm(struct kvm_vm *vm);
6363

6464
void memstress_set_write_percent(struct kvm_vm *vm, uint32_t write_percent);
65-
void memstress_set_random_seed(struct kvm_vm *vm, uint32_t random_seed);
6665
void memstress_set_random_access(struct kvm_vm *vm, bool random_access);
6766

6867
void memstress_start_vcpu_threads(int vcpus, void (*vcpu_fn)(struct memstress_vcpu_args *));

tools/testing/selftests/kvm/include/test_util.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,17 @@ struct guest_random_state {
9191
uint32_t seed;
9292
};
9393

94+
extern uint32_t guest_random_seed;
95+
extern struct guest_random_state guest_rng;
96+
9497
struct guest_random_state new_guest_random_state(uint32_t seed);
9598
uint32_t guest_random_u32(struct guest_random_state *state);
9699

100+
static inline uint64_t guest_random_u64(struct guest_random_state *state)
101+
{
102+
return ((uint64_t)guest_random_u32(state) << 32) | guest_random_u32(state);
103+
}
104+
97105
enum vm_mem_backing_src_type {
98106
VM_MEM_SRC_ANONYMOUS,
99107
VM_MEM_SRC_ANONYMOUS_THP,

tools/testing/selftests/kvm/lib/kvm_util.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
#define KVM_UTIL_MIN_PFN 2
2020

21+
uint32_t guest_random_seed;
22+
struct guest_random_state guest_rng;
23+
2124
static int vcpu_mmap_sz(void);
2225

2326
int open_path_or_exit(const char *path, int flags)
@@ -430,6 +433,10 @@ struct kvm_vm *__vm_create(struct vm_shape shape, uint32_t nr_runnable_vcpus,
430433
slot0 = memslot2region(vm, 0);
431434
ucall_init(vm, slot0->region.guest_phys_addr + slot0->region.memory_size);
432435

436+
pr_info("Random seed: 0x%x\n", guest_random_seed);
437+
guest_rng = new_guest_random_state(guest_random_seed);
438+
sync_global_to_guest(vm, guest_rng);
439+
433440
kvm_arch_vm_post_create(vm);
434441

435442
return vm;
@@ -2303,6 +2310,8 @@ void __attribute((constructor)) kvm_selftest_init(void)
23032310
/* Tell stdout not to buffer its content. */
23042311
setbuf(stdout, NULL);
23052312

2313+
guest_random_seed = random();
2314+
23062315
kvm_selftest_arch_init();
23072316
}
23082317

tools/testing/selftests/kvm/lib/memstress.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void memstress_guest_code(uint32_t vcpu_idx)
5454
uint64_t page;
5555
int i;
5656

57-
rand_state = new_guest_random_state(args->random_seed + vcpu_idx);
57+
rand_state = new_guest_random_state(guest_random_seed + vcpu_idx);
5858

5959
gva = vcpu_args->gva;
6060
pages = vcpu_args->pages;
@@ -241,12 +241,6 @@ void memstress_set_write_percent(struct kvm_vm *vm, uint32_t write_percent)
241241
sync_global_to_guest(vm, memstress_args.write_percent);
242242
}
243243

244-
void memstress_set_random_seed(struct kvm_vm *vm, uint32_t random_seed)
245-
{
246-
memstress_args.random_seed = random_seed;
247-
sync_global_to_guest(vm, memstress_args.random_seed);
248-
}
249-
250244
void memstress_set_random_access(struct kvm_vm *vm, bool random_access)
251245
{
252246
memstress_args.random_access = random_access;

0 commit comments

Comments
 (0)