aboutsummaryrefslogtreecommitdiff
path: root/tools/testing/selftests/kvm/include/x86_64/processor.h
diff options
context:
space:
mode:
authorReinette Chatre <reinette.chatre@intel.com>2024-06-12 11:16:11 -0700
committerSean Christopherson <seanjc@google.com>2024-06-28 11:40:38 -0700
commit6b878cbb87bf4fc4c07906ada431624911e3d85a (patch)
tree140c95a5508b952994acd1a0992ab14536a518ee /tools/testing/selftests/kvm/include/x86_64/processor.h
parentdd103407ca315b467074d74b3580abe210c4c695 (diff)
KVM: selftests: Add guest udelay() utility for x86
Add udelay() for x86 tests to allow busy waiting in the guest for a specific duration, and to match ARM and RISC-V's udelay() in the hopes of eventually making udelay() available on all architectures. Get the guest's TSC frequency using KVM_GET_TSC_KHZ and expose it to all VMs via a new global, guest_tsc_khz. Assert that KVM_GET_TSC_KHZ returns a valid frequency, instead of simply skipping tests, which would require detecting which tests actually need/want udelay(). KVM hasn't returned an error for KVM_GET_TSC_KHZ since commit cc578287e322 ("KVM: Infrastructure for software and hardware based TSC rate scaling"), which predates KVM selftests by 6+ years (KVM_GET_TSC_KHZ itself predates KVM selftest by 7+ years). Note, if the GUEST_ASSERT() in udelay() somehow fires and the test doesn't check for guest asserts, then the test will fail with a very cryptic message. But fixing that, e.g. by automatically handling guest asserts, is a much larger task, and practically speaking the odds of a test afoul of this wart are infinitesimally small. Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Link: https://lore.kernel.org/r/5aa86285d1c1d7fe1960e3fe490f4b22273977e6.1718214999.git.reinette.chatre@intel.com Co-developed-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Sean Christopherson <seanjc@google.com>
Diffstat (limited to 'tools/testing/selftests/kvm/include/x86_64/processor.h')
-rw-r--r--tools/testing/selftests/kvm/include/x86_64/processor.h18
1 files changed, 18 insertions, 0 deletions
diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
index 8eb57de0b587..8501735c6f41 100644
--- a/tools/testing/selftests/kvm/include/x86_64/processor.h
+++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
@@ -23,6 +23,7 @@
extern bool host_cpu_is_intel;
extern bool host_cpu_is_amd;
+extern uint64_t guest_tsc_khz;
/* Forced emulation prefix, used to invoke the emulator unconditionally. */
#define KVM_FEP "ud2; .byte 'k', 'v', 'm';"
@@ -815,6 +816,23 @@ static inline void cpu_relax(void)
asm volatile("rep; nop" ::: "memory");
}
+static inline void udelay(unsigned long usec)
+{
+ uint64_t start, now, cycles;
+
+ GUEST_ASSERT(guest_tsc_khz);
+ cycles = guest_tsc_khz / 1000 * usec;
+
+ /*
+ * Deliberately don't PAUSE, a.k.a. cpu_relax(), so that the delay is
+ * as accurate as possible, e.g. doesn't trigger PAUSE-Loop VM-Exits.
+ */
+ start = rdtsc();
+ do {
+ now = rdtsc();
+ } while (now - start < cycles);
+}
+
#define ud2() \
__asm__ __volatile__( \
"ud2\n" \