Path: blob/master/tools/testing/selftests/kvm/system_counter_offset_test.c
38189 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright (C) 2021, Google LLC.3*4* Tests for adjusting the system counter from userspace5*/6#include <asm/kvm_para.h>7#include <stdint.h>8#include <string.h>9#include <sys/stat.h>10#include <time.h>1112#include "test_util.h"13#include "kvm_util.h"14#include "processor.h"1516#ifdef __x86_64__1718struct test_case {19uint64_t tsc_offset;20};2122static struct test_case test_cases[] = {23{ 0 },24{ 180 * NSEC_PER_SEC },25{ -180 * NSEC_PER_SEC },26};2728static void check_preconditions(struct kvm_vcpu *vcpu)29{30__TEST_REQUIRE(!__vcpu_has_device_attr(vcpu, KVM_VCPU_TSC_CTRL,31KVM_VCPU_TSC_OFFSET),32"KVM_VCPU_TSC_OFFSET not supported; skipping test");33}3435static void setup_system_counter(struct kvm_vcpu *vcpu, struct test_case *test)36{37vcpu_device_attr_set(vcpu, KVM_VCPU_TSC_CTRL, KVM_VCPU_TSC_OFFSET,38&test->tsc_offset);39}4041static uint64_t guest_read_system_counter(struct test_case *test)42{43return rdtsc();44}4546static uint64_t host_read_guest_system_counter(struct test_case *test)47{48return rdtsc() + test->tsc_offset;49}5051#else /* __x86_64__ */5253#error test not implemented for this architecture!5455#endif5657#define GUEST_SYNC_CLOCK(__stage, __val) \58GUEST_SYNC_ARGS(__stage, __val, 0, 0, 0)5960static void guest_main(void)61{62int i;6364for (i = 0; i < ARRAY_SIZE(test_cases); i++) {65struct test_case *test = &test_cases[i];6667GUEST_SYNC_CLOCK(i, guest_read_system_counter(test));68}69}7071static void handle_sync(struct ucall *uc, uint64_t start, uint64_t end)72{73uint64_t obs = uc->args[2];7475TEST_ASSERT(start <= obs && obs <= end,76"unexpected system counter value: %"PRIu64" expected range: [%"PRIu64", %"PRIu64"]",77obs, start, end);7879pr_info("system counter value: %"PRIu64" expected range [%"PRIu64", %"PRIu64"]\n",80obs, start, end);81}8283static void handle_abort(struct ucall *uc)84{85REPORT_GUEST_ASSERT(*uc);86}8788static void enter_guest(struct kvm_vcpu *vcpu)89{90uint64_t start, end;91struct ucall uc;92int i;9394for (i = 0; i < ARRAY_SIZE(test_cases); i++) {95struct test_case *test = &test_cases[i];9697setup_system_counter(vcpu, test);98start = host_read_guest_system_counter(test);99vcpu_run(vcpu);100end = host_read_guest_system_counter(test);101102switch (get_ucall(vcpu, &uc)) {103case UCALL_SYNC:104handle_sync(&uc, start, end);105break;106case UCALL_ABORT:107handle_abort(&uc);108return;109default:110TEST_ASSERT(0, "unhandled ucall %ld",111get_ucall(vcpu, &uc));112}113}114}115116int main(void)117{118struct kvm_vcpu *vcpu;119struct kvm_vm *vm;120121vm = vm_create_with_one_vcpu(&vcpu, guest_main);122check_preconditions(vcpu);123124enter_guest(vcpu);125kvm_vm_free(vm);126}127128129