From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lucas Meneghel Rodrigues Subject: Re: [Autotest PATCH] KVM-test: TSC drift test Date: Fri, 29 Apr 2011 02:42:20 -0300 Message-ID: References: <20110421073302.12433.13463.stgit@t> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Cc: autotest@test.kernel.org, glommer@redhat.com, zamsden@redhat.com, kvm@vger.kernel.org To: Amos Kong Return-path: In-Reply-To: <20110421073302.12433.13463.stgit@t> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: autotest-bounces@test.kernel.org Errors-To: autotest-bounces@test.kernel.org List-Id: kvm.vger.kernel.org On Thu, Apr 21, 2011 at 4:33 AM, Amos Kong wrote: > This case is used to test the drift between host and guest. > Use taskset to make tsc program execute in a single cpu. > If the drift ratio bigger than 10%, then fail this case. The calculations of the tsc frequency looks wrong... See comments below. Also, when Glauber or Zach could take a look into this test it'd be great! > Signed-off-by: Amos Kong > --- > =A0client/tests/kvm/deps/get_tsc.c =A0 =A0 =A0 =A0| =A0 27 ++++++++++ > =A0client/tests/kvm/tests/tsc_drift.py =A0 =A0| =A0 88 ++++++++++++++++++= ++++++++++++++ > =A0client/tests/kvm/tests_base.cfg.sample | =A0 =A05 ++ > =A03 files changed, 120 insertions(+), 0 deletions(-) > =A0create mode 100644 client/tests/kvm/deps/get_tsc.c > =A0create mode 100644 client/tests/kvm/tests/tsc_drift.py > > diff --git a/client/tests/kvm/deps/get_tsc.c b/client/tests/kvm/deps/get_= tsc.c > new file mode 100644 > index 0000000..e91a41f > --- /dev/null > +++ b/client/tests/kvm/deps/get_tsc.c > @@ -0,0 +1,27 @@ > +/* > + * Programme to get cpu's TSC(time stamp counter) > + * Copyright(C) 2009 Redhat, Inc. > + * Amos Kong > + * Dec 9, 2009 > + * > + */ > + > +#define _GNU_SOURCE > +#include > +#include > + > +typedef unsigned long long u64; > + > +u64 rdtsc(void) > +{ > + =A0 =A0 =A0 unsigned tsc_lo, tsc_hi; > + > + =A0 =A0 =A0 asm volatile("rdtsc" : "=3Da"(tsc_lo), "=3Dd"(tsc_hi)); > + =A0 =A0 =A0 return tsc_lo | (u64)tsc_hi << 32; > +} > + > +int main(void) > +{ > + =A0 =A0 =A0 printf("%lld\n", rdtsc()); > + =A0 =A0 =A0 return 0; > +} > diff --git a/client/tests/kvm/tests/tsc_drift.py b/client/tests/kvm/tests= /tsc_drift.py > new file mode 100644 > index 0000000..de2fb76 > --- /dev/null > +++ b/client/tests/kvm/tests/tsc_drift.py > @@ -0,0 +1,88 @@ > +import time, os, logging, commands, re > +from autotest_lib.client.common_lib import error > +from autotest_lib.client.bin import local_host > +import kvm_test_utils > + > + > +def run_tsc_drift(test, params, env): > + =A0 =A0""" > + =A0 =A0Check the TSC(time stamp counter) frequency of guest and host wh= ether match > + =A0 =A0or not > + > + =A0 =A01) Computer average tsc frequency of host's cpus by C the program > + =A0 =A02) Copy the C code to the guest, complie and run it to get tsc > + =A0 =A0 =A0 frequency of guest's vcpus > + =A0 =A03) Sleep sometimes and get the TSC of host and guest again > + =A0 =A04) Compute the TSC frequency of host and guest > + =A0 =A05) Compare the frequency deviation between host and guest with s= tandard > + > + =A0 =A0@param test: Kvm test object > + =A0 =A0@param params: Dictionary with the test parameters. > + =A0 =A0@param env: Dictionary with test environment. > + =A0 =A0""" > + =A0 =A0drift_threshold =3D float(params.get("drift_threshold")) > + =A0 =A0interval =3D float(params.get("interval")) > + =A0 =A0cpu_chk_cmd =3D params.get("cpu_chk_cmd") > + =A0 =A0tsc_freq_path =3D os.path.join(test.bindir, 'deps/get_tsc.c') > + =A0 =A0host_freq =3D 0 > + > + =A0 =A0def get_tsc(machine=3D"host", i=3D0): > + =A0 =A0 =A0 =A0cmd =3D "taskset -c %s /tmp/get_tsc" % i > + =A0 =A0 =A0 =A0if machine =3D=3D "host": > + =A0 =A0 =A0 =A0 =A0 =A0s, o =3D commands.getstatusoutput(cmd) > + =A0 =A0 =A0 =A0else: > + =A0 =A0 =A0 =A0 =A0 =A0s, o =3D session.cmd_status_output(cmd) > + =A0 =A0 =A0 =A0if s !=3D 0: > + =A0 =A0 =A0 =A0 =A0 =A0logging.debug(o) > + =A0 =A0 =A0 =A0 =A0 =A0raise error.TestError("Fail to get tsc of host, = ncpu: %d" % i) > + =A0 =A0 =A0 =A0return float(re.findall("(\d+)",o)[0]) > + > + =A0 =A0vm =3D env.get_vm(params["main_vm"]) > + =A0 =A0vm.verify_alive() > + =A0 =A0timeout =3D float(params.get("login_timeout", 240)) > + =A0 =A0session =3D vm.wait_for_login(timeout=3Dtimeout) > + > + =A0 =A0commands.getoutput("gcc %s -o /tmp/get_tsc" % tsc_freq_path) > + =A0 =A0ncpu =3D local_host.LocalHost().get_num_cpu() > + > + =A0 =A0logging.info("Interval is %s" % interval) > + =A0 =A0logging.info("Determine the TSC frequency in the host") > + =A0 =A0for i in range(ncpu): > + =A0 =A0 =A0 =A0tsc1 =3D get_tsc("host", i) > + =A0 =A0 =A0 =A0time.sleep(interval) > + =A0 =A0 =A0 =A0tsc2 =3D get_tsc("host", i) > + > + =A0 =A0 =A0 =A0delta =3D tsc2 - tsc1 > + =A0 =A0 =A0 =A0logging.info("Host TSC delta for cpu %s is %s" % (i, del= ta)) > + =A0 =A0 =A0 =A0if delta < 0: > + =A0 =A0 =A0 =A0 =A0 =A0raise error.TestError("Host TSC for cpu %s warps= %s" % (i, delta)) ^ Yeah, I don't think this is expected to warp, but yet, good to check. > + =A0 =A0 =A0 =A0host_freq +=3D delta / ncpu Now, i really didn't understand the concept behind the tsc frequency. So we have a difference between 2 timestamps taken over an arbitrary period of time (in this case, looks 30s by default) and divide by the number of cpus, however we will repeat this procedure by the same amount so: N * ( d_tsc1/N + d_tsc2/N + d_tsc3/N + ... + d_tscn/N) This could be simplified to (d_tsc1 + d_tsc2 + d_tsc3 +.... + d_tscn) Unless I'm missing something... so host_freq =3D sum(d_tsci) The calculation could be simplified then... And by definition, isn't frequency how many times a phenomena occurs (in this case, change of timestamp counter) per time? So, don't we have to divide this sum by the time the program slept? Also, it looks like the whole logic to get the frequencies can be factored to a single function and just call that function for guest and host. -- = Lucas