kvmclock_test.c 4.6 KB

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