Add testcases for clock monotonicity across vCPUs. In a sense this is a reduced adaptation of Ingo Molnar's time-wrap-test. These testcases are extremely unlikely to pass on SMP VMs, so they are reported as XFAILs. Their purpose is to demonstrate that it's impossible to achieve clock monotonicity across vCPUs (unless you can completely exclude preemption of vCPUs by the hypervisor, of course). Note that even in the (faked) case of PVCLOCK_TSC_STABLE_BIT unset, when pvclock_clocksource_read() tries to monotonize the clock using basically the same technique as the testcase uses, it still fails the global monotonicity test. Signed-off-by: Roman Kagan <rkagan@xxxxxxxxxxxxx> --- the patch applies on top of my earlier patch "x86/kvmclock_test: rework to avoid spinlocks" x86/kvmclock_test.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/x86/kvmclock_test.c b/x86/kvmclock_test.c index fc3cb2e..0af30c8 100644 --- a/x86/kvmclock_test.c +++ b/x86/kvmclock_test.c @@ -15,6 +15,8 @@ struct warp_test_info { long long worst; }; struct warp_test_info wti[MAX_CPU]; +struct warp_test_info xwti[MAX_CPU]; +atomic64_t last_value = ATOMIC64_INIT(0); struct perf_test_info { unsigned long long cycles; @@ -80,6 +82,38 @@ static void warp_test_cpu(void *data) atomic_dec(&cpus_left); } +static void xwarp_test_cpu(void *data) +{ + struct warp_test_info *ti = data; + unsigned long long t = kvm_clock_read(); + unsigned long long end = t + DURATION * NSEC_PER_SEC; + ti->warps = 0; + ti->stalls = 0; + ti->worst = 0; + + do { + long long delta; + u64 last; + + t = kvm_clock_read(); + last = atomic64_read(&last_value); + delta = t - last; + + while (t > last) + last = atomic64_cmpxchg(&last_value, last, t); + + if (delta < 0) { + ti->warps++; + if (delta < ti->worst) + ti->worst = delta; + } + if (delta == 0) + ti->stalls++; + } while (t < end); + + atomic_dec(&cpus_left); +} + static void perf_test_cpu(void *data) { struct perf_test_info *ti = data; @@ -121,6 +155,32 @@ static void warp_test(int ncpus, bool stable) warps == 0, stable ? "" : "out", warps, worst, stalls); } +static void xwarp_test(int ncpus, bool stable) +{ + int i; + unsigned long long warps = 0, stalls = 0; + long long worst = 0; + + pvclock_set_flags(stable ? PVCLOCK_RAW_CYCLE_BIT : 0); + + atomic_set(&cpus_left, ncpus); + for (i = ncpus - 1; i >= 0; i--) + on_cpu_async(i, xwarp_test_cpu, &xwti[i]); + while (atomic_read(&cpus_left)); + + for (i = 0; i < ncpus; i++) { + warps += xwti[i].warps; + stalls += xwti[i].stalls; + if (xwti[i].worst < worst) + worst = xwti[i].worst; + } + + report_xfail("with%s TSC_STABLE: x-cpu warps:" + " %llu (worst %lld), stalls: %llu", + ncpus > 1, warps == 0, stable ? "" : "out", + warps, worst, stalls); +} + static void perf_test(int ncpus, bool stable) { int i; @@ -169,6 +229,8 @@ int main(int ac, char **av) warp_test(ncpus, true); warp_test(ncpus, false); + xwarp_test(ncpus, true); + xwarp_test(ncpus, false); perf_test(ncpus, true); perf_test(ncpus, false); -- 2.5.5 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html