Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling

From: Haozhong Zhang
Date: Fri Oct 23 2015 - 10:31:53 EST


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;
}