Commit 55626ca9 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Paolo Bonzini

selftests: kvm: Check that TSC page value is small after KVM_SET_CLOCK(0)

Add a test for the issue when KVM_SET_CLOCK(0) call could cause
TSC page value to go very big because of a signedness issue around
hv_clock->system_time.
Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20210326155551.17446-3-vkuznets@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 77fcbe82
...@@ -80,19 +80,24 @@ static inline void check_tsc_msr_rdtsc(void) ...@@ -80,19 +80,24 @@ static inline void check_tsc_msr_rdtsc(void)
GUEST_ASSERT(delta_ns * 100 < (t2 - t1) * 100); GUEST_ASSERT(delta_ns * 100 < (t2 - t1) * 100);
} }
static inline u64 get_tscpage_ts(struct ms_hyperv_tsc_page *tsc_page)
{
return mul_u64_u64_shr64(rdtsc(), tsc_page->tsc_scale) + tsc_page->tsc_offset;
}
static inline void check_tsc_msr_tsc_page(struct ms_hyperv_tsc_page *tsc_page) static inline void check_tsc_msr_tsc_page(struct ms_hyperv_tsc_page *tsc_page)
{ {
u64 r1, r2, t1, t2; u64 r1, r2, t1, t2;
/* Compare TSC page clocksource with HV_X64_MSR_TIME_REF_COUNT */ /* Compare TSC page clocksource with HV_X64_MSR_TIME_REF_COUNT */
t1 = mul_u64_u64_shr64(rdtsc(), tsc_page->tsc_scale) + tsc_page->tsc_offset; t1 = get_tscpage_ts(tsc_page);
r1 = rdmsr(HV_X64_MSR_TIME_REF_COUNT); r1 = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
/* 10 ms tolerance */ /* 10 ms tolerance */
GUEST_ASSERT(r1 >= t1 && r1 - t1 < 100000); GUEST_ASSERT(r1 >= t1 && r1 - t1 < 100000);
nop_loop(); nop_loop();
t2 = mul_u64_u64_shr64(rdtsc(), tsc_page->tsc_scale) + tsc_page->tsc_offset; t2 = get_tscpage_ts(tsc_page);
r2 = rdmsr(HV_X64_MSR_TIME_REF_COUNT); r2 = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
GUEST_ASSERT(r2 >= t1 && r2 - t2 < 100000); GUEST_ASSERT(r2 >= t1 && r2 - t2 < 100000);
} }
...@@ -130,7 +135,11 @@ static void guest_main(struct ms_hyperv_tsc_page *tsc_page, vm_paddr_t tsc_page_ ...@@ -130,7 +135,11 @@ static void guest_main(struct ms_hyperv_tsc_page *tsc_page, vm_paddr_t tsc_page_
tsc_offset = tsc_page->tsc_offset; tsc_offset = tsc_page->tsc_offset;
/* Call KVM_SET_CLOCK from userspace, check that TSC page was updated */ /* Call KVM_SET_CLOCK from userspace, check that TSC page was updated */
GUEST_SYNC(7); GUEST_SYNC(7);
/* Sanity check TSC page timestamp, it should be close to 0 */
GUEST_ASSERT(get_tscpage_ts(tsc_page) < 100000);
GUEST_ASSERT(tsc_page->tsc_offset != tsc_offset); GUEST_ASSERT(tsc_page->tsc_offset != tsc_offset);
nop_loop(); nop_loop();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment