1ce83c7adSJason Wang #include "libcflat.h"
2ce83c7adSJason Wang #include "smp.h"
3ce83c7adSJason Wang #include "atomic.h"
4ce83c7adSJason Wang #include "processor.h"
5ce83c7adSJason Wang #include "kvmclock.h"
6ce83c7adSJason Wang
7ce83c7adSJason Wang #define DEFAULT_TEST_LOOPS 100000000L
8ce83c7adSJason Wang #define DEFAULT_THRESHOLD 5L
9ce83c7adSJason Wang
104f0202c0SPaolo Bonzini long loops = DEFAULT_TEST_LOOPS;
114f0202c0SPaolo Bonzini long sec = 0;
124f0202c0SPaolo Bonzini long threshold = DEFAULT_THRESHOLD;
134f0202c0SPaolo Bonzini
14ce83c7adSJason Wang struct test_info {
15ce83c7adSJason Wang struct spinlock lock;
16ce83c7adSJason Wang u64 warps; /* warp count */
17ce83c7adSJason Wang u64 stalls; /* stall count */
18ce83c7adSJason Wang long long worst; /* worst warp */
19ce83c7adSJason Wang volatile cycle_t last; /* last cycle seen by test */
20ce83c7adSJason Wang int check; /* check cycle ? */
21ce83c7adSJason Wang };
22ce83c7adSJason Wang
23ce83c7adSJason Wang struct test_info ti[4];
24ce83c7adSJason Wang
wallclock_test(void * data)254f0202c0SPaolo Bonzini static void wallclock_test(void *data)
26ce83c7adSJason Wang {
274f0202c0SPaolo Bonzini int *p_err = data;
28ce83c7adSJason Wang long ksec, offset;
29ce83c7adSJason Wang struct timespec ts;
30ce83c7adSJason Wang
31ce83c7adSJason Wang kvm_get_wallclock(&ts);
32ce83c7adSJason Wang ksec = ts.tv_sec;
33ce83c7adSJason Wang
34ce83c7adSJason Wang offset = ksec - sec;
35b2e0a90fSAndrew Jones printf("Raw nanoseconds value from kvmclock: %" PRIu64 " (cpu %d)\n", kvm_clock_read(), smp_id());
364f0202c0SPaolo Bonzini printf("Seconds get from kvmclock: %ld (cpu %d, offset: %ld)\n", ksec, smp_id(), offset);
37ce83c7adSJason Wang
38ce83c7adSJason Wang if (offset > threshold || offset < -threshold) {
39ce83c7adSJason Wang printf("offset too large!\n");
404f0202c0SPaolo Bonzini (*p_err)++;
41ce83c7adSJason Wang }
42ce83c7adSJason Wang }
43ce83c7adSJason Wang
kvm_clock_test(void * data)44ce83c7adSJason Wang static void kvm_clock_test(void *data)
45ce83c7adSJason Wang {
46ce83c7adSJason Wang struct test_info *hv_test_info = (struct test_info *)data;
47ce83c7adSJason Wang long i, check = hv_test_info->check;
48ce83c7adSJason Wang
494f0202c0SPaolo Bonzini for (i = 0; i < loops; i++){
50ce83c7adSJason Wang cycle_t t0, t1;
51ce83c7adSJason Wang long long delta;
52ce83c7adSJason Wang
53ce83c7adSJason Wang if (check == 0) {
54ce83c7adSJason Wang kvm_clock_read();
55ce83c7adSJason Wang continue;
56ce83c7adSJason Wang }
57ce83c7adSJason Wang
58ce83c7adSJason Wang spin_lock(&hv_test_info->lock);
59ce83c7adSJason Wang t1 = kvm_clock_read();
60ce83c7adSJason Wang t0 = hv_test_info->last;
61ce83c7adSJason Wang hv_test_info->last = kvm_clock_read();
62ce83c7adSJason Wang spin_unlock(&hv_test_info->lock);
63ce83c7adSJason Wang
64ce83c7adSJason Wang delta = t1 - t0;
65ce83c7adSJason Wang if (delta < 0) {
66ce83c7adSJason Wang spin_lock(&hv_test_info->lock);
67ce83c7adSJason Wang ++hv_test_info->warps;
68ce83c7adSJason Wang if (delta < hv_test_info->worst){
69ce83c7adSJason Wang hv_test_info->worst = delta;
70b006d7ebSAndrew Jones printf("Worst warp %lld\n", hv_test_info->worst);
71ce83c7adSJason Wang }
72ce83c7adSJason Wang spin_unlock(&hv_test_info->lock);
73ce83c7adSJason Wang }
74ce83c7adSJason Wang if (delta == 0)
75ce83c7adSJason Wang ++hv_test_info->stalls;
76ce83c7adSJason Wang
77ce83c7adSJason Wang if (!((unsigned long)i & 31))
78ce83c7adSJason Wang asm volatile("rep; nop");
79ce83c7adSJason Wang }
80ce83c7adSJason Wang }
81ce83c7adSJason Wang
cycle_test(int check,struct test_info * ti)82*8dc6b730SAndrew Jones static int cycle_test(int check, struct test_info *ti)
83ce83c7adSJason Wang {
84ce83c7adSJason Wang unsigned long long begin, end;
85ce83c7adSJason Wang
86ce83c7adSJason Wang begin = rdtsc();
87ce83c7adSJason Wang
88ce83c7adSJason Wang ti->check = check;
89*8dc6b730SAndrew Jones on_cpus(kvm_clock_test, ti);
90ce83c7adSJason Wang
91ce83c7adSJason Wang end = rdtsc();
92ce83c7adSJason Wang
93*8dc6b730SAndrew Jones printf("Total vcpus: %d\n", cpu_count());
944f0202c0SPaolo Bonzini printf("Test loops: %ld\n", loops);
95ce83c7adSJason Wang if (check == 1) {
96b006d7ebSAndrew Jones printf("Total warps: %" PRId64 "\n", ti->warps);
97b006d7ebSAndrew Jones printf("Total stalls: %" PRId64 "\n", ti->stalls);
98ce83c7adSJason Wang printf("Worst warp: %lld\n", ti->worst);
99ce83c7adSJason Wang } else
100ce83c7adSJason Wang printf("TSC cycles: %lld\n", end - begin);
101ce83c7adSJason Wang
102ce83c7adSJason Wang return ti->warps ? 1 : 0;
103ce83c7adSJason Wang }
104ce83c7adSJason Wang
main(int ac,char ** av)105ce83c7adSJason Wang int main(int ac, char **av)
106ce83c7adSJason Wang {
1074f0202c0SPaolo Bonzini int nerr = 0;
10809b22d11SAvi Kivity int ncpus;
1094f0202c0SPaolo Bonzini int i;
110ce83c7adSJason Wang
111ce83c7adSJason Wang if (ac > 1)
112ce83c7adSJason Wang loops = atol(av[1]);
113ce83c7adSJason Wang if (ac > 2)
114ce83c7adSJason Wang sec = atol(av[2]);
115ce83c7adSJason Wang if (ac > 3)
116ce83c7adSJason Wang threshold = atol(av[3]);
117ce83c7adSJason Wang
11809b22d11SAvi Kivity ncpus = cpu_count();
119ce83c7adSJason Wang if (ncpus > MAX_CPU)
120*8dc6b730SAndrew Jones report_abort("number cpus exceeds %d", MAX_CPU);
121*8dc6b730SAndrew Jones
122*8dc6b730SAndrew Jones on_cpus(kvm_clock_init, NULL);
123ce83c7adSJason Wang
1244f0202c0SPaolo Bonzini if (ac > 2) {
1254f0202c0SPaolo Bonzini printf("Wallclock test, threshold %ld\n", threshold);
1264f0202c0SPaolo Bonzini printf("Seconds get from host: %ld\n", sec);
1274f0202c0SPaolo Bonzini for (i = 0; i < ncpus; ++i)
1284f0202c0SPaolo Bonzini on_cpu(i, wallclock_test, &nerr);
1294f0202c0SPaolo Bonzini }
130ce83c7adSJason Wang
131ce83c7adSJason Wang printf("Check the stability of raw cycle ...\n");
132ce83c7adSJason Wang pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT
133ce83c7adSJason Wang | PVCLOCK_RAW_CYCLE_BIT);
134*8dc6b730SAndrew Jones if (cycle_test(1, &ti[0]))
135ce83c7adSJason Wang printf("Raw cycle is not stable\n");
136ce83c7adSJason Wang else
137ce83c7adSJason Wang printf("Raw cycle is stable\n");
138ce83c7adSJason Wang
139ce83c7adSJason Wang pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
140ce83c7adSJason Wang printf("Monotonic cycle test:\n");
141*8dc6b730SAndrew Jones nerr += cycle_test(1, &ti[1]);
142ce83c7adSJason Wang
143ce83c7adSJason Wang printf("Measure the performance of raw cycle ...\n");
144ce83c7adSJason Wang pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT
145ce83c7adSJason Wang | PVCLOCK_RAW_CYCLE_BIT);
146*8dc6b730SAndrew Jones cycle_test(0, &ti[2]);
147ce83c7adSJason Wang
148ce83c7adSJason Wang printf("Measure the performance of adjusted cycle ...\n");
149ce83c7adSJason Wang pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
150*8dc6b730SAndrew Jones cycle_test(0, &ti[3]);
151ce83c7adSJason Wang
152*8dc6b730SAndrew Jones on_cpus(kvm_clock_clear, NULL);
153ce83c7adSJason Wang
154ce83c7adSJason Wang return nerr > 0 ? 1 : 0;
155ce83c7adSJason Wang }
156