mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 14:51:51 -04:00
Use u64 instead of uint64_t to make the KVM selftests code more concise and more similar to the kernel (since selftests are primarily developed by kernel developers). This commit was generated with the following command: git ls-files tools/testing/selftests/kvm | xargs sed -i 's/uint64_t/u64/g' Then by manually adjusting whitespace to make checkpatch.pl happy. Include <linux/types.h> in include/kvm_util_types.h, iinclude/test_util.h, and include/x86/pmu.h to pick up the tools-defined u64. Arguably, all headers (especially kvm_util_types.h) should have already been including stdint.h to get uint64_t from the libc headers, but the missing dependency only rears its head once KVM uses u64 instead of uint64_t. No functional change intended. Signed-off-by: David Matlack <dmatlack@google.com> [sean: rename pread_uint64() => pread_u64, expand on types.h include] Link: https://patch.msgid.link/20260420212004.3938325-5-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
128 lines
2.6 KiB
C
128 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (C) 2021, Google LLC.
|
|
*
|
|
* Tests for adjusting the system counter from userspace
|
|
*/
|
|
#include <asm/kvm_para.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
|
|
#include "test_util.h"
|
|
#include "kvm_util.h"
|
|
#include "processor.h"
|
|
|
|
#ifdef __x86_64__
|
|
|
|
struct test_case {
|
|
u64 tsc_offset;
|
|
};
|
|
|
|
static struct test_case test_cases[] = {
|
|
{ 0 },
|
|
{ 180 * NSEC_PER_SEC },
|
|
{ -180 * NSEC_PER_SEC },
|
|
};
|
|
|
|
static void check_preconditions(struct kvm_vcpu *vcpu)
|
|
{
|
|
__TEST_REQUIRE(!__vcpu_has_device_attr(vcpu, KVM_VCPU_TSC_CTRL,
|
|
KVM_VCPU_TSC_OFFSET),
|
|
"KVM_VCPU_TSC_OFFSET not supported; skipping test");
|
|
}
|
|
|
|
static void setup_system_counter(struct kvm_vcpu *vcpu, struct test_case *test)
|
|
{
|
|
vcpu_device_attr_set(vcpu, KVM_VCPU_TSC_CTRL, KVM_VCPU_TSC_OFFSET,
|
|
&test->tsc_offset);
|
|
}
|
|
|
|
static u64 guest_read_system_counter(struct test_case *test)
|
|
{
|
|
return rdtsc();
|
|
}
|
|
|
|
static u64 host_read_guest_system_counter(struct test_case *test)
|
|
{
|
|
return rdtsc() + test->tsc_offset;
|
|
}
|
|
|
|
#else /* __x86_64__ */
|
|
|
|
#error test not implemented for this architecture!
|
|
|
|
#endif
|
|
|
|
#define GUEST_SYNC_CLOCK(__stage, __val) \
|
|
GUEST_SYNC_ARGS(__stage, __val, 0, 0, 0)
|
|
|
|
static void guest_main(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
|
|
struct test_case *test = &test_cases[i];
|
|
|
|
GUEST_SYNC_CLOCK(i, guest_read_system_counter(test));
|
|
}
|
|
}
|
|
|
|
static void handle_sync(struct ucall *uc, u64 start, u64 end)
|
|
{
|
|
u64 obs = uc->args[2];
|
|
|
|
TEST_ASSERT(start <= obs && obs <= end,
|
|
"unexpected system counter value: %"PRIu64" expected range: [%"PRIu64", %"PRIu64"]",
|
|
obs, start, end);
|
|
|
|
pr_info("system counter value: %"PRIu64" expected range [%"PRIu64", %"PRIu64"]\n",
|
|
obs, start, end);
|
|
}
|
|
|
|
static void handle_abort(struct ucall *uc)
|
|
{
|
|
REPORT_GUEST_ASSERT(*uc);
|
|
}
|
|
|
|
static void enter_guest(struct kvm_vcpu *vcpu)
|
|
{
|
|
u64 start, end;
|
|
struct ucall uc;
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
|
|
struct test_case *test = &test_cases[i];
|
|
|
|
setup_system_counter(vcpu, test);
|
|
start = host_read_guest_system_counter(test);
|
|
vcpu_run(vcpu);
|
|
end = host_read_guest_system_counter(test);
|
|
|
|
switch (get_ucall(vcpu, &uc)) {
|
|
case UCALL_SYNC:
|
|
handle_sync(&uc, start, end);
|
|
break;
|
|
case UCALL_ABORT:
|
|
handle_abort(&uc);
|
|
return;
|
|
default:
|
|
TEST_ASSERT(0, "unhandled ucall %ld",
|
|
get_ucall(vcpu, &uc));
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
struct kvm_vcpu *vcpu;
|
|
struct kvm_vm *vm;
|
|
|
|
vm = vm_create_with_one_vcpu(&vcpu, guest_main);
|
|
check_preconditions(vcpu);
|
|
|
|
enter_guest(vcpu);
|
|
kvm_vm_free(vm);
|
|
}
|