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