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 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 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 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 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 118ce83c7adSJason Wang smp_init(); 119ce83c7adSJason Wang 12009b22d11SAvi Kivity ncpus = cpu_count(); 121ce83c7adSJason Wang if (ncpus > MAX_CPU) 122*8dc6b730SAndrew Jones report_abort("number cpus exceeds %d", MAX_CPU); 123*8dc6b730SAndrew Jones 124*8dc6b730SAndrew Jones on_cpus(kvm_clock_init, NULL); 125ce83c7adSJason Wang 1264f0202c0SPaolo Bonzini if (ac > 2) { 1274f0202c0SPaolo Bonzini printf("Wallclock test, threshold %ld\n", threshold); 1284f0202c0SPaolo Bonzini printf("Seconds get from host: %ld\n", sec); 1294f0202c0SPaolo Bonzini for (i = 0; i < ncpus; ++i) 1304f0202c0SPaolo Bonzini on_cpu(i, wallclock_test, &nerr); 1314f0202c0SPaolo Bonzini } 132ce83c7adSJason Wang 133ce83c7adSJason Wang printf("Check the stability of raw cycle ...\n"); 134ce83c7adSJason Wang pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT 135ce83c7adSJason Wang | PVCLOCK_RAW_CYCLE_BIT); 136*8dc6b730SAndrew Jones if (cycle_test(1, &ti[0])) 137ce83c7adSJason Wang printf("Raw cycle is not stable\n"); 138ce83c7adSJason Wang else 139ce83c7adSJason Wang printf("Raw cycle is stable\n"); 140ce83c7adSJason Wang 141ce83c7adSJason Wang pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); 142ce83c7adSJason Wang printf("Monotonic cycle test:\n"); 143*8dc6b730SAndrew Jones nerr += cycle_test(1, &ti[1]); 144ce83c7adSJason Wang 145ce83c7adSJason Wang printf("Measure the performance of raw cycle ...\n"); 146ce83c7adSJason Wang pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT 147ce83c7adSJason Wang | PVCLOCK_RAW_CYCLE_BIT); 148*8dc6b730SAndrew Jones cycle_test(0, &ti[2]); 149ce83c7adSJason Wang 150ce83c7adSJason Wang printf("Measure the performance of adjusted cycle ...\n"); 151ce83c7adSJason Wang pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); 152*8dc6b730SAndrew Jones cycle_test(0, &ti[3]); 153ce83c7adSJason Wang 154*8dc6b730SAndrew Jones on_cpus(kvm_clock_clear, NULL); 155ce83c7adSJason Wang 156ce83c7adSJason Wang return nerr > 0 ? 1 : 0; 157ce83c7adSJason Wang } 158