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