test_util.c 9.8 KB

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