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