~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/kvm/system_counter_offset_test.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright (C) 2021, Google LLC.
  4  *
  5  * Tests for adjusting the system counter from userspace
  6  */
  7 #include <asm/kvm_para.h>
  8 #include <stdint.h>
  9 #include <string.h>
 10 #include <sys/stat.h>
 11 #include <time.h>
 12 
 13 #include "test_util.h"
 14 #include "kvm_util.h"
 15 #include "processor.h"
 16 
 17 #ifdef __x86_64__
 18 
 19 struct test_case {
 20         uint64_t tsc_offset;
 21 };
 22 
 23 static struct test_case test_cases[] = {
 24         { 0 },
 25         { 180 * NSEC_PER_SEC },
 26         { -180 * NSEC_PER_SEC },
 27 };
 28 
 29 static void check_preconditions(struct kvm_vcpu *vcpu)
 30 {
 31         __TEST_REQUIRE(!__vcpu_has_device_attr(vcpu, KVM_VCPU_TSC_CTRL,
 32                                                KVM_VCPU_TSC_OFFSET),
 33                        "KVM_VCPU_TSC_OFFSET not supported; skipping test");
 34 }
 35 
 36 static void setup_system_counter(struct kvm_vcpu *vcpu, struct test_case *test)
 37 {
 38         vcpu_device_attr_set(vcpu, KVM_VCPU_TSC_CTRL, KVM_VCPU_TSC_OFFSET,
 39                              &test->tsc_offset);
 40 }
 41 
 42 static uint64_t guest_read_system_counter(struct test_case *test)
 43 {
 44         return rdtsc();
 45 }
 46 
 47 static uint64_t host_read_guest_system_counter(struct test_case *test)
 48 {
 49         return rdtsc() + test->tsc_offset;
 50 }
 51 
 52 #else /* __x86_64__ */
 53 
 54 #error test not implemented for this architecture!
 55 
 56 #endif
 57 
 58 #define GUEST_SYNC_CLOCK(__stage, __val)                        \
 59                 GUEST_SYNC_ARGS(__stage, __val, 0, 0, 0)
 60 
 61 static void guest_main(void)
 62 {
 63         int i;
 64 
 65         for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
 66                 struct test_case *test = &test_cases[i];
 67 
 68                 GUEST_SYNC_CLOCK(i, guest_read_system_counter(test));
 69         }
 70 }
 71 
 72 static void handle_sync(struct ucall *uc, uint64_t start, uint64_t end)
 73 {
 74         uint64_t obs = uc->args[2];
 75 
 76         TEST_ASSERT(start <= obs && obs <= end,
 77                     "unexpected system counter value: %"PRIu64" expected range: [%"PRIu64", %"PRIu64"]",
 78                     obs, start, end);
 79 
 80         pr_info("system counter value: %"PRIu64" expected range [%"PRIu64", %"PRIu64"]\n",
 81                 obs, start, end);
 82 }
 83 
 84 static void handle_abort(struct ucall *uc)
 85 {
 86         REPORT_GUEST_ASSERT(*uc);
 87 }
 88 
 89 static void enter_guest(struct kvm_vcpu *vcpu)
 90 {
 91         uint64_t start, end;
 92         struct ucall uc;
 93         int i;
 94 
 95         for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
 96                 struct test_case *test = &test_cases[i];
 97 
 98                 setup_system_counter(vcpu, test);
 99                 start = host_read_guest_system_counter(test);
100                 vcpu_run(vcpu);
101                 end = host_read_guest_system_counter(test);
102 
103                 switch (get_ucall(vcpu, &uc)) {
104                 case UCALL_SYNC:
105                         handle_sync(&uc, start, end);
106                         break;
107                 case UCALL_ABORT:
108                         handle_abort(&uc);
109                         return;
110                 default:
111                         TEST_ASSERT(0, "unhandled ucall %ld",
112                                     get_ucall(vcpu, &uc));
113                 }
114         }
115 }
116 
117 int main(void)
118 {
119         struct kvm_vcpu *vcpu;
120         struct kvm_vm *vm;
121 
122         vm = vm_create_with_one_vcpu(&vcpu, guest_main);
123         check_preconditions(vcpu);
124 
125         enter_guest(vcpu);
126         kvm_vm_free(vm);
127 }
128 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php