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-or-later
2#include "tests/common.h"
3#include <string.h>
4#include <getopt.h>
5#include <linux/memory_hotplug.h>
6#include <linux/build_bug.h>
7
8#define INIT_MEMBLOCK_REGIONS 128
9#define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
10#define PREFIXES_MAX 15
11#define DELIM ": "
12
13static struct test_memory memory_block;
14static const char __maybe_unused *prefixes[PREFIXES_MAX];
15static int __maybe_unused nr_prefixes;
16
17static const char *short_opts = "mv";
18static const struct option long_opts[] = {
19 {"movable-node", 0, NULL, 'm'},
20 {"verbose", 0, NULL, 'v'},
21 {NULL, 0, NULL, 0}
22};
23
24static const char * const help_opts[] = {
25 "disallow allocations from regions marked as hotplugged\n\t\t\t"
26 "by simulating enabling the \"movable_node\" kernel\n\t\t\t"
27 "parameter",
28 "enable verbose output, which includes the name of the\n\t\t\t"
29 "memblock function being tested, the name of the test,\n\t\t\t"
30 "and whether the test passed or failed."
31};
32
33static int verbose;
34
35/* sets global variable returned by movable_node_is_enabled() stub */
36bool movable_node_enabled;
37
38void reset_memblock_regions(void)
39{
40 memset(memblock.memory.regions, 0,
41 memblock.memory.cnt * sizeof(struct memblock_region));
42 memblock.memory.cnt = 1;
43 memblock.memory.max = INIT_MEMBLOCK_REGIONS;
44 memblock.memory.total_size = 0;
45
46 memset(memblock.reserved.regions, 0,
47 memblock.reserved.cnt * sizeof(struct memblock_region));
48 memblock.reserved.cnt = 1;
49 memblock.reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS;
50 memblock.reserved.total_size = 0;
51}
52
53void reset_memblock_attributes(void)
54{
55 memblock.memory.name = "memory";
56 memblock.reserved.name = "reserved";
57 memblock.bottom_up = false;
58 memblock.current_limit = MEMBLOCK_ALLOC_ANYWHERE;
59}
60
61void setup_memblock(void)
62{
63 reset_memblock_regions();
64 memblock_add((phys_addr_t)memory_block.base, MEM_SIZE);
65}
66
67void dummy_physical_memory_init(void)
68{
69 memory_block.base = malloc(MEM_SIZE);
70 assert(memory_block.base);
71}
72
73void dummy_physical_memory_cleanup(void)
74{
75 free(memory_block.base);
76}
77
78static void usage(const char *prog)
79{
80 BUILD_BUG_ON(ARRAY_SIZE(help_opts) != ARRAY_SIZE(long_opts) - 1);
81
82 printf("Usage: %s [-%s]\n", prog, short_opts);
83
84 for (int i = 0; long_opts[i].name; i++) {
85 printf(" -%c, --%-12s\t%s\n", long_opts[i].val,
86 long_opts[i].name, help_opts[i]);
87 }
88
89 exit(1);
90}
91
92void parse_args(int argc, char **argv)
93{
94 int c;
95
96 while ((c = getopt_long_only(argc, argv, short_opts, long_opts,
97 NULL)) != -1) {
98 switch (c) {
99 case 'm':
100 movable_node_enabled = true;
101 break;
102 case 'v':
103 verbose = 1;
104 break;
105 default:
106 usage(argv[0]);
107 }
108 }
109}
110
111void print_prefixes(const char *postfix)
112{
113 for (int i = 0; i < nr_prefixes; i++)
114 test_print("%s%s", prefixes[i], DELIM);
115 test_print(postfix);
116}
117
118void test_fail(void)
119{
120 if (verbose) {
121 ksft_test_result_fail(": ");
122 print_prefixes("failed\n");
123 }
124}
125
126void test_pass(void)
127{
128 if (verbose) {
129 ksft_test_result_pass(": ");
130 print_prefixes("passed\n");
131 }
132}
133
134void test_print(const char *fmt, ...)
135{
136 if (verbose) {
137 int saved_errno = errno;
138 va_list args;
139
140 va_start(args, fmt);
141 errno = saved_errno;
142 vprintf(fmt, args);
143 va_end(args);
144 }
145}
146
147void prefix_reset(void)
148{
149 memset(prefixes, 0, PREFIXES_MAX * sizeof(char *));
150 nr_prefixes = 0;
151}
152
153void prefix_push(const char *prefix)
154{
155 assert(nr_prefixes < PREFIXES_MAX);
156 prefixes[nr_prefixes] = prefix;
157 nr_prefixes++;
158}
159
160void prefix_pop(void)
161{
162 if (nr_prefixes > 0) {
163 prefixes[nr_prefixes - 1] = 0;
164 nr_prefixes--;
165 }
166}