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 atomic_t ncpus; /* number of cpu in the test*/ 21 int check; /* check cycle ? */ 22 }; 23 24 struct test_info ti[4]; 25 26 static void wallclock_test(void *data) 27 { 28 int *p_err = data; 29 long ksec, offset; 30 struct timespec ts; 31 32 kvm_get_wallclock(&ts); 33 ksec = ts.tv_sec; 34 35 offset = ksec - sec; 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 atomic_dec(&hv_test_info->ncpus); 82 } 83 84 static int cycle_test(int ncpus, int check, struct test_info *ti) 85 { 86 int i; 87 unsigned long long begin, end; 88 89 begin = rdtsc(); 90 91 atomic_set(&ti->ncpus, ncpus); 92 ti->check = check; 93 for (i = ncpus - 1; i >= 0; i--) 94 on_cpu_async(i, kvm_clock_test, (void *)ti); 95 96 /* Wait for the end of other vcpu */ 97 while(atomic_read(&ti->ncpus)) 98 ; 99 100 end = rdtsc(); 101 102 printf("Total vcpus: %d\n", ncpus); 103 printf("Test loops: %ld\n", loops); 104 if (check == 1) { 105 printf("Total warps: %lld\n", ti->warps); 106 printf("Total stalls: %lld\n", ti->stalls); 107 printf("Worst warp: %lld\n", ti->worst); 108 } else 109 printf("TSC cycles: %lld\n", end - begin); 110 111 return ti->warps ? 1 : 0; 112 } 113 114 int main(int ac, char **av) 115 { 116 int nerr = 0; 117 int ncpus; 118 int i; 119 120 if (ac > 1) 121 loops = atol(av[1]); 122 if (ac > 2) 123 sec = atol(av[2]); 124 if (ac > 3) 125 threshold = atol(av[3]); 126 127 smp_init(); 128 129 ncpus = cpu_count(); 130 if (ncpus > MAX_CPU) 131 ncpus = MAX_CPU; 132 for (i = 0; i < ncpus; ++i) 133 on_cpu(i, kvm_clock_init, (void *)0); 134 135 if (ac > 2) { 136 printf("Wallclock test, threshold %ld\n", threshold); 137 printf("Seconds get from host: %ld\n", sec); 138 for (i = 0; i < ncpus; ++i) 139 on_cpu(i, wallclock_test, &nerr); 140 } 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, 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, 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, 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, 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