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. Signed-off-by: Amos Kong <akong@xxxxxxxxxx> --- client/tests/kvm/deps/get_tsc.c | 27 ++++++++++ client/tests/kvm/tests/tsc_drift.py | 88 ++++++++++++++++++++++++++++++++ client/tests/kvm/tests_base.cfg.sample | 5 ++ 3 files changed, 120 insertions(+), 0 deletions(-) create mode 100644 client/tests/kvm/deps/get_tsc.c create 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 <akong@xxxxxxxxxx> + * Dec 9, 2009 + * + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdint.h> + +typedef unsigned long long u64; + +u64 rdtsc(void) +{ + unsigned tsc_lo, tsc_hi; + + asm volatile("rdtsc" : "=a"(tsc_lo), "=d"(tsc_hi)); + return tsc_lo | (u64)tsc_hi << 32; +} + +int main(void) +{ + printf("%lld\n", rdtsc()); + 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): + """ + Check the TSC(time stamp counter) frequency of guest and host whether match + or not + + 1) Computer average tsc frequency of host's cpus by C the program + 2) Copy the C code to the guest, complie and run it to get tsc + frequency of guest's vcpus + 3) Sleep sometimes and get the TSC of host and guest again + 4) Compute the TSC frequency of host and guest + 5) Compare the frequency deviation between host and guest with standard + + @param test: Kvm test object + @param params: Dictionary with the test parameters. + @param env: Dictionary with test environment. + """ + drift_threshold = float(params.get("drift_threshold")) + interval = float(params.get("interval")) + cpu_chk_cmd = params.get("cpu_chk_cmd") + tsc_freq_path = os.path.join(test.bindir, 'deps/get_tsc.c') + host_freq = 0 + + def get_tsc(machine="host", i=0): + cmd = "taskset -c %s /tmp/get_tsc" % i + if machine == "host": + s, o = commands.getstatusoutput(cmd) + else: + s, o = session.cmd_status_output(cmd) + if s != 0: + logging.debug(o) + raise error.TestError("Fail to get tsc of host, ncpu: %d" % i) + return float(re.findall("(\d+)",o)[0]) + + vm = env.get_vm(params["main_vm"]) + vm.verify_alive() + timeout = float(params.get("login_timeout", 240)) + session = vm.wait_for_login(timeout=timeout) + + commands.getoutput("gcc %s -o /tmp/get_tsc" % tsc_freq_path) + ncpu = local_host.LocalHost().get_num_cpu() + + logging.info("Interval is %s" % interval) + logging.info("Determine the TSC frequency in the host") + for i in range(ncpu): + tsc1 = get_tsc("host", i) + time.sleep(interval) + tsc2 = get_tsc("host", i) + + delta = tsc2 - tsc1 + logging.info("Host TSC delta for cpu %s is %s" % (i, delta)) + if delta < 0: + raise error.TestError("Host TSC for cpu %s warps %s" % (i, delta)) + + host_freq += delta / ncpu + logging.info("Average frequency of host's cpus: %s" % host_freq) + + vm.copy_files_to(tsc_freq_path,'/tmp/get_tsc.c') + session.cmd("gcc /tmp/get_tsc.c -o /tmp/get_tsc") + + s, guest_ncpu = session.cmd_status_output(cpu_chk_cmd) + + success = True + for i in range(int(guest_ncpu)): + tsc1 = get_tsc("guest", i) + time.sleep(interval) + tsc2 = get_tsc("guest", i) + + delta = tsc2 - tsc1 + logging.info("Guest TSC delta for vcpu %s is %s" % (i, delta)) + if delta < 0: + logging.error("Guest TSC for vcpu %s warps %s" % (i, delta)) + + ratio = 100 * (delta - host_freq) / host_freq + logging.info("TSC drift ratio for vcpu %s is %s" % (i, ratio)) + if abs(ratio) > drift_threshold: + logging.error("TSC drift found for vcpu %s ratio %s" % (i, ratio)) + success = False + + if not success: + raise error.TestFail("TSC drift found for the guest, please check the " + "log for details") + session.close() diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample index ceafebe..8e70746 100644 --- a/client/tests/kvm/tests_base.cfg.sample +++ b/client/tests/kvm/tests_base.cfg.sample @@ -331,6 +331,11 @@ variants: drift_threshold = 10 drift_threshold_single = 3 + - tsc_drift: + type = tsc_drift + drift_threshold = 10 + interval = 30 + - balloon_check: install setup unattended_install.cdrom type = balloon_check extra_params += " -balloon virtio" -- 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