The test checks the behavior of the MSR between L1 and L2. In particular, the value must be preserved across entry and exit, even in presence of a TSC offset in the VMCB. Based on a VMX test by Ken Hofsass. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- x86/svm.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/x86/svm.c b/x86/svm.c index 162632c..2350911 100644 --- a/x86/svm.c +++ b/x86/svm.c @@ -877,6 +877,46 @@ static bool npt_rw_l1mmio_check(struct test *test) && (test->vmcb->control.exit_info_1 == 0x100000007ULL); } +#define TSC_ADJUST_VALUE (1ll << 32) +#define TSC_OFFSET_VALUE (-1ll << 48) +static bool ok; + +static void tsc_adjust_prepare(struct test *test) +{ + default_prepare(test); + test->vmcb->control.tsc_offset = TSC_OFFSET_VALUE; + + wrmsr(MSR_IA32_TSC_ADJUST, -TSC_ADJUST_VALUE); + int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); + ok = adjust == -TSC_ADJUST_VALUE; +} + +static void tsc_adjust_test(struct test *test) +{ + int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); + ok &= adjust == -TSC_ADJUST_VALUE; + + uint64_t l1_tsc = rdtsc() - TSC_OFFSET_VALUE; + wrmsr(MSR_IA32_TSC, l1_tsc - TSC_ADJUST_VALUE); + + adjust = rdmsr(MSR_IA32_TSC_ADJUST); + ok &= adjust <= -2 * TSC_ADJUST_VALUE; + + uint64_t l1_tsc_end = rdtsc() - TSC_OFFSET_VALUE; + ok &= (l1_tsc_end + TSC_ADJUST_VALUE - l1_tsc) < TSC_ADJUST_VALUE; + + uint64_t l1_tsc_msr = rdmsr(MSR_IA32_TSC) - TSC_OFFSET_VALUE; + ok &= (l1_tsc_msr + TSC_ADJUST_VALUE - l1_tsc) < TSC_ADJUST_VALUE; +} + +static bool tsc_adjust_check(struct test *test) +{ + int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); + + wrmsr(MSR_IA32_TSC_ADJUST, 0); + return ok && adjust <= -2 * TSC_ADJUST_VALUE; +} + static void latency_prepare(struct test *test) { default_prepare(test); @@ -1048,6 +1088,8 @@ static struct test tests[] = { default_finished, npt_l1mmio_check }, { "npt_rw_l1mmio", npt_supported, npt_rw_l1mmio_prepare, npt_rw_l1mmio_test, default_finished, npt_rw_l1mmio_check }, + { "tsc_adjust", default_supported, tsc_adjust_prepare, tsc_adjust_test, + default_finished, tsc_adjust_check }, { "latency_run_exit", default_supported, latency_prepare, latency_test, latency_finished, latency_check }, { "latency_svm_insn", default_supported, lat_svm_insn_prepare, null_test, -- 2.14.3