Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 */
20size_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
58int64_t timespec_to_ns(struct timespec ts)
59{
60 return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec;
61}
62
63struct 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
74struct 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
81struct 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
88struct 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
96struct 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
103void 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
114const 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
120void 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
129enum 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}