xref: /kvm-unit-tests/x86/kvmclock_test.c (revision ce83c7add52222222afb15a9ca831d1f2b0123bb)
1*ce83c7adSJason Wang #include "libcflat.h"
2*ce83c7adSJason Wang #include "smp.h"
3*ce83c7adSJason Wang #include "atomic.h"
4*ce83c7adSJason Wang #include "processor.h"
5*ce83c7adSJason Wang #include "kvmclock.h"
6*ce83c7adSJason Wang 
7*ce83c7adSJason Wang #define DEFAULT_TEST_LOOPS 100000000L
8*ce83c7adSJason Wang #define DEFAULT_THRESHOLD  5L
9*ce83c7adSJason Wang 
10*ce83c7adSJason Wang struct test_info {
11*ce83c7adSJason Wang         struct spinlock lock;
12*ce83c7adSJason Wang         long loops;               /* test loops */
13*ce83c7adSJason Wang         u64 warps;                /* warp count */
14*ce83c7adSJason Wang         u64 stalls;               /* stall count */
15*ce83c7adSJason Wang         long long worst;          /* worst warp */
16*ce83c7adSJason Wang         volatile cycle_t last;    /* last cycle seen by test */
17*ce83c7adSJason Wang         atomic_t ncpus;           /* number of cpu in the test*/
18*ce83c7adSJason Wang         int check;                /* check cycle ? */
19*ce83c7adSJason Wang };
20*ce83c7adSJason Wang 
21*ce83c7adSJason Wang struct test_info ti[4];
22*ce83c7adSJason Wang 
23*ce83c7adSJason Wang static int wallclock_test(long sec, long threshold)
24*ce83c7adSJason Wang {
25*ce83c7adSJason Wang         long ksec, offset;
26*ce83c7adSJason Wang         struct timespec ts;
27*ce83c7adSJason Wang 
28*ce83c7adSJason Wang         printf("Wallclock test, threshold %ld\n", threshold);
29*ce83c7adSJason Wang         kvm_get_wallclock(&ts);
30*ce83c7adSJason Wang         ksec = ts.tv_sec;
31*ce83c7adSJason Wang 
32*ce83c7adSJason Wang         offset = ksec - sec;
33*ce83c7adSJason Wang         printf("Seconds get from host:     %ld\n", sec);
34*ce83c7adSJason Wang         printf("Seconds get from kvmclock: %ld\n", ksec);
35*ce83c7adSJason Wang         printf("Offset:                    %ld\n", offset);
36*ce83c7adSJason Wang 
37*ce83c7adSJason Wang         if (offset > threshold || offset < -threshold) {
38*ce83c7adSJason Wang                 printf("offset too large!\n");
39*ce83c7adSJason Wang                 return 1;
40*ce83c7adSJason Wang         }
41*ce83c7adSJason Wang 
42*ce83c7adSJason Wang         return 0;
43*ce83c7adSJason Wang }
44*ce83c7adSJason Wang 
45*ce83c7adSJason Wang static void kvm_clock_test(void *data)
46*ce83c7adSJason Wang {
47*ce83c7adSJason Wang         struct test_info *hv_test_info = (struct test_info *)data;
48*ce83c7adSJason Wang         long i, check = hv_test_info->check;
49*ce83c7adSJason Wang 
50*ce83c7adSJason Wang         for (i = 0; i < hv_test_info->loops; i++){
51*ce83c7adSJason Wang                 cycle_t t0, t1;
52*ce83c7adSJason Wang                 long long delta;
53*ce83c7adSJason Wang 
54*ce83c7adSJason Wang                 if (check == 0) {
55*ce83c7adSJason Wang                         kvm_clock_read();
56*ce83c7adSJason Wang                         continue;
57*ce83c7adSJason Wang                 }
58*ce83c7adSJason Wang 
59*ce83c7adSJason Wang                 spin_lock(&hv_test_info->lock);
60*ce83c7adSJason Wang                 t1 = kvm_clock_read();
61*ce83c7adSJason Wang                 t0 = hv_test_info->last;
62*ce83c7adSJason Wang                 hv_test_info->last = kvm_clock_read();
63*ce83c7adSJason Wang                 spin_unlock(&hv_test_info->lock);
64*ce83c7adSJason Wang 
65*ce83c7adSJason Wang                 delta = t1 - t0;
66*ce83c7adSJason Wang                 if (delta < 0) {
67*ce83c7adSJason Wang                         spin_lock(&hv_test_info->lock);
68*ce83c7adSJason Wang                         ++hv_test_info->warps;
69*ce83c7adSJason Wang                         if (delta < hv_test_info->worst){
70*ce83c7adSJason Wang                                 hv_test_info->worst = delta;
71*ce83c7adSJason Wang                                 printf("Worst warp %lld %\n", hv_test_info->worst);
72*ce83c7adSJason Wang                         }
73*ce83c7adSJason Wang                         spin_unlock(&hv_test_info->lock);
74*ce83c7adSJason Wang                 }
75*ce83c7adSJason Wang                 if (delta == 0)
76*ce83c7adSJason Wang                         ++hv_test_info->stalls;
77*ce83c7adSJason Wang 
78*ce83c7adSJason Wang                 if (!((unsigned long)i & 31))
79*ce83c7adSJason Wang                         asm volatile("rep; nop");
80*ce83c7adSJason Wang         }
81*ce83c7adSJason Wang 
82*ce83c7adSJason Wang         atomic_dec(&hv_test_info->ncpus);
83*ce83c7adSJason Wang }
84*ce83c7adSJason Wang 
85*ce83c7adSJason Wang static int cycle_test(int ncpus, long loops, int check, struct test_info *ti)
86*ce83c7adSJason Wang {
87*ce83c7adSJason Wang         int i;
88*ce83c7adSJason Wang         unsigned long long begin, end;
89*ce83c7adSJason Wang 
90*ce83c7adSJason Wang         begin = rdtsc();
91*ce83c7adSJason Wang 
92*ce83c7adSJason Wang         atomic_set(&ti->ncpus, ncpus);
93*ce83c7adSJason Wang         ti->loops = loops;
94*ce83c7adSJason Wang         ti->check = check;
95*ce83c7adSJason Wang         for (i = ncpus - 1; i >= 0; i--)
96*ce83c7adSJason Wang                 on_cpu_async(i, kvm_clock_test, (void *)ti);
97*ce83c7adSJason Wang 
98*ce83c7adSJason Wang         /* Wait for the end of other vcpu */
99*ce83c7adSJason Wang         while(atomic_read(&ti->ncpus))
100*ce83c7adSJason Wang                 ;
101*ce83c7adSJason Wang 
102*ce83c7adSJason Wang         end = rdtsc();
103*ce83c7adSJason Wang 
104*ce83c7adSJason Wang         printf("Total vcpus: %d\n", ncpus);
105*ce83c7adSJason Wang         printf("Test  loops: %ld\n", ti->loops);
106*ce83c7adSJason Wang         if (check == 1) {
107*ce83c7adSJason Wang                 printf("Total warps:  %lld\n", ti->warps);
108*ce83c7adSJason Wang                 printf("Total stalls: %lld\n", ti->stalls);
109*ce83c7adSJason Wang                 printf("Worst warp:   %lld\n", ti->worst);
110*ce83c7adSJason Wang         } else
111*ce83c7adSJason Wang                 printf("TSC cycles:  %lld\n", end - begin);
112*ce83c7adSJason Wang 
113*ce83c7adSJason Wang         return ti->warps ? 1 : 0;
114*ce83c7adSJason Wang }
115*ce83c7adSJason Wang 
116*ce83c7adSJason Wang int main(int ac, char **av)
117*ce83c7adSJason Wang {
118*ce83c7adSJason Wang         int ncpus = cpu_count();
119*ce83c7adSJason Wang         int nerr = 0, i;
120*ce83c7adSJason Wang         long loops = DEFAULT_TEST_LOOPS;
121*ce83c7adSJason Wang         long sec = 0;
122*ce83c7adSJason Wang         long threshold = DEFAULT_THRESHOLD;
123*ce83c7adSJason Wang 
124*ce83c7adSJason Wang         if (ac > 1)
125*ce83c7adSJason Wang                 loops = atol(av[1]);
126*ce83c7adSJason Wang         if (ac > 2)
127*ce83c7adSJason Wang                 sec = atol(av[2]);
128*ce83c7adSJason Wang         if (ac > 3)
129*ce83c7adSJason Wang                 threshold = atol(av[3]);
130*ce83c7adSJason Wang 
131*ce83c7adSJason Wang         smp_init();
132*ce83c7adSJason Wang 
133*ce83c7adSJason Wang         if (ncpus > MAX_CPU)
134*ce83c7adSJason Wang                 ncpus = MAX_CPU;
135*ce83c7adSJason Wang         for (i = 0; i < ncpus; ++i)
136*ce83c7adSJason Wang                 on_cpu(i, kvm_clock_init, (void *)0);
137*ce83c7adSJason Wang 
138*ce83c7adSJason Wang         if (ac > 2)
139*ce83c7adSJason Wang                 nerr += wallclock_test(sec, threshold);
140*ce83c7adSJason Wang 
141*ce83c7adSJason Wang         printf("Check the stability of raw cycle ...\n");
142*ce83c7adSJason Wang         pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT
143*ce83c7adSJason Wang                           | PVCLOCK_RAW_CYCLE_BIT);
144*ce83c7adSJason Wang         if (cycle_test(ncpus, loops, 1, &ti[0]))
145*ce83c7adSJason Wang                 printf("Raw cycle is not stable\n");
146*ce83c7adSJason Wang         else
147*ce83c7adSJason Wang                 printf("Raw cycle is stable\n");
148*ce83c7adSJason Wang 
149*ce83c7adSJason Wang         pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
150*ce83c7adSJason Wang         printf("Monotonic cycle test:\n");
151*ce83c7adSJason Wang         nerr += cycle_test(ncpus, loops, 1, &ti[1]);
152*ce83c7adSJason Wang 
153*ce83c7adSJason Wang         printf("Measure the performance of raw cycle ...\n");
154*ce83c7adSJason Wang         pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT
155*ce83c7adSJason Wang                           | PVCLOCK_RAW_CYCLE_BIT);
156*ce83c7adSJason Wang         cycle_test(ncpus, loops, 0, &ti[2]);
157*ce83c7adSJason Wang 
158*ce83c7adSJason Wang         printf("Measure the performance of adjusted cycle ...\n");
159*ce83c7adSJason Wang         pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
160*ce83c7adSJason Wang         cycle_test(ncpus, loops, 0, &ti[3]);
161*ce83c7adSJason Wang 
162*ce83c7adSJason Wang         for (i = 0; i < ncpus; ++i)
163*ce83c7adSJason Wang                 on_cpu(i, kvm_clock_clear, (void *)0);
164*ce83c7adSJason Wang 
165*ce83c7adSJason Wang         return nerr > 0 ? 1 : 0;
166*ce83c7adSJason Wang }
167