Provide a generic function cycles_read to read the system counter from the guest for timing purposes and a helper cycles_to_ns to convert to nanoseconds. cycles_to_ns may overflow if the cycles argument goes above 10 billion, but that is far outside the intended use of these functions and different timing instruments should be used. clocks_calc_mult_shift could be used to solve this problem, but importing clocksource code here was annoying. Substitute the previous custom implementation of a similar function in system_counter_offset_test with this new implementation. Signed-off-by: Colton Lewis <coltonlewis@xxxxxxxxxx> --- .../selftests/kvm/include/aarch64/processor.h | 3 +++ .../selftests/kvm/include/x86_64/processor.h | 3 +++ tools/testing/selftests/kvm/lib/aarch64/processor.c | 12 ++++++++++++ tools/testing/selftests/kvm/lib/x86_64/processor.c | 13 +++++++++++++ .../selftests/kvm/system_counter_offset_test.c | 10 ++-------- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h index 5f977528e09c..f65e491763e0 100644 --- a/tools/testing/selftests/kvm/include/aarch64/processor.h +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h @@ -216,4 +216,7 @@ void smccc_hvc(uint32_t function_id, uint64_t arg0, uint64_t arg1, uint32_t guest_get_vcpuid(void); +uint64_t cycles_read(void); +uint64_t cycles_to_ns(struct kvm_vcpu *vcpu, uint64_t cycles); + #endif /* SELFTEST_KVM_PROCESSOR_H */ diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index 53ffa43c90db..5d977f95d5f5 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -1134,4 +1134,7 @@ void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, #define PFERR_GUEST_PAGE_MASK BIT_ULL(PFERR_GUEST_PAGE_BIT) #define PFERR_IMPLICIT_ACCESS BIT_ULL(PFERR_IMPLICIT_ACCESS_BIT) +uint64_t cycles_read(void); +uint64_t cycles_to_ns(struct kvm_vcpu *vcpu, uint64_t cycles); + #endif /* SELFTEST_KVM_PROCESSOR_H */ diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c index 5972a23b2765..5475a7e98d41 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/processor.c +++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c @@ -8,6 +8,7 @@ #include <linux/compiler.h> #include <assert.h> +#include "arch_timer.h" #include "guest_modes.h" #include "kvm_util.h" #include "processor.h" @@ -551,3 +552,14 @@ void vm_vaddr_populate_bitmap(struct kvm_vm *vm) sparsebit_set_num(vm->vpages_valid, 0, (1ULL << vm->va_bits) >> vm->page_shift); } + +uint64_t cycles_read(void) +{ + return timer_get_cntct(VIRTUAL); +} + +uint64_t cycles_to_ns(struct kvm_vcpu *vcpu, uint64_t cycles) +{ + TEST_ASSERT(cycles < 10000000000, "Conversion to ns may overflow"); + return cycles * NSEC_PER_SEC / timer_get_cntfrq(); +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index ae1e573d94ce..adef76bebff3 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -1270,3 +1270,16 @@ void kvm_selftest_arch_init(void) host_cpu_is_intel = this_cpu_is_intel(); host_cpu_is_amd = this_cpu_is_amd(); } + +uint64_t cycles_read(void) +{ + return rdtsc(); +} + +uint64_t cycles_to_ns(struct kvm_vcpu *vcpu, uint64_t cycles) +{ + uint64_t tsc_khz = __vcpu_ioctl(vcpu, KVM_GET_TSC_KHZ, NULL); + + TEST_ASSERT(cycles < 10000000000, "Conversion to ns may overflow"); + return cycles * NSEC_PER_SEC / (tsc_khz * 1000); +} diff --git a/tools/testing/selftests/kvm/system_counter_offset_test.c b/tools/testing/selftests/kvm/system_counter_offset_test.c index 7f5b330b6a1b..44101d0fcb48 100644 --- a/tools/testing/selftests/kvm/system_counter_offset_test.c +++ b/tools/testing/selftests/kvm/system_counter_offset_test.c @@ -39,14 +39,9 @@ static void setup_system_counter(struct kvm_vcpu *vcpu, struct test_case *test) &test->tsc_offset); } -static uint64_t guest_read_system_counter(struct test_case *test) -{ - return rdtsc(); -} - static uint64_t host_read_guest_system_counter(struct test_case *test) { - return rdtsc() + test->tsc_offset; + return cycles_read() + test->tsc_offset; } #else /* __x86_64__ */ @@ -63,9 +58,8 @@ 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)); + GUEST_SYNC_CLOCK(i, cycles_read()); } } -- 2.40.0.348.gf938b09366-goog