xref: /openbmc/linux/tools/testing/selftests/kvm/lib/test_util.c (revision 8a511e7efc5a72173f64d191f01cda236d54e27a)
1af99e1adSBen Gardon // SPDX-License-Identifier: GPL-2.0-only
2af99e1adSBen Gardon /*
3af99e1adSBen Gardon  * tools/testing/selftests/kvm/lib/test_util.c
4af99e1adSBen Gardon  *
5af99e1adSBen Gardon  * Copyright (C) 2020, Google LLC.
6af99e1adSBen Gardon  */
71eafbd27SBen Gardon 
8dfaf20afSAndrew Jones #define _GNU_SOURCE
9dfaf20afSAndrew Jones #include <stdio.h>
10dfaf20afSAndrew Jones #include <stdarg.h>
111eafbd27SBen Gardon #include <assert.h>
12af99e1adSBen Gardon #include <ctype.h>
13af99e1adSBen Gardon #include <limits.h>
141eafbd27SBen Gardon #include <stdlib.h>
151eafbd27SBen Gardon #include <time.h>
163b70c4d1SYanan Wang #include <sys/stat.h>
1720175d5eSShuah Khan #include <sys/syscall.h>
18623653b7SYanan Wang #include <linux/mman.h>
199e965bb7SBen Gardon #include "linux/kernel.h"
201eafbd27SBen Gardon 
21af99e1adSBen Gardon #include "test_util.h"
22af99e1adSBen Gardon 
23af99e1adSBen Gardon /*
24b31f21a7SColton Lewis  * Random number generator that is usable from guest code. This is the
25b31f21a7SColton Lewis  * Park-Miller LCG using standard constants.
26b31f21a7SColton Lewis  */
27b31f21a7SColton Lewis 
new_guest_random_state(uint32_t seed)28b31f21a7SColton Lewis struct guest_random_state new_guest_random_state(uint32_t seed)
29b31f21a7SColton Lewis {
30b31f21a7SColton Lewis 	struct guest_random_state s = {.seed = seed};
31b31f21a7SColton Lewis 	return s;
32b31f21a7SColton Lewis }
33b31f21a7SColton Lewis 
guest_random_u32(struct guest_random_state * state)34b31f21a7SColton Lewis uint32_t guest_random_u32(struct guest_random_state *state)
35b31f21a7SColton Lewis {
36b31f21a7SColton Lewis 	state->seed = (uint64_t)state->seed * 48271 % ((uint32_t)(1 << 31) - 1);
37b31f21a7SColton Lewis 	return state->seed;
38b31f21a7SColton Lewis }
39b31f21a7SColton Lewis 
40b31f21a7SColton Lewis /*
41af99e1adSBen Gardon  * Parses "[0-9]+[kmgt]?".
42af99e1adSBen Gardon  */
parse_size(const char * size)43af99e1adSBen Gardon size_t parse_size(const char *size)
44af99e1adSBen Gardon {
45af99e1adSBen Gardon 	size_t base;
46af99e1adSBen Gardon 	char *scale;
47af99e1adSBen Gardon 	int shift = 0;
48af99e1adSBen Gardon 
49af99e1adSBen Gardon 	TEST_ASSERT(size && isdigit(size[0]), "Need at least one digit in '%s'", size);
50af99e1adSBen Gardon 
51af99e1adSBen Gardon 	base = strtoull(size, &scale, 0);
52af99e1adSBen Gardon 
53af99e1adSBen Gardon 	TEST_ASSERT(base != ULLONG_MAX, "Overflow parsing size!");
54af99e1adSBen Gardon 
55af99e1adSBen Gardon 	switch (tolower(*scale)) {
56af99e1adSBen Gardon 	case 't':
57af99e1adSBen Gardon 		shift = 40;
58af99e1adSBen Gardon 		break;
59af99e1adSBen Gardon 	case 'g':
60af99e1adSBen Gardon 		shift = 30;
61af99e1adSBen Gardon 		break;
62af99e1adSBen Gardon 	case 'm':
63af99e1adSBen Gardon 		shift = 20;
64af99e1adSBen Gardon 		break;
65af99e1adSBen Gardon 	case 'k':
66af99e1adSBen Gardon 		shift = 10;
67af99e1adSBen Gardon 		break;
68af99e1adSBen Gardon 	case 'b':
69af99e1adSBen Gardon 	case '\0':
70af99e1adSBen Gardon 		shift = 0;
71af99e1adSBen Gardon 		break;
72af99e1adSBen Gardon 	default:
73af99e1adSBen Gardon 		TEST_ASSERT(false, "Unknown size letter %c", *scale);
74af99e1adSBen Gardon 	}
75af99e1adSBen Gardon 
76af99e1adSBen Gardon 	TEST_ASSERT((base << shift) >> shift == base, "Overflow scaling size!");
77af99e1adSBen Gardon 
78af99e1adSBen Gardon 	return base << shift;
79af99e1adSBen Gardon }
80f09205b9SBen Gardon 
timespec_to_ns(struct timespec ts)81f09205b9SBen Gardon int64_t timespec_to_ns(struct timespec ts)
82f09205b9SBen Gardon {
83f09205b9SBen Gardon 	return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec;
84f09205b9SBen Gardon }
85f09205b9SBen Gardon 
timespec_add_ns(struct timespec ts,int64_t ns)8694c4b76bSAndrew Jones struct timespec timespec_add_ns(struct timespec ts, int64_t ns)
8794c4b76bSAndrew Jones {
8894c4b76bSAndrew Jones 	struct timespec res;
8994c4b76bSAndrew Jones 
9094c4b76bSAndrew Jones 	res.tv_nsec = ts.tv_nsec + ns;
91bfcaa849SAndrew Jones 	res.tv_sec = ts.tv_sec + res.tv_nsec / 1000000000LL;
92bfcaa849SAndrew Jones 	res.tv_nsec %= 1000000000LL;
9394c4b76bSAndrew Jones 
9494c4b76bSAndrew Jones 	return res;
9594c4b76bSAndrew Jones }
9694c4b76bSAndrew Jones 
timespec_add(struct timespec ts1,struct timespec ts2)97bfcaa849SAndrew Jones struct timespec timespec_add(struct timespec ts1, struct timespec ts2)
98bfcaa849SAndrew Jones {
99bfcaa849SAndrew Jones 	int64_t ns1 = timespec_to_ns(ts1);
100bfcaa849SAndrew Jones 	int64_t ns2 = timespec_to_ns(ts2);
101bfcaa849SAndrew Jones 	return timespec_add_ns((struct timespec){0}, ns1 + ns2);
102bfcaa849SAndrew Jones }
103bfcaa849SAndrew Jones 
timespec_sub(struct timespec ts1,struct timespec ts2)104bfcaa849SAndrew Jones struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)
105bfcaa849SAndrew Jones {
106bfcaa849SAndrew Jones 	int64_t ns1 = timespec_to_ns(ts1);
107bfcaa849SAndrew Jones 	int64_t ns2 = timespec_to_ns(ts2);
108bfcaa849SAndrew Jones 	return timespec_add_ns((struct timespec){0}, ns1 - ns2);
109bfcaa849SAndrew Jones }
110bfcaa849SAndrew Jones 
timespec_elapsed(struct timespec start)111f9224a52SBen Gardon struct timespec timespec_elapsed(struct timespec start)
1121eafbd27SBen Gardon {
1131eafbd27SBen Gardon 	struct timespec end;
1141eafbd27SBen Gardon 
1151eafbd27SBen Gardon 	clock_gettime(CLOCK_MONOTONIC, &end);
1161eafbd27SBen Gardon 	return timespec_sub(end, start);
1171eafbd27SBen Gardon }
1181eafbd27SBen Gardon 
timespec_div(struct timespec ts,int divisor)1194fd94ec7SBen Gardon struct timespec timespec_div(struct timespec ts, int divisor)
1204fd94ec7SBen Gardon {
1214fd94ec7SBen Gardon 	int64_t ns = timespec_to_ns(ts) / divisor;
1224fd94ec7SBen Gardon 
1234fd94ec7SBen Gardon 	return timespec_add_ns((struct timespec){0}, ns);
1244fd94ec7SBen Gardon }
1254fd94ec7SBen Gardon 
print_skip(const char * fmt,...)126d0aac332SAndrew Jones void print_skip(const char *fmt, ...)
127d0aac332SAndrew Jones {
128d0aac332SAndrew Jones 	va_list ap;
129d0aac332SAndrew Jones 
130d0aac332SAndrew Jones 	assert(fmt);
131d0aac332SAndrew Jones 	va_start(ap, fmt);
132d0aac332SAndrew Jones 	vprintf(fmt, ap);
133d0aac332SAndrew Jones 	va_end(ap);
134d0aac332SAndrew Jones 	puts(", skipping test");
135d0aac332SAndrew Jones }
1369e965bb7SBen Gardon 
thp_configured(void)1373b70c4d1SYanan Wang bool thp_configured(void)
1383b70c4d1SYanan Wang {
1393b70c4d1SYanan Wang 	int ret;
1403b70c4d1SYanan Wang 	struct stat statbuf;
1413b70c4d1SYanan Wang 
1423b70c4d1SYanan Wang 	ret = stat("/sys/kernel/mm/transparent_hugepage", &statbuf);
1433b70c4d1SYanan Wang 	TEST_ASSERT(ret == 0 || (ret == -1 && errno == ENOENT),
1443b70c4d1SYanan Wang 		    "Error in stating /sys/kernel/mm/transparent_hugepage");
1453b70c4d1SYanan Wang 
1463b70c4d1SYanan Wang 	return ret == 0;
1473b70c4d1SYanan Wang }
1483b70c4d1SYanan Wang 
get_trans_hugepagesz(void)1493b70c4d1SYanan Wang size_t get_trans_hugepagesz(void)
1503b70c4d1SYanan Wang {
1513b70c4d1SYanan Wang 	size_t size;
1523b70c4d1SYanan Wang 	FILE *f;
1533a4f0cc6SShuah Khan 	int ret;
1543b70c4d1SYanan Wang 
1553b70c4d1SYanan Wang 	TEST_ASSERT(thp_configured(), "THP is not configured in host kernel");
1563b70c4d1SYanan Wang 
1573b70c4d1SYanan Wang 	f = fopen("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", "r");
1583b70c4d1SYanan Wang 	TEST_ASSERT(f != NULL, "Error in opening transparent_hugepage/hpage_pmd_size");
1593b70c4d1SYanan Wang 
1603a4f0cc6SShuah Khan 	ret = fscanf(f, "%ld", &size);
1613a4f0cc6SShuah Khan 	ret = fscanf(f, "%ld", &size);
1623a4f0cc6SShuah Khan 	TEST_ASSERT(ret < 1, "Error reading transparent_hugepage/hpage_pmd_size");
1633b70c4d1SYanan Wang 	fclose(f);
1643b70c4d1SYanan Wang 
1653b70c4d1SYanan Wang 	return size;
1663b70c4d1SYanan Wang }
1673b70c4d1SYanan Wang 
get_def_hugetlb_pagesz(void)1685579fa68SYanan Wang size_t get_def_hugetlb_pagesz(void)
1695579fa68SYanan Wang {
1705579fa68SYanan Wang 	char buf[64];
1713dc40cf8SPaolo Bonzini 	const char *hugepagesize = "Hugepagesize:";
1723dc40cf8SPaolo Bonzini 	const char *hugepages_total = "HugePages_Total:";
1735579fa68SYanan Wang 	FILE *f;
1745579fa68SYanan Wang 
1755579fa68SYanan Wang 	f = fopen("/proc/meminfo", "r");
1765579fa68SYanan Wang 	TEST_ASSERT(f != NULL, "Error in opening /proc/meminfo");
1775579fa68SYanan Wang 
1785579fa68SYanan Wang 	while (fgets(buf, sizeof(buf), f) != NULL) {
1793dc40cf8SPaolo Bonzini 		if (strstr(buf, hugepages_total) == buf) {
1803dc40cf8SPaolo Bonzini 			unsigned long long total = strtoull(buf + strlen(hugepages_total), NULL, 10);
1813dc40cf8SPaolo Bonzini 			if (!total) {
1823dc40cf8SPaolo Bonzini 				fprintf(stderr, "HUGETLB is not enabled in /proc/sys/vm/nr_hugepages\n");
1833dc40cf8SPaolo Bonzini 				exit(KSFT_SKIP);
1843dc40cf8SPaolo Bonzini 			}
1853dc40cf8SPaolo Bonzini 		}
1863dc40cf8SPaolo Bonzini 		if (strstr(buf, hugepagesize) == buf) {
1875579fa68SYanan Wang 			fclose(f);
1883dc40cf8SPaolo Bonzini 			return strtoull(buf + strlen(hugepagesize), NULL, 10) << 10;
1895579fa68SYanan Wang 		}
1905579fa68SYanan Wang 	}
1915579fa68SYanan Wang 
1923dc40cf8SPaolo Bonzini 	if (feof(f)) {
1933dc40cf8SPaolo Bonzini 		fprintf(stderr, "HUGETLB is not configured in host kernel");
1943dc40cf8SPaolo Bonzini 		exit(KSFT_SKIP);
1953dc40cf8SPaolo Bonzini 	}
1963dc40cf8SPaolo Bonzini 
1975579fa68SYanan Wang 	TEST_FAIL("Error in reading /proc/meminfo");
1985579fa68SYanan Wang }
1995579fa68SYanan Wang 
20095bf69b4SYanan Wang #define ANON_FLAGS	(MAP_PRIVATE | MAP_ANONYMOUS)
20195bf69b4SYanan Wang #define ANON_HUGE_FLAGS	(ANON_FLAGS | MAP_HUGETLB)
20295bf69b4SYanan Wang 
vm_mem_backing_src_alias(uint32_t i)203623653b7SYanan Wang const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(uint32_t i)
204623653b7SYanan Wang {
205623653b7SYanan Wang 	static const struct vm_mem_backing_src_alias aliases[] = {
206623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS] = {
207623653b7SYanan Wang 			.name = "anonymous",
20895bf69b4SYanan Wang 			.flag = ANON_FLAGS,
209623653b7SYanan Wang 		},
210623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_THP] = {
211623653b7SYanan Wang 			.name = "anonymous_thp",
21295bf69b4SYanan Wang 			.flag = ANON_FLAGS,
213623653b7SYanan Wang 		},
214623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB] = {
215623653b7SYanan Wang 			.name = "anonymous_hugetlb",
21695bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS,
217623653b7SYanan Wang 		},
218623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_16KB] = {
219623653b7SYanan Wang 			.name = "anonymous_hugetlb_16kb",
22095bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_16KB,
221623653b7SYanan Wang 		},
222623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_64KB] = {
223623653b7SYanan Wang 			.name = "anonymous_hugetlb_64kb",
22495bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_64KB,
225623653b7SYanan Wang 		},
226623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_512KB] = {
227623653b7SYanan Wang 			.name = "anonymous_hugetlb_512kb",
22895bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_512KB,
229623653b7SYanan Wang 		},
230623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_1MB] = {
231623653b7SYanan Wang 			.name = "anonymous_hugetlb_1mb",
23295bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_1MB,
233623653b7SYanan Wang 		},
234623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_2MB] = {
235623653b7SYanan Wang 			.name = "anonymous_hugetlb_2mb",
23695bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_2MB,
237623653b7SYanan Wang 		},
238623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_8MB] = {
239623653b7SYanan Wang 			.name = "anonymous_hugetlb_8mb",
24095bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_8MB,
241623653b7SYanan Wang 		},
242623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_16MB] = {
243623653b7SYanan Wang 			.name = "anonymous_hugetlb_16mb",
24495bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_16MB,
245623653b7SYanan Wang 		},
246623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_32MB] = {
247623653b7SYanan Wang 			.name = "anonymous_hugetlb_32mb",
24895bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_32MB,
249623653b7SYanan Wang 		},
250623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_256MB] = {
251623653b7SYanan Wang 			.name = "anonymous_hugetlb_256mb",
25295bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_256MB,
253623653b7SYanan Wang 		},
254623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_512MB] = {
255623653b7SYanan Wang 			.name = "anonymous_hugetlb_512mb",
25695bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_512MB,
257623653b7SYanan Wang 		},
258623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_1GB] = {
259623653b7SYanan Wang 			.name = "anonymous_hugetlb_1gb",
26095bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_1GB,
261623653b7SYanan Wang 		},
262623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_2GB] = {
263623653b7SYanan Wang 			.name = "anonymous_hugetlb_2gb",
26495bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_2GB,
265623653b7SYanan Wang 		},
266623653b7SYanan Wang 		[VM_MEM_SRC_ANONYMOUS_HUGETLB_16GB] = {
267623653b7SYanan Wang 			.name = "anonymous_hugetlb_16gb",
26895bf69b4SYanan Wang 			.flag = ANON_HUGE_FLAGS | MAP_HUGE_16GB,
269623653b7SYanan Wang 		},
270c9befd59SAxel Rasmussen 		[VM_MEM_SRC_SHMEM] = {
271c9befd59SAxel Rasmussen 			.name = "shmem",
272c9befd59SAxel Rasmussen 			.flag = MAP_SHARED,
273c9befd59SAxel Rasmussen 		},
27433090a88SAxel Rasmussen 		[VM_MEM_SRC_SHARED_HUGETLB] = {
27533090a88SAxel Rasmussen 			.name = "shared_hugetlb",
27633090a88SAxel Rasmussen 			/*
27733090a88SAxel Rasmussen 			 * No MAP_HUGETLB, we use MFD_HUGETLB instead. Since
27833090a88SAxel Rasmussen 			 * we're using "file backed" memory, we need to specify
27933090a88SAxel Rasmussen 			 * this when the FD is created, not when the area is
28033090a88SAxel Rasmussen 			 * mapped.
28133090a88SAxel Rasmussen 			 */
28233090a88SAxel Rasmussen 			.flag = MAP_SHARED,
28333090a88SAxel Rasmussen 		},
284623653b7SYanan Wang 	};
285623653b7SYanan Wang 	_Static_assert(ARRAY_SIZE(aliases) == NUM_SRC_TYPES,
286623653b7SYanan Wang 		       "Missing new backing src types?");
287623653b7SYanan Wang 
288623653b7SYanan Wang 	TEST_ASSERT(i < NUM_SRC_TYPES, "Backing src type ID %d too big", i);
289623653b7SYanan Wang 
290623653b7SYanan Wang 	return &aliases[i];
291623653b7SYanan Wang }
292623653b7SYanan Wang 
293623653b7SYanan Wang #define MAP_HUGE_PAGE_SIZE(x) (1ULL << ((x >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK))
294623653b7SYanan Wang 
get_backing_src_pagesz(uint32_t i)295623653b7SYanan Wang size_t get_backing_src_pagesz(uint32_t i)
296623653b7SYanan Wang {
297623653b7SYanan Wang 	uint32_t flag = vm_mem_backing_src_alias(i)->flag;
298623653b7SYanan Wang 
299623653b7SYanan Wang 	switch (i) {
300623653b7SYanan Wang 	case VM_MEM_SRC_ANONYMOUS:
301c9befd59SAxel Rasmussen 	case VM_MEM_SRC_SHMEM:
302623653b7SYanan Wang 		return getpagesize();
303623653b7SYanan Wang 	case VM_MEM_SRC_ANONYMOUS_THP:
304623653b7SYanan Wang 		return get_trans_hugepagesz();
305623653b7SYanan Wang 	case VM_MEM_SRC_ANONYMOUS_HUGETLB:
30633090a88SAxel Rasmussen 	case VM_MEM_SRC_SHARED_HUGETLB:
307623653b7SYanan Wang 		return get_def_hugetlb_pagesz();
308623653b7SYanan Wang 	default:
309623653b7SYanan Wang 		return MAP_HUGE_PAGE_SIZE(flag);
310623653b7SYanan Wang 	}
311623653b7SYanan Wang }
312623653b7SYanan Wang 
is_backing_src_hugetlb(uint32_t i)313f4870ef3SSean Christopherson bool is_backing_src_hugetlb(uint32_t i)
314f4870ef3SSean Christopherson {
315f4870ef3SSean Christopherson 	return !!(vm_mem_backing_src_alias(i)->flag & MAP_HUGETLB);
316f4870ef3SSean Christopherson }
317f4870ef3SSean Christopherson 
print_available_backing_src_types(const char * prefix)3189f2fc555SDavid Matlack static void print_available_backing_src_types(const char *prefix)
3199e965bb7SBen Gardon {
3209e965bb7SBen Gardon 	int i;
3219e965bb7SBen Gardon 
3229f2fc555SDavid Matlack 	printf("%sAvailable backing src types:\n", prefix);
3239f2fc555SDavid Matlack 
324623653b7SYanan Wang 	for (i = 0; i < NUM_SRC_TYPES; i++)
3259f2fc555SDavid Matlack 		printf("%s    %s\n", prefix, vm_mem_backing_src_alias(i)->name);
3269f2fc555SDavid Matlack }
3279f2fc555SDavid Matlack 
backing_src_help(const char * flag)3289f2fc555SDavid Matlack void backing_src_help(const char *flag)
3299f2fc555SDavid Matlack {
3309f2fc555SDavid Matlack 	printf(" %s: specify the type of memory that should be used to\n"
3319f2fc555SDavid Matlack 	       "     back the guest data region. (default: %s)\n",
3329f2fc555SDavid Matlack 	       flag, vm_mem_backing_src_alias(DEFAULT_VM_MEM_SRC)->name);
3339f2fc555SDavid Matlack 	print_available_backing_src_types("     ");
3349e965bb7SBen Gardon }
3359e965bb7SBen Gardon 
parse_backing_src_type(const char * type_name)3369e965bb7SBen Gardon enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name)
3379e965bb7SBen Gardon {
3389e965bb7SBen Gardon 	int i;
3399e965bb7SBen Gardon 
340623653b7SYanan Wang 	for (i = 0; i < NUM_SRC_TYPES; i++)
341623653b7SYanan Wang 		if (!strcmp(type_name, vm_mem_backing_src_alias(i)->name))
342623653b7SYanan Wang 			return i;
3439e965bb7SBen Gardon 
3449f2fc555SDavid Matlack 	print_available_backing_src_types("");
3459e965bb7SBen Gardon 	TEST_FAIL("Unknown backing src type: %s", type_name);
3469e965bb7SBen Gardon 	return -1;
3479e965bb7SBen Gardon }
34820175d5eSShuah Khan 
get_run_delay(void)34920175d5eSShuah Khan long get_run_delay(void)
35020175d5eSShuah Khan {
35120175d5eSShuah Khan 	char path[64];
35220175d5eSShuah Khan 	long val[2];
35320175d5eSShuah Khan 	FILE *fp;
35420175d5eSShuah Khan 
35520175d5eSShuah Khan 	sprintf(path, "/proc/%ld/schedstat", syscall(SYS_gettid));
35620175d5eSShuah Khan 	fp = fopen(path, "r");
357f5013d41SShuah Khan 	/* Return MIN_RUN_DELAY_NS upon failure just to be safe */
358f5013d41SShuah Khan 	if (fscanf(fp, "%ld %ld ", &val[0], &val[1]) < 2)
359f5013d41SShuah Khan 		val[1] = MIN_RUN_DELAY_NS;
36020175d5eSShuah Khan 	fclose(fp);
36120175d5eSShuah Khan 
36220175d5eSShuah Khan 	return val[1];
36320175d5eSShuah Khan }
364018ea2d7SVipin Sharma 
atoi_paranoid(const char * num_str)365018ea2d7SVipin Sharma int atoi_paranoid(const char *num_str)
366018ea2d7SVipin Sharma {
367018ea2d7SVipin Sharma 	char *end_ptr;
368018ea2d7SVipin Sharma 	long num;
369018ea2d7SVipin Sharma 
370018ea2d7SVipin Sharma 	errno = 0;
371018ea2d7SVipin Sharma 	num = strtol(num_str, &end_ptr, 0);
372018ea2d7SVipin Sharma 	TEST_ASSERT(!errno, "strtol(\"%s\") failed", num_str);
373018ea2d7SVipin Sharma 	TEST_ASSERT(num_str != end_ptr,
374018ea2d7SVipin Sharma 		    "strtol(\"%s\") didn't find a valid integer.", num_str);
375018ea2d7SVipin Sharma 	TEST_ASSERT(*end_ptr == '\0',
376018ea2d7SVipin Sharma 		    "strtol(\"%s\") failed to parse trailing characters \"%s\".",
377018ea2d7SVipin Sharma 		    num_str, end_ptr);
378018ea2d7SVipin Sharma 	TEST_ASSERT(num >= INT_MIN && num <= INT_MAX,
379018ea2d7SVipin Sharma 		    "%ld not in range of [%d, %d]", num, INT_MIN, INT_MAX);
380018ea2d7SVipin Sharma 
381018ea2d7SVipin Sharma 	return num;
382018ea2d7SVipin Sharma }
383dfaf20afSAndrew Jones 
strdup_printf(const char * fmt,...)384dfaf20afSAndrew Jones char *strdup_printf(const char *fmt, ...)
385dfaf20afSAndrew Jones {
386dfaf20afSAndrew Jones 	va_list ap;
387dfaf20afSAndrew Jones 	char *str;
388dfaf20afSAndrew Jones 
389dfaf20afSAndrew Jones 	va_start(ap, fmt);
390*7c329bbdSSean Christopherson 	TEST_ASSERT(vasprintf(&str, fmt, ap) >= 0, "vasprintf() failed");
391dfaf20afSAndrew Jones 	va_end(ap);
392dfaf20afSAndrew Jones 
393dfaf20afSAndrew Jones 	return str;
394dfaf20afSAndrew Jones }
395