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