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