@@ -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 */
@@ -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 */
@@ -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();
+}
@@ -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);
+}
@@ -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());
}
}
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@google.com> --- .../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(-) -- 2.40.0.348.gf938b09366-goog