Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux-2.6-microblaze.git] / tools / testing / selftests / kvm / lib / test_util.c
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 }