Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: selftests: Rework timespec functions and usage

The steal_time test's timespec stop condition was wrong and should have
used the timespec functions instead to avoid being wrong, but
timespec_diff had a strange interface. Rework all the timespec API and
its use.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Andrew Jones and committed by
Paolo Bonzini
bfcaa849 cf6c26ec

+35 -44
+16 -21
tools/testing/selftests/kvm/demand_paging_test.c
··· 117 117 struct kvm_vm *vm = args->vm; 118 118 int vcpu_id = args->vcpu_id; 119 119 struct kvm_run *run; 120 - struct timespec start; 121 - struct timespec end; 120 + struct timespec start, end, ts_diff; 122 121 123 122 vcpu_args_set(vm, vcpu_id, 1, vcpu_id); 124 123 run = vcpu_state(vm, vcpu_id); ··· 134 135 } 135 136 136 137 clock_gettime(CLOCK_MONOTONIC, &end); 137 - PER_VCPU_DEBUG("vCPU %d execution time: %lld.%.9lds\n", vcpu_id, 138 - (long long)(timespec_diff(start, end).tv_sec), 139 - timespec_diff(start, end).tv_nsec); 138 + ts_diff = timespec_sub(end, start); 139 + PER_VCPU_DEBUG("vCPU %d execution time: %ld.%.9lds\n", vcpu_id, 140 + ts_diff.tv_sec, ts_diff.tv_nsec); 140 141 141 142 return NULL; 142 143 } ··· 200 201 201 202 clock_gettime(CLOCK_MONOTONIC, &end); 202 203 203 - PER_PAGE_DEBUG("UFFDIO_COPY %d \t%lld ns\n", tid, 204 - (long long)timespec_to_ns(timespec_diff(start, end))); 204 + PER_PAGE_DEBUG("UFFDIO_COPY %d \t%ld ns\n", tid, 205 + timespec_to_ns(timespec_sub(end, start))); 205 206 PER_PAGE_DEBUG("Paged in %ld bytes at 0x%lx from thread %d\n", 206 207 host_page_size, addr, tid); 207 208 ··· 223 224 int pipefd = uffd_args->pipefd; 224 225 useconds_t delay = uffd_args->delay; 225 226 int64_t pages = 0; 226 - struct timespec start; 227 - struct timespec end; 227 + struct timespec start, end, ts_diff; 228 228 229 229 clock_gettime(CLOCK_MONOTONIC, &start); 230 230 while (!quit_uffd_thread) { ··· 293 295 } 294 296 295 297 clock_gettime(CLOCK_MONOTONIC, &end); 296 - PER_VCPU_DEBUG("userfaulted %ld pages over %lld.%.9lds. (%f/sec)\n", 297 - pages, (long long)(timespec_diff(start, end).tv_sec), 298 - timespec_diff(start, end).tv_nsec, pages / 299 - ((double)timespec_diff(start, end).tv_sec + 300 - (double)timespec_diff(start, end).tv_nsec / 100000000.0)); 298 + ts_diff = timespec_sub(end, start); 299 + PER_VCPU_DEBUG("userfaulted %ld pages over %ld.%.9lds. (%f/sec)\n", 300 + pages, ts_diff.tv_sec, ts_diff.tv_nsec, 301 + pages / ((double)ts_diff.tv_sec + (double)ts_diff.tv_nsec / 100000000.0)); 301 302 302 303 return NULL; 303 304 } ··· 357 360 pthread_t *vcpu_threads; 358 361 pthread_t *uffd_handler_threads = NULL; 359 362 struct uffd_handler_args *uffd_args = NULL; 363 + struct timespec start, end, ts_diff; 360 364 int *pipefds = NULL; 361 365 struct kvm_vm *vm; 362 366 uint64_t guest_num_pages; 363 367 int vcpu_id; 364 368 int r; 365 - struct timespec start; 366 - struct timespec end; 367 369 368 370 vm = create_vm(mode, vcpus, vcpu_memory_bytes); 369 371 ··· 510 514 } 511 515 } 512 516 513 - pr_info("Total guest execution time: %lld.%.9lds\n", 514 - (long long)(timespec_diff(start, end).tv_sec), 515 - timespec_diff(start, end).tv_nsec); 517 + ts_diff = timespec_sub(end, start); 518 + pr_info("Total guest execution time: %ld.%.9lds\n", 519 + ts_diff.tv_sec, ts_diff.tv_nsec); 516 520 pr_info("Overall demand paging rate: %f pgs/sec\n", 517 - guest_num_pages / ((double)timespec_diff(start, end).tv_sec + 518 - (double)timespec_diff(start, end).tv_nsec / 100000000.0)); 521 + guest_num_pages / ((double)ts_diff.tv_sec + (double)ts_diff.tv_nsec / 100000000.0)); 519 522 520 523 ucall_uninit(vm); 521 524 kvm_vm_free(vm);
+2 -1
tools/testing/selftests/kvm/include/test_util.h
··· 61 61 size_t parse_size(const char *size); 62 62 63 63 int64_t timespec_to_ns(struct timespec ts); 64 - struct timespec timespec_diff(struct timespec start, struct timespec end); 65 64 struct timespec timespec_add_ns(struct timespec ts, int64_t ns); 65 + struct timespec timespec_add(struct timespec ts1, struct timespec ts2); 66 + struct timespec timespec_sub(struct timespec ts1, struct timespec ts2); 66 67 67 68 #endif /* SELFTEST_KVM_TEST_UTIL_H */
+16 -21
tools/testing/selftests/kvm/lib/test_util.c
··· 56 56 return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec; 57 57 } 58 58 59 - struct timespec timespec_diff(struct timespec start, struct timespec end) 60 - { 61 - struct timespec temp; 62 - 63 - if ((end.tv_nsec - start.tv_nsec) < 0) { 64 - temp.tv_sec = end.tv_sec - start.tv_sec - 1; 65 - temp.tv_nsec = 1000000000LL + end.tv_nsec - start.tv_nsec; 66 - } else { 67 - temp.tv_sec = end.tv_sec - start.tv_sec; 68 - temp.tv_nsec = end.tv_nsec - start.tv_nsec; 69 - } 70 - 71 - return temp; 72 - } 73 - 74 59 struct timespec timespec_add_ns(struct timespec ts, int64_t ns) 75 60 { 76 61 struct timespec res; 77 62 78 - res.tv_sec = ts.tv_sec; 79 63 res.tv_nsec = ts.tv_nsec + ns; 80 - 81 - if (res.tv_nsec > 1000000000UL) { 82 - res.tv_sec += 1; 83 - res.tv_nsec -= 1000000000UL; 84 - } 64 + res.tv_sec = ts.tv_sec + res.tv_nsec / 1000000000LL; 65 + res.tv_nsec %= 1000000000LL; 85 66 86 67 return res; 68 + } 69 + 70 + struct timespec timespec_add(struct timespec ts1, struct timespec ts2) 71 + { 72 + int64_t ns1 = timespec_to_ns(ts1); 73 + int64_t ns2 = timespec_to_ns(ts2); 74 + return timespec_add_ns((struct timespec){0}, ns1 + ns2); 75 + } 76 + 77 + struct timespec timespec_sub(struct timespec ts1, struct timespec ts2) 78 + { 79 + int64_t ns1 = timespec_to_ns(ts1); 80 + int64_t ns2 = timespec_to_ns(ts2); 81 + return timespec_add_ns((struct timespec){0}, ns1 - ns2); 87 82 } 88 83 89 84 void print_skip(const char *fmt, ...)
+1 -1
tools/testing/selftests/kvm/steal_time.c
··· 242 242 243 243 while (1) { 244 244 clock_gettime(CLOCK_MONOTONIC, &ts); 245 - if (ts.tv_sec > stop.tv_sec || ts.tv_nsec >= stop.tv_nsec) 245 + if (timespec_to_ns(timespec_sub(ts, stop)) >= 0) 246 246 break; 247 247 } 248 248