1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * tools/testing/selftests/kvm/lib/test_util.c 4 * 5 * Copyright (C) 2020, Google LLC. 6 */ 7 8 #include <assert.h> 9 #include <ctype.h> 10 #include <limits.h> 11 #include <stdlib.h> 12 #include <time.h> 13 #include "linux/kernel.h" 14 15 #include "test_util.h" 16 17 /* 18 * Parses "[0-9]+[kmgt]?". 19 */ 20 size_t parse_size(const char *size) 21 { 22 size_t base; 23 char *scale; 24 int shift = 0; 25 26 TEST_ASSERT(size && isdigit(size[0]), "Need at least one digit in '%s'", size); 27 28 base = strtoull(size, &scale, 0); 29 30 TEST_ASSERT(base != ULLONG_MAX, "Overflow parsing size!"); 31 32 switch (tolower(*scale)) { 33 case 't': 34 shift = 40; 35 break; 36 case 'g': 37 shift = 30; 38 break; 39 case 'm': 40 shift = 20; 41 break; 42 case 'k': 43 shift = 10; 44 break; 45 case 'b': 46 case '\0': 47 shift = 0; 48 break; 49 default: 50 TEST_ASSERT(false, "Unknown size letter %c", *scale); 51 } 52 53 TEST_ASSERT((base << shift) >> shift == base, "Overflow scaling size!"); 54 55 return base << shift; 56 } 57 58 int64_t timespec_to_ns(struct timespec ts) 59 { 60 return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec; 61 } 62 63 struct timespec timespec_add_ns(struct timespec ts, int64_t ns) 64 { 65 struct timespec res; 66 67 res.tv_nsec = ts.tv_nsec + ns; 68 res.tv_sec = ts.tv_sec + res.tv_nsec / 1000000000LL; 69 res.tv_nsec %= 1000000000LL; 70 71 return res; 72 } 73 74 struct timespec timespec_add(struct timespec ts1, struct timespec ts2) 75 { 76 int64_t ns1 = timespec_to_ns(ts1); 77 int64_t ns2 = timespec_to_ns(ts2); 78 return timespec_add_ns((struct timespec){0}, ns1 + ns2); 79 } 80 81 struct timespec timespec_sub(struct timespec ts1, struct timespec ts2) 82 { 83 int64_t ns1 = timespec_to_ns(ts1); 84 int64_t ns2 = timespec_to_ns(ts2); 85 return timespec_add_ns((struct timespec){0}, ns1 - ns2); 86 } 87 88 struct timespec timespec_elapsed(struct timespec start) 89 { 90 struct timespec end; 91 92 clock_gettime(CLOCK_MONOTONIC, &end); 93 return timespec_sub(end, start); 94 } 95 96 struct timespec timespec_div(struct timespec ts, int divisor) 97 { 98 int64_t ns = timespec_to_ns(ts) / divisor; 99 100 return timespec_add_ns((struct timespec){0}, ns); 101 } 102 103 void print_skip(const char *fmt, ...) 104 { 105 va_list ap; 106 107 assert(fmt); 108 va_start(ap, fmt); 109 vprintf(fmt, ap); 110 va_end(ap); 111 puts(", skipping test"); 112 } 113 114 const struct vm_mem_backing_src_alias backing_src_aliases[] = { 115 {"anonymous", VM_MEM_SRC_ANONYMOUS,}, 116 {"anonymous_thp", VM_MEM_SRC_ANONYMOUS_THP,}, 117 {"anonymous_hugetlb", VM_MEM_SRC_ANONYMOUS_HUGETLB,}, 118 }; 119 120 void backing_src_help(void) 121 { 122 int i; 123 124 printf("Available backing src types:\n"); 125 for (i = 0; i < ARRAY_SIZE(backing_src_aliases); i++) 126 printf("\t%s\n", backing_src_aliases[i].name); 127 } 128 129 enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name) 130 { 131 int i; 132 133 for (i = 0; i < ARRAY_SIZE(backing_src_aliases); i++) 134 if (!strcmp(type_name, backing_src_aliases[i].name)) 135 return backing_src_aliases[i].type; 136 137 backing_src_help(); 138 TEST_FAIL("Unknown backing src type: %s", type_name); 139 return -1; 140 } 141