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

* 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

#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();
        tsc1 = rdtsc();

        delta = tsc1 - tsc0;
        printf("Passed %lf s\n", delta / (tsc_khz * 1000.0));

        return 0;

Reply via email to