brintos

brintos / linux-shallow public Read only

0
0
Text · 2.4 KiB · 59c7304 Raw
111 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright © 2021 Amazon.com, Inc. or its affiliates.4 */5 6#include "test_util.h"7#include "kvm_util.h"8#include "processor.h"9 10#include <stdint.h>11#include <time.h>12#include <sched.h>13#include <signal.h>14#include <pthread.h>15 16#define NR_TEST_VCPUS 2017 18static struct kvm_vm *vm;19pthread_spinlock_t create_lock;20 21#define TEST_TSC_KHZ    2345678UL22#define TEST_TSC_OFFSET 20000000023 24uint64_t tsc_sync;25static void guest_code(void)26{27	uint64_t start_tsc, local_tsc, tmp;28 29	start_tsc = rdtsc();30	do {31		tmp = READ_ONCE(tsc_sync);32		local_tsc = rdtsc();33		WRITE_ONCE(tsc_sync, local_tsc);34		if (unlikely(local_tsc < tmp))35			GUEST_SYNC_ARGS(0, local_tsc, tmp, 0, 0);36 37	} while (local_tsc - start_tsc < 5000 * TEST_TSC_KHZ);38 39	GUEST_DONE();40}41 42 43static void *run_vcpu(void *_cpu_nr)44{45	unsigned long vcpu_id = (unsigned long)_cpu_nr;46	unsigned long failures = 0;47	static bool first_cpu_done;48	struct kvm_vcpu *vcpu;49 50	/* The kernel is fine, but vm_vcpu_add() needs locking */51	pthread_spin_lock(&create_lock);52 53	vcpu = vm_vcpu_add(vm, vcpu_id, guest_code);54 55	if (!first_cpu_done) {56		first_cpu_done = true;57		vcpu_set_msr(vcpu, MSR_IA32_TSC, TEST_TSC_OFFSET);58	}59 60	pthread_spin_unlock(&create_lock);61 62	for (;;) {63                struct ucall uc;64 65		vcpu_run(vcpu);66		TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);67 68		switch (get_ucall(vcpu, &uc)) {69                case UCALL_DONE:70			goto out;71 72                case UCALL_SYNC:73			printf("Guest %d sync %lx %lx %ld\n", vcpu->id,74			       uc.args[2], uc.args[3], uc.args[2] - uc.args[3]);75			failures++;76			break;77 78                default:79                        TEST_FAIL("Unknown ucall %lu", uc.cmd);80		}81	}82 out:83	return (void *)failures;84}85 86int main(int argc, char *argv[])87{88	TEST_REQUIRE(kvm_has_cap(KVM_CAP_VM_TSC_CONTROL));89 90	vm = vm_create(NR_TEST_VCPUS);91	vm_ioctl(vm, KVM_SET_TSC_KHZ, (void *) TEST_TSC_KHZ);92 93	pthread_spin_init(&create_lock, PTHREAD_PROCESS_PRIVATE);94	pthread_t cpu_threads[NR_TEST_VCPUS];95	unsigned long cpu;96	for (cpu = 0; cpu < NR_TEST_VCPUS; cpu++)97		pthread_create(&cpu_threads[cpu], NULL, run_vcpu, (void *)cpu);98 99	unsigned long failures = 0;100	for (cpu = 0; cpu < NR_TEST_VCPUS; cpu++) {101		void *this_cpu_failures;102		pthread_join(cpu_threads[cpu], &this_cpu_failures);103		failures += (unsigned long)this_cpu_failures;104	}105 106	TEST_ASSERT(!failures, "TSC sync failed");107	pthread_spin_destroy(&create_lock);108	kvm_vm_free(vm);109	return 0;110}111