xref: /linux/tools/testing/selftests/kvm/lib/test_util.c (revision 02e5f74ef08d3e6afec438d571487d0d0cec3c48)
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 #include <stdio.h>
8 #include <stdarg.h>
9 #include <assert.h>
10 #include <ctype.h>
11 #include <limits.h>
12 #include <stdlib.h>
13 #include <time.h>
14 #include <sys/stat.h>
15 #include <sys/syscall.h>
16 #include <linux/mman.h>
17 #include "linux/kernel.h"
18 
19 #include "test_util.h"
20 
21 sigjmp_buf expect_sigbus_jmpbuf;
22 
expect_sigbus_handler(int signum)23 void __attribute__((used)) expect_sigbus_handler(int signum)
24 {
25 	siglongjmp(expect_sigbus_jmpbuf, 1);
26 }
27 
28 /*
29  * Random number generator that is usable from guest code. This is the
30  * Park-Miller LCG using standard constants.
31  */
32 
new_guest_random_state(uint32_t seed)33 struct guest_random_state new_guest_random_state(uint32_t seed)
34 {
35 	struct guest_random_state s = {.seed = seed};
36 	return s;
37 }
38 
guest_random_u32(struct guest_random_state * state)39 uint32_t guest_random_u32(struct guest_random_state *state)
40 {
41 	state->seed = (uint64_t)state->seed * 48271 % ((uint32_t)(1 << 31) - 1);
42 	return state->seed;
43 }
44 
45 /*
46  * Parses "[0-9]+[kmgt]?".
47  */
parse_size(const char * size)48 size_t parse_size(const char *size)
49 {
50 	size_t base;
51 	char *scale;
52 	int shift = 0;
53 
54 	TEST_ASSERT(size && isdigit(size[0]), "Need at least one digit in '%s'", size);
55 
56 	base = strtoull(size, &scale, 0);
57 
58 	TEST_ASSERT(base != ULLONG_MAX, "Overflow parsing size!");
59 
60 	switch (tolower(*scale)) {
61 	case 't':
62 		shift = 40;
63 		break;
64 	case 'g':
65 		shift = 30;
66 		break;
67 	case 'm':
68 		shift = 20;
69 		break;
70 	case 'k':
71 		shift = 10;
72 		break;
73 	case 'b':
74 	case '\0':
75 		shift = 0;
76 		break;
77 	default:
78 		TEST_ASSERT(false, "Unknown size letter %c", *scale);
79 	}
80 
81 	TEST_ASSERT((base << shift) >> shift == base, "Overflow scaling size!");
82 
83 	return base << shift;
84 }
85 
timespec_to_ns(struct timespec ts)86 int64_t timespec_to_ns(struct timespec ts)
87 {
88 	return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec;
89 }
90 
timespec_add_ns(struct timespec ts,int64_t ns)91 struct timespec timespec_add_ns(struct timespec ts, int64_t ns)
92 {
93 	struct timespec res;
94 
95 	res.tv_nsec = ts.tv_nsec + ns;
96 	res.tv_sec = ts.tv_sec + res.tv_nsec / 1000000000LL;
97 	res.tv_nsec %= 1000000000LL;
98 
99 	return res;
100 }
101 
timespec_add(struct timespec ts1,struct timespec ts2)102 struct timespec timespec_add(struct timespec ts1, struct timespec ts2)
103 {
104 	int64_t ns1 = timespec_to_ns(ts1);
105 	int64_t ns2 = timespec_to_ns(ts2);
106 	return timespec_add_ns((struct timespec){0}, ns1 + ns2);
107 }
108 
timespec_sub(struct timespec ts1,struct timespec ts2)109 struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)
110 {
111 	int64_t ns1 = timespec_to_ns(ts1);
112 	int64_t ns2 = timespec_to_ns(ts2);
113 	return timespec_add_ns((struct timespec){0}, ns1 - ns2);
114 }
115 
timespec_elapsed(struct timespec start)116 struct timespec timespec_elapsed(struct timespec start)
117 {
118 	struct timespec end;
119 
120 	clock_gettime(CLOCK_MONOTONIC, &end);
121 	return timespec_sub(end, start);
122 }
123 
timespec_div(struct timespec ts,int divisor)124 struct timespec timespec_div(struct timespec ts, int divisor)
125 {
126 	int64_t ns = timespec_to_ns(ts) / divisor;
127 
128 	return timespec_add_ns((struct timespec){0}, ns);
129 }
130 
print_skip(const char * fmt,...)131 void print_skip(const char *fmt, ...)
132 {
133 	va_list ap;
134 
135 	assert(fmt);
136 	va_start(ap, fmt);
137 	vprintf(fmt, ap);
138 	va_end(ap);
139 	puts(", skipping test");
140 }
141 
test_sysfs_path(const char * path)142 static bool test_sysfs_path(const char *path)
143 {
144 	struct stat statbuf;
145 	int ret;
146 
147 	ret = stat(path, &statbuf);
148 	TEST_ASSERT(ret == 0 || (ret == -1 && errno == ENOENT),
149 		    "Error in stat()ing '%s'", path);
150 
151 	return ret == 0;
152 }
153 
thp_configured(void)154 bool thp_configured(void)
155 {
156 	return test_sysfs_path("/sys/kernel/mm/transparent_hugepage");
157 }
158 
get_sysfs_val(const char * path)159 static size_t get_sysfs_val(const char *path)
160 {
161 	size_t size;
162 	FILE *f;
163 	int ret;
164 
165 	f = fopen(path, "r");
166 	TEST_ASSERT(f, "Error opening '%s'", path);
167 
168 	ret = fscanf(f, "%ld", &size);
169 	TEST_ASSERT(ret > 0, "Error reading '%s'", path);
170 
171 	/* Re-scan the input stream to verify the entire file was read. */
172 	ret = fscanf(f, "%ld", &size);
173 	TEST_ASSERT(ret < 1, "Error reading '%s'", path);
174 
175 	fclose(f);
176 	return size;
177 }
178 
get_trans_hugepagesz(void)179 size_t get_trans_hugepagesz(void)
180 {
181 	TEST_ASSERT(thp_configured(), "THP is not configured in host kernel");
182 
183 	return get_sysfs_val("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size");
184 }
185 
is_numa_balancing_enabled(void)186 bool is_numa_balancing_enabled(void)
187 {
188 	if (!test_sysfs_path("/proc/sys/kernel/numa_balancing"))
189 		return false;
190 	return get_sysfs_val("/proc/sys/kernel/numa_balancing") == 1;
191 }
192 
get_def_hugetlb_pagesz(void)193 size_t get_def_hugetlb_pagesz(void)
194 {
195 	char buf[64];
196 	const char *hugepagesize = "Hugepagesize:";
197 	const char *hugepages_total = "HugePages_Total:";
198 	FILE *f;
199 
200 	f = fopen("/proc/meminfo", "r");
201 	TEST_ASSERT(f != NULL, "Error in opening /proc/meminfo");
202 
203 	while (fgets(buf, sizeof(buf), f) != NULL) {
204 		if (strstr(buf, hugepages_total) == buf) {
205 			unsigned long long total = strtoull(buf + strlen(hugepages_total), NULL, 10);
206 			if (!total) {
207 				fprintf(stderr, "HUGETLB is not enabled in /proc/sys/vm/nr_hugepages\n");
208 				exit(KSFT_SKIP);
209 			}
210 		}
211 		if (strstr(buf, hugepagesize) == buf) {
212 			fclose(f);
213 			return strtoull(buf + strlen(hugepagesize), NULL, 10) << 10;
214 		}
215 	}
216 
217 	if (feof(f)) {
218 		fprintf(stderr, "HUGETLB is not configured in host kernel");
219 		exit(KSFT_SKIP);
220 	}
221 
222 	TEST_FAIL("Error in reading /proc/meminfo");
223 }
224 
225 #define ANON_FLAGS	(MAP_PRIVATE | MAP_ANONYMOUS)
226 #define ANON_HUGE_FLAGS	(ANON_FLAGS | MAP_HUGETLB)
227 
vm_mem_backing_src_alias(uint32_t i)228 const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(uint32_t i)
229 {
230 	static const struct vm_mem_backing_src_alias aliases[] = {
231 		[VM_MEM_SRC_ANONYMOUS] = {
232 			.name = "anonymous",
233 			.flag = ANON_FLAGS,
234 		},
235 		[VM_MEM_SRC_ANONYMOUS_THP] = {
236 			.name = "anonymous_thp",
237 			.flag = ANON_FLAGS,
238 		},
239 		[VM_MEM_SRC_ANONYMOUS_HUGETLB] = {
240 			.name = "anonymous_hugetlb",
241 			.flag = ANON_HUGE_FLAGS,
242 		},
243 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_16KB] = {
244 			.name = "anonymous_hugetlb_16kb",
245 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_16KB,
246 		},
247 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_64KB] = {
248 			.name = "anonymous_hugetlb_64kb",
249 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_64KB,
250 		},
251 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_512KB] = {
252 			.name = "anonymous_hugetlb_512kb",
253 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_512KB,
254 		},
255 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_1MB] = {
256 			.name = "anonymous_hugetlb_1mb",
257 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_1MB,
258 		},
259 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_2MB] = {
260 			.name = "anonymous_hugetlb_2mb",
261 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_2MB,
262 		},
263 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_8MB] = {
264 			.name = "anonymous_hugetlb_8mb",
265 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_8MB,
266 		},
267 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_16MB] = {
268 			.name = "anonymous_hugetlb_16mb",
269 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_16MB,
270 		},
271 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_32MB] = {
272 			.name = "anonymous_hugetlb_32mb",
273 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_32MB,
274 		},
275 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_256MB] = {
276 			.name = "anonymous_hugetlb_256mb",
277 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_256MB,
278 		},
279 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_512MB] = {
280 			.name = "anonymous_hugetlb_512mb",
281 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_512MB,
282 		},
283 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_1GB] = {
284 			.name = "anonymous_hugetlb_1gb",
285 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_1GB,
286 		},
287 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_2GB] = {
288 			.name = "anonymous_hugetlb_2gb",
289 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_2GB,
290 		},
291 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_16GB] = {
292 			.name = "anonymous_hugetlb_16gb",
293 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_16GB,
294 		},
295 		[VM_MEM_SRC_SHMEM] = {
296 			.name = "shmem",
297 			.flag = MAP_SHARED,
298 		},
299 		[VM_MEM_SRC_SHARED_HUGETLB] = {
300 			.name = "shared_hugetlb",
301 			/*
302 			 * No MAP_HUGETLB, we use MFD_HUGETLB instead. Since
303 			 * we're using "file backed" memory, we need to specify
304 			 * this when the FD is created, not when the area is
305 			 * mapped.
306 			 */
307 			.flag = MAP_SHARED,
308 		},
309 	};
310 	_Static_assert(ARRAY_SIZE(aliases) == NUM_SRC_TYPES,
311 		       "Missing new backing src types?");
312 
313 	TEST_ASSERT(i < NUM_SRC_TYPES, "Backing src type ID %d too big", i);
314 
315 	return &aliases[i];
316 }
317 
318 #define MAP_HUGE_PAGE_SIZE(x) (1ULL << ((x >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK))
319 
get_backing_src_pagesz(uint32_t i)320 size_t get_backing_src_pagesz(uint32_t i)
321 {
322 	uint32_t flag = vm_mem_backing_src_alias(i)->flag;
323 
324 	switch (i) {
325 	case VM_MEM_SRC_ANONYMOUS:
326 	case VM_MEM_SRC_SHMEM:
327 		return getpagesize();
328 	case VM_MEM_SRC_ANONYMOUS_THP:
329 		return get_trans_hugepagesz();
330 	case VM_MEM_SRC_ANONYMOUS_HUGETLB:
331 	case VM_MEM_SRC_SHARED_HUGETLB:
332 		return get_def_hugetlb_pagesz();
333 	default:
334 		return MAP_HUGE_PAGE_SIZE(flag);
335 	}
336 }
337 
is_backing_src_hugetlb(uint32_t i)338 bool is_backing_src_hugetlb(uint32_t i)
339 {
340 	return !!(vm_mem_backing_src_alias(i)->flag & MAP_HUGETLB);
341 }
342 
print_available_backing_src_types(const char * prefix)343 static void print_available_backing_src_types(const char *prefix)
344 {
345 	int i;
346 
347 	printf("%sAvailable backing src types:\n", prefix);
348 
349 	for (i = 0; i < NUM_SRC_TYPES; i++)
350 		printf("%s    %s\n", prefix, vm_mem_backing_src_alias(i)->name);
351 }
352 
backing_src_help(const char * flag)353 void backing_src_help(const char *flag)
354 {
355 	printf(" %s: specify the type of memory that should be used to\n"
356 	       "     back the guest data region. (default: %s)\n",
357 	       flag, vm_mem_backing_src_alias(DEFAULT_VM_MEM_SRC)->name);
358 	print_available_backing_src_types("     ");
359 }
360 
parse_backing_src_type(const char * type_name)361 enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name)
362 {
363 	int i;
364 
365 	for (i = 0; i < NUM_SRC_TYPES; i++)
366 		if (!strcmp(type_name, vm_mem_backing_src_alias(i)->name))
367 			return i;
368 
369 	print_available_backing_src_types("");
370 	TEST_FAIL("Unknown backing src type: %s", type_name);
371 	return -1;
372 }
373 
get_run_delay(void)374 long get_run_delay(void)
375 {
376 	char path[64];
377 	long val[2];
378 	FILE *fp;
379 
380 	sprintf(path, "/proc/%ld/schedstat", syscall(SYS_gettid));
381 	fp = fopen(path, "r");
382 	/* Return MIN_RUN_DELAY_NS upon failure just to be safe */
383 	if (fscanf(fp, "%ld %ld ", &val[0], &val[1]) < 2)
384 		val[1] = MIN_RUN_DELAY_NS;
385 	fclose(fp);
386 
387 	return val[1];
388 }
389 
atoi_paranoid(const char * num_str)390 int atoi_paranoid(const char *num_str)
391 {
392 	char *end_ptr;
393 	long num;
394 
395 	errno = 0;
396 	num = strtol(num_str, &end_ptr, 0);
397 	TEST_ASSERT(!errno, "strtol(\"%s\") failed", num_str);
398 	TEST_ASSERT(num_str != end_ptr,
399 		    "strtol(\"%s\") didn't find a valid integer.", num_str);
400 	TEST_ASSERT(*end_ptr == '\0',
401 		    "strtol(\"%s\") failed to parse trailing characters \"%s\".",
402 		    num_str, end_ptr);
403 	TEST_ASSERT(num >= INT_MIN && num <= INT_MAX,
404 		    "%ld not in range of [%d, %d]", num, INT_MIN, INT_MAX);
405 
406 	return num;
407 }
408 
strdup_printf(const char * fmt,...)409 char *strdup_printf(const char *fmt, ...)
410 {
411 	va_list ap;
412 	char *str;
413 
414 	va_start(ap, fmt);
415 	TEST_ASSERT(vasprintf(&str, fmt, ap) >= 0, "vasprintf() failed");
416 	va_end(ap);
417 
418 	return str;
419 }
420 
421 #define CLOCKSOURCE_PATH "/sys/devices/system/clocksource/clocksource0/current_clocksource"
422 
sys_get_cur_clocksource(void)423 char *sys_get_cur_clocksource(void)
424 {
425 	char *clk_name;
426 	struct stat st;
427 	FILE *fp;
428 
429 	fp = fopen(CLOCKSOURCE_PATH, "r");
430 	TEST_ASSERT(fp, "failed to open clocksource file, errno: %d", errno);
431 
432 	TEST_ASSERT(!fstat(fileno(fp), &st), "failed to stat clocksource file, errno: %d",
433 		    errno);
434 
435 	clk_name = malloc(st.st_size);
436 	TEST_ASSERT(clk_name, "failed to allocate buffer to read file");
437 
438 	TEST_ASSERT(fgets(clk_name, st.st_size, fp), "failed to read clocksource file: %d",
439 		    ferror(fp));
440 
441 	fclose(fp);
442 
443 	return clk_name;
444 }
445