1 // SPDX-License-Identifier: GPL-2.0-or-later
2 #include "tests/common.h"
5 #include <linux/memory_hotplug.h>
6 #include <linux/build_bug.h>
8 #define PREFIXES_MAX 15
12 static struct test_memory memory_block
;
13 static const char __maybe_unused
*prefixes
[PREFIXES_MAX
];
14 static int __maybe_unused nr_prefixes
;
16 static const char *short_opts
= "hmv";
17 static const struct option long_opts
[] = {
18 {"help", 0, NULL
, 'h'},
19 {"movable-node", 0, NULL
, 'm'},
20 {"verbose", 0, NULL
, 'v'},
24 static const char * const help_opts
[] = {
25 "display this help message and exit",
26 "disallow allocations from regions marked as hotplugged\n\t\t\t"
27 "by simulating enabling the \"movable_node\" kernel\n\t\t\t"
29 "enable verbose output, which includes the name of the\n\t\t\t"
30 "memblock function being tested, the name of the test,\n\t\t\t"
31 "and whether the test passed or failed."
36 /* sets global variable returned by movable_node_is_enabled() stub */
37 bool movable_node_enabled
;
39 void reset_memblock_regions(void)
41 memset(memblock
.memory
.regions
, 0,
42 memblock
.memory
.cnt
* sizeof(struct memblock_region
));
43 memblock
.memory
.cnt
= 0;
44 memblock
.memory
.max
= INIT_MEMBLOCK_REGIONS
;
45 memblock
.memory
.total_size
= 0;
47 memset(memblock
.reserved
.regions
, 0,
48 memblock
.reserved
.cnt
* sizeof(struct memblock_region
));
49 memblock
.reserved
.cnt
= 0;
50 memblock
.reserved
.max
= INIT_MEMBLOCK_RESERVED_REGIONS
;
51 memblock
.reserved
.total_size
= 0;
54 void reset_memblock_attributes(void)
56 memblock
.memory
.name
= "memory";
57 memblock
.reserved
.name
= "reserved";
58 memblock
.bottom_up
= false;
59 memblock
.current_limit
= MEMBLOCK_ALLOC_ANYWHERE
;
62 static inline void fill_memblock(void)
64 memset(memory_block
.base
, 1, PHYS_MEM_SIZE
);
67 void setup_memblock(void)
69 reset_memblock_regions();
70 memblock_add((phys_addr_t
)memory_block
.base
, MEM_SIZE
);
75 * setup_numa_memblock:
76 * Set up a memory layout with multiple NUMA nodes in a previously allocated
77 * dummy physical memory.
78 * @node_fracs: an array representing the fraction of MEM_SIZE contained in
79 * each node in basis point units (one hundredth of 1% or 1/10000).
80 * For example, if node 0 should contain 1/8 of MEM_SIZE,
81 * node_fracs[0] = 1250.
83 * The nids will be set to 0 through NUMA_NODES - 1.
85 void setup_numa_memblock(const unsigned int node_fracs
[])
90 reset_memblock_regions();
91 base
= (phys_addr_t
)memory_block
.base
;
92 flags
= (movable_node_is_enabled()) ? MEMBLOCK_NONE
: MEMBLOCK_HOTPLUG
;
94 for (int i
= 0; i
< NUMA_NODES
; i
++) {
95 assert(node_fracs
[i
] <= BASIS
);
96 phys_addr_t size
= MEM_SIZE
* node_fracs
[i
] / BASIS
;
98 memblock_add_node(base
, size
, i
, flags
);
104 void dummy_physical_memory_init(void)
106 memory_block
.base
= malloc(PHYS_MEM_SIZE
);
107 assert(memory_block
.base
);
111 void dummy_physical_memory_cleanup(void)
113 free(memory_block
.base
);
116 phys_addr_t
dummy_physical_memory_base(void)
118 return (phys_addr_t
)memory_block
.base
;
121 static void usage(const char *prog
)
123 BUILD_BUG_ON(ARRAY_SIZE(help_opts
) != ARRAY_SIZE(long_opts
) - 1);
125 printf("Usage: %s [-%s]\n", prog
, short_opts
);
127 for (int i
= 0; long_opts
[i
].name
; i
++) {
128 printf(" -%c, --%-12s\t%s\n", long_opts
[i
].val
,
129 long_opts
[i
].name
, help_opts
[i
]);
135 void parse_args(int argc
, char **argv
)
139 while ((c
= getopt_long_only(argc
, argv
, short_opts
, long_opts
,
143 movable_node_enabled
= true;
154 void print_prefixes(const char *postfix
)
156 for (int i
= 0; i
< nr_prefixes
; i
++)
157 test_print("%s%s", prefixes
[i
], DELIM
);
164 ksft_test_result_fail(": ");
165 print_prefixes("failed\n");
172 ksft_test_result_pass(": ");
173 print_prefixes("passed\n");
177 void test_print(const char *fmt
, ...)
180 int saved_errno
= errno
;
190 void prefix_reset(void)
192 memset(prefixes
, 0, PREFIXES_MAX
* sizeof(char *));
196 void prefix_push(const char *prefix
)
198 assert(nr_prefixes
< PREFIXES_MAX
);
199 prefixes
[nr_prefixes
] = prefix
;
203 void prefix_pop(void)
205 if (nr_prefixes
> 0) {
206 prefixes
[nr_prefixes
- 1] = 0;