Following is how I test this patchset. It should also apply to AMD machines by replacing Intel with AMD and VMX TSC scaling with SVM TSC ratio. * Hardware Requirements 1) Two machines with Intel CPUs, called M_A and M_B below. 2) TSC frequency of CPUs on M_A is different from CPUs on M_B. Suppose TSC frequency on M_A is f_a KHz. 3) At least CPUs on M_B support VMX TSC scaling. * Software Requirements 1) Apply this patchset to KVM on both machines. 2) Apply QEMU patches[1] to QEMU commit 40fe17b on both machines * Test Process 1) Start a linux guest on M_A qemu-system-x86_64 -enable-kvm -smp 4 -cpu qemu66 -m 512 -hda linux.img 2) In guest linux, check the TSC frequency detected by Linux kernel. e.g. search in dmeg for messages like "tsc: Detected XYZ.ABC MHz processor" or "tsc: Refined TSC clocksource calibration: XYZ.ABC MHz" 3) Start QEMU waiting for migration on M_B: qemu-system-x86_64 -enable-kvm -smp 4 -cpu qemu64,load-tsc-freq -m 512 -hda linux.img -incoming tcp:0:1234 4) Migrate above VM to M_B as normal in QEMU monitor: migrate tcp:<M_B's ip>:1234 5) After the migration, if VMX TSC scaling and this patchset work on M_B, no messages like "Clocksource tsc unstable (delta = xxxxx ns)" should appear in dmesg of guest linux 6) Furthermore, users can also check whether guest TSC after the migration increases in the same rate as before by running the attached program test_tsc in VM: ./test_tsc N f_a It measures the number of TSC ticks passed in N seconds, and divides it by the expected TSC frequency f_a to get the output result. If this patchset works, the output should be very closed to N [1] http://www.spinics.net/lists/kvm/msg122421.html Thanks, Haozhong
#include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <unistd.h> static inline uint64_t rdtsc(void) { uint32_t lo, hi; asm volatile("lfence; rdtsc" : "=a" (lo), "=d" (hi)); return (uint64_t)hi << 32 | lo; } int main(int argc, char **argv) { uint64_t tsc0, tsc1; int ns, tsc_khz; double delta; if (argc < 2) { printf("Usage: %s <nr_seconds> <tsc_khz>\n", argv[0]); return -1; } if ((ns = atoi(argv[1])) <= 0) return -1; if ((tsc_khz = atoi(argv[2])) <= 0) return -1; tsc0 = rdtsc(); sleep(ns); tsc1 = rdtsc(); delta = tsc1 - tsc0; printf("Passed %lf s\n", delta / (tsc_khz * 1000.0)); return 0; }