From patchwork Sun Jul 26 03:22:53 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wang X-Patchwork-Id: 114180 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o6Q3MxIp016402 for ; Mon, 26 Jul 2010 03:22:59 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753376Ab0GZDW5 (ORCPT ); Sun, 25 Jul 2010 23:22:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:26434 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753347Ab0GZDW4 (ORCPT ); Sun, 25 Jul 2010 23:22:56 -0400 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6Q3Mu0n018404 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 25 Jul 2010 23:22:56 -0400 Received: from [127.0.1.1] (dhcp-65-104.nay.redhat.com [10.66.65.104]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6Q3MsXt014705; Sun, 25 Jul 2010 23:22:55 -0400 Subject: [PATCH 3/3] test: Add test for kvmclock To: mtosatti@redhat.com, avi@redhat.com, kvm@vger.kernel.org From: Jason Wang Date: Sun, 26 Jul 2009 11:22:53 +0800 Message-ID: <20090726032253.8068.62886.stgit@FreeLancer> In-Reply-To: <20090726032237.8068.32553.stgit@FreeLancer> References: <20090726032237.8068.32553.stgit@FreeLancer> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.16 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 26 Jul 2010 03:23:00 +0000 (UTC) diff --git a/kvm/test/config-x86-common.mak b/kvm/test/config-x86-common.mak index a6ee18c..3dfd450 100644 --- a/kvm/test/config-x86-common.mak +++ b/kvm/test/config-x86-common.mak @@ -25,7 +25,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 @@ -67,6 +68,9 @@ $(TEST_DIR)/xsave.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/xsave.o $(TEST_DIR)/rmap_chain.flat: $(cstart.o) $(TEST_DIR)/rmap_chain.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/kvm/test/x86/kvmclock_test.c b/kvm/test/x86/kvmclock_test.c new file mode 100644 index 0000000..8530a89 --- /dev/null +++ b/kvm/test/x86/kvmclock_test.c @@ -0,0 +1,128 @@ +#include "libcflat.h" +#include "smp.h" +#include "kvmclock.h" + +#define TEST_LOOPS 100000000 + +static inline int atomic_read(int *v) +{ + return (*(volatile int *)&(v)); +} + +static inline void atomic_dec(int *v) +{ + asm volatile("lock decl %0": "+m" (*v)); +} + +struct test_info { + struct spinlock lock; + u64 loops; /* test loops */ + u64 warps; /* warp count */ + long long worst; /* worst warp */ + volatile cycle_t last; /* last cycle seen by test */ + int ncpus; /* number of cpu in the test*/ +}; + +struct test_info ti[2]; + +static int wallclock_test() +{ + int i; + struct timespec ts, ts_last; + + kvm_get_wallclock(&ts_last); + + 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 index = smp_id(); + 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, int loops, struct test_info *ti) +{ + int i; + + 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("Total loops: %lld\n", ti->loops * ncpus); + printf("Total warps: %lld\n", ti->warps); + printf("Worst warp: %lld\n", ti->worst); + + return ti->warps ? 1 : 0; +} + +int main() +{ + int ncpus = cpu_count(); + int nerr = 0, i; + + smp_init(); + + if (ncpus > MAX_CPU) + ncpus = MAX_CPU; + for (i = 0; i < ncpus; ++i) + on_cpu(i, kvm_clock_init, (void *)0); + + printf("Wallclock test:\n"); + nerr += wallclock_test(); + + pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); + printf("Monotonic cycle test:\n"); + nerr += cycle_test(ncpus, TEST_LOOPS, &ti[0]); + + pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT + | PVCLOCK_CYCLE_RAW_TEST_BIT); + printf("Raw cycle test:\n"); + nerr += cycle_test(ncpus, TEST_LOOPS, &ti[1]); + + for (i = 0; i < ncpus; ++i) + on_cpu(i, kvm_clock_clear, (void *)0); + + return nerr > 0 ? 1 : 0; +} diff --git a/kvm/test/x86/unittests.cfg b/kvm/test/x86/unittests.cfg index f39c5bd..0d077ac 100644 --- a/kvm/test/x86/unittests.cfg +++ b/kvm/test/x86/unittests.cfg @@ -53,3 +53,7 @@ file = xsave.flat [rmap_chain] file = rmap_chain.flat + +[kvmclock] +file = kvmclock_test.flat +smp = 2