123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- #include "libcflat.h"
- #include "smp.h"
- #include "atomic.h"
- #include "processor.h"
- #include "kvmclock.h"
- #define DEFAULT_TEST_LOOPS 100000000L
- #define DEFAULT_THRESHOLD 5L
- long loops = DEFAULT_TEST_LOOPS;
- long sec = 0;
- long threshold = DEFAULT_THRESHOLD;
- struct test_info {
- struct spinlock lock;
- u64 warps; /* warp count */
- u64 stalls; /* stall count */
- long long worst; /* worst warp */
- volatile cycle_t last; /* last cycle seen by test */
- int check; /* check cycle ? */
- };
- struct test_info ti[4];
- static void wallclock_test(void *data)
- {
- int *p_err = data;
- long ksec, offset;
- struct timespec ts;
- kvm_get_wallclock(&ts);
- ksec = ts.tv_sec;
- offset = ksec - sec;
- printf("Raw nanoseconds value from kvmclock: %" PRIu64 " (cpu %d)\n", kvm_clock_read(), smp_id());
- printf("Seconds get from kvmclock: %ld (cpu %d, offset: %ld)\n", ksec, smp_id(), offset);
- if (offset > threshold || offset < -threshold) {
- printf("offset too large!\n");
- (*p_err)++;
- }
- }
- static void kvm_clock_test(void *data)
- {
- struct test_info *hv_test_info = (struct test_info *)data;
- long i, check = hv_test_info->check;
- for (i = 0; i < loops; i++){
- cycle_t t0, t1;
- long long delta;
- if (check == 0) {
- kvm_clock_read();
- continue;
- }
- spin_lock(&hv_test_info->lock);
- t1 = kvm_clock_read();
- t0 = hv_test_info->last;
- hv_test_info->last = kvm_clock_read();
- spin_unlock(&hv_test_info->lock);
- delta = t1 - t0;
- if (delta < 0) {
- spin_lock(&hv_test_info->lock);
- ++hv_test_info->warps;
- if (delta < hv_test_info->worst){
- hv_test_info->worst = delta;
- printf("Worst warp %lld\n", hv_test_info->worst);
- }
- spin_unlock(&hv_test_info->lock);
- }
- if (delta == 0)
- ++hv_test_info->stalls;
- if (!((unsigned long)i & 31))
- asm volatile("rep; nop");
- }
- }
- static int cycle_test(int check, struct test_info *ti)
- {
- unsigned long long begin, end;
- begin = rdtsc();
- ti->check = check;
- on_cpus(kvm_clock_test, ti);
- end = rdtsc();
- printf("Total vcpus: %d\n", cpu_count());
- printf("Test loops: %ld\n", loops);
- if (check == 1) {
- printf("Total warps: %" PRId64 "\n", ti->warps);
- printf("Total stalls: %" PRId64 "\n", ti->stalls);
- printf("Worst warp: %lld\n", ti->worst);
- } else
- printf("TSC cycles: %lld\n", end - begin);
- return ti->warps ? 1 : 0;
- }
- int main(int ac, char **av)
- {
- int nerr = 0;
- int ncpus;
- int i;
- if (ac > 1)
- loops = atol(av[1]);
- if (ac > 2)
- sec = atol(av[2]);
- if (ac > 3)
- threshold = atol(av[3]);
- smp_init();
- ncpus = cpu_count();
- if (ncpus > MAX_CPU)
- report_abort("number cpus exceeds %d", MAX_CPU);
- on_cpus(kvm_clock_init, NULL);
- if (ac > 2) {
- printf("Wallclock test, threshold %ld\n", threshold);
- printf("Seconds get from host: %ld\n", sec);
- for (i = 0; i < ncpus; ++i)
- on_cpu(i, wallclock_test, &nerr);
- }
- printf("Check the stability of raw cycle ...\n");
- pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT
- | PVCLOCK_RAW_CYCLE_BIT);
- if (cycle_test(1, &ti[0]))
- printf("Raw cycle is not stable\n");
- else
- printf("Raw cycle is stable\n");
- pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
- printf("Monotonic cycle test:\n");
- nerr += cycle_test(1, &ti[1]);
- printf("Measure the performance of raw cycle ...\n");
- pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT
- | PVCLOCK_RAW_CYCLE_BIT);
- cycle_test(0, &ti[2]);
- printf("Measure the performance of adjusted cycle ...\n");
- pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
- cycle_test(0, &ti[3]);
- on_cpus(kvm_clock_clear, NULL);
- return nerr > 0 ? 1 : 0;
- }
|