----- "Zachary Amsden" <zamsden@xxxxxxxxxx> wrote: > On 08/26/2010 07:49 PM, Jason Wang wrote: > > This patch implements two tests for kvmclock. First one check > whether > > the date of time returned by kvmclock matches the value got from > > host. Second one check whether the cycle of kvmclock grows > > monotonically in smp guest. > > > > Technically, it's not monotonic, it's non-decreasing. > > > Three parameters were accepted by the test: test loops, seconds > > since 1970-01-01 00:00:00 UTC which could be easily get through > date > > +%s and the max accepted offset value between the tod of guest and > > host. > > > > This in general looks awesome. > > > Signed-off-by: Jason Wang<jasowang@xxxxxxxxxx> > > --- > > config-x86-common.mak | 6 ++ > > x86/README | 2 + > > x86/kvmclock_test.c | 145 > +++++++++++++++++++++++++++++++++++++++++++++++++ > > x86/unittests.cfg | 5 ++ > > 4 files changed, 157 insertions(+), 1 deletions(-) > > create mode 100644 x86/kvmclock_test.c > > > > diff --git a/config-x86-common.mak b/config-x86-common.mak > > index b8ca859..b541c1c 100644 > > --- a/config-x86-common.mak > > +++ b/config-x86-common.mak > > @@ -26,7 +26,8 @@ FLATLIBS = lib/libcflat.a $(libgcc) > > tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ > > $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat > \ > > $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \ > > - $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat > > + $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \ > > + $(TEST_DIR)/kvmclock_test.flat > > > > tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg > > > > @@ -70,6 +71,9 @@ $(TEST_DIR)/rmap_chain.flat: $(cstart.o) > $(TEST_DIR)/rmap_chain.o \ > > > > $(TEST_DIR)/svm.flat: $(cstart.o) $(TEST_DIR)/vm.o > > > > +$(TEST_DIR)/kvmclock_test.flat: $(cstart.o) $(TEST_DIR)/kvmclock.o > \ > > + $(TEST_DIR)/kvmclock_test.o > > + > > arch_clean: > > $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \ > > $(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o > > diff --git a/x86/README b/x86/README > > index ab5a2ae..4b90080 100644 > > --- a/x86/README > > +++ b/x86/README > > @@ -12,3 +12,5 @@ sieve: heavy memory access with no paging and with > paging static and with paging > > smptest: run smp_id() on every cpu and compares return value to > number > > tsc: write to tsc(0) and write to tsc(100000000000) and read it > back > > vmexit: long loops for each: cpuid, vmcall, mov_from_cr8, > mov_to_cr8, inl_pmtimer, ipi, ipi+halt > > +kvmclock_test: monotonic cycle test of kvmclock and a sanity test > of > > +wallclock > > diff --git a/x86/kvmclock_test.c b/x86/kvmclock_test.c > > new file mode 100644 > > index 0000000..cd80915 > > --- /dev/null > > +++ b/x86/kvmclock_test.c > > @@ -0,0 +1,145 @@ > > +#include "libcflat.h" > > +#include "smp.h" > > +#include "atomic.h" > > +#include "string.h" > > +#include "kvmclock.h" > > + > > +#define DEFAULT_TEST_LOOPS 100000000L > > +#define DEFAULT_THRESHOLD 60L > > + > > +struct test_info { > > + struct spinlock lock; > > + long loops; /* test loops */ > > + u64 warps; /* warp count */ > > + long long worst; /* worst warp */ > > + volatile cycle_t last; /* last cycle seen by test */ > > + atomic_t ncpus; /* number of cpu in the test*/ > > +}; > > + > > +struct test_info ti[2]; > > + > > +static int wallclock_test(long sec, long threshold) > > +{ > > + int i; > > + long ksec, offset; > > + struct timespec ts, ts_last; > > + > > + printf("Wallclock test, threshold %ld\n", threshold); > > + kvm_get_wallclock(&ts_last); > > + ksec = ts_last.sec + ts_last.nsec / NSEC_PER_SEC; > > + > > + offset = ksec - sec; > > + printf("Seconds get from host: %ld\n", sec); > > + printf("Seconds get from kvmclock: %ld\n", ksec); > > + > > + if (offset> threshold || offset< -threshold) { > > + printf("Seconds get from kvmclock: %ld\n", ksec); > > + return 1; > > + } > > + > > + for (i=0; i< 100; i++){ > > + kvm_get_wallclock(&ts); > > + if (ts.nsec != ts_last.nsec || ts.sec != > ts_last.sec){ > > + printf ("Inconsistent wall clock > returned!\n"); > > + return 1; > > + } > > + } > > + return 0; > > +} > > + > > +static void kvm_clock_test(void *data) > > +{ > > + struct test_info *hv_test_info = (struct test_info *)data; > > + int i; > > + > > + for (i = 0; i< hv_test_info->loops; i++){ > > + cycle_t t0, t1; > > + long long delta; > > + > > + spin_lock(&hv_test_info->lock); > > + t1 = kvm_clock_read(); > > + t0 = hv_test_info->last; > > + hv_test_info->last = kvm_clock_read(); > > + spin_unlock(&hv_test_info->lock); > > + > > + delta = t1 - t0; > > + if (delta< 0){ > > + spin_lock(&hv_test_info->lock); > > + ++hv_test_info->warps; > > + if (delta< hv_test_info->worst){ > > + hv_test_info->worst = delta; > > + printf("Worst warp %lld %\n", > hv_test_info->worst); > > + } > > + spin_unlock(&hv_test_info->lock); > > + } > > + > > + if (!((unsigned long)i& 31)) > > + asm volatile("rep; nop"); > > + } > > + > > + atomic_dec(&hv_test_info->ncpus); > > +} > > + > > +static int cycle_test(int ncpus, long loops, struct test_info *ti) > > +{ > > + int i; > > + > > + atomic_set(&ti->ncpus, ncpus); > > + ti->loops = loops; > > + for (i = ncpus - 1; i>= 0; i--) > > + on_cpu_async(i, kvm_clock_test, (void *)ti); > > + > > + /* Wait for the end of other vcpu */ > > + while(atomic_read(&ti->ncpus)) > > + ; > > + > > + printf("Total vcpus: %d\n", ncpus); > > + printf("Test loops: %ld\n", ti->loops); > > + printf("Total warps: %lld\n", ti->warps); > > + printf("Worst warp: %lld\n", ti->worst); > > + > > + return ti->warps ? 1 : 0; > > +} > > + > > +int main(int ac, char **av) > > +{ > > + int ncpus = cpu_count(); > > + int nerr = 0, i; > > + long loops = DEFAULT_TEST_LOOPS; > > + long sec = 0; > > + long threshold = DEFAULT_THRESHOLD; > > + > > + if (ac> 1) > > + loops = atol(av[1]); > > + if (ac> 2) > > + sec = atol(av[2]); > > + if (ac> 3) > > + threshold = atol(av[3]); > > + > > + smp_init(); > > + > > + if (ncpus> MAX_CPU) > > + ncpus = MAX_CPU; > > + for (i = 0; i< ncpus; ++i) > > + on_cpu(i, kvm_clock_init, (void *)0); > > + > > + if (ac> 2) > > + nerr += wallclock_test(sec, threshold); > > + > > + printf("Check the stability of raw cycle\n"); > > + pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT > > + | PVCLOCK_RAW_CYCLE_BIT); > > > > What is this RAW_CYCLE_BIT ? Did I miss something? RAW_CYCLE_BIT is used to tell the driver return unadjusted cycle value as could be used to test whether the host could supply a stable cycle. > > > -- > 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 -- 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