test_util.c 10 KB

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