0001
0002 #include "tests/common.h"
0003 #include <string.h>
0004 #include <getopt.h>
0005 #include <linux/memory_hotplug.h>
0006 #include <linux/build_bug.h>
0007
0008 #define INIT_MEMBLOCK_REGIONS 128
0009 #define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
0010 #define PREFIXES_MAX 15
0011 #define DELIM ": "
0012
0013 static struct test_memory memory_block;
0014 static const char __maybe_unused *prefixes[PREFIXES_MAX];
0015 static int __maybe_unused nr_prefixes;
0016
0017 static const char *short_opts = "mv";
0018 static const struct option long_opts[] = {
0019 {"movable-node", 0, NULL, 'm'},
0020 {"verbose", 0, NULL, 'v'},
0021 {NULL, 0, NULL, 0}
0022 };
0023
0024 static const char * const help_opts[] = {
0025 "disallow allocations from regions marked as hotplugged\n\t\t\t"
0026 "by simulating enabling the \"movable_node\" kernel\n\t\t\t"
0027 "parameter",
0028 "enable verbose output, which includes the name of the\n\t\t\t"
0029 "memblock function being tested, the name of the test,\n\t\t\t"
0030 "and whether the test passed or failed."
0031 };
0032
0033 static int verbose;
0034
0035
0036 bool movable_node_enabled;
0037
0038 void reset_memblock_regions(void)
0039 {
0040 memset(memblock.memory.regions, 0,
0041 memblock.memory.cnt * sizeof(struct memblock_region));
0042 memblock.memory.cnt = 1;
0043 memblock.memory.max = INIT_MEMBLOCK_REGIONS;
0044 memblock.memory.total_size = 0;
0045
0046 memset(memblock.reserved.regions, 0,
0047 memblock.reserved.cnt * sizeof(struct memblock_region));
0048 memblock.reserved.cnt = 1;
0049 memblock.reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS;
0050 memblock.reserved.total_size = 0;
0051 }
0052
0053 void reset_memblock_attributes(void)
0054 {
0055 memblock.memory.name = "memory";
0056 memblock.reserved.name = "reserved";
0057 memblock.bottom_up = false;
0058 memblock.current_limit = MEMBLOCK_ALLOC_ANYWHERE;
0059 }
0060
0061 void setup_memblock(void)
0062 {
0063 reset_memblock_regions();
0064 memblock_add((phys_addr_t)memory_block.base, MEM_SIZE);
0065 }
0066
0067 void dummy_physical_memory_init(void)
0068 {
0069 memory_block.base = malloc(MEM_SIZE);
0070 assert(memory_block.base);
0071 }
0072
0073 void dummy_physical_memory_cleanup(void)
0074 {
0075 free(memory_block.base);
0076 }
0077
0078 static void usage(const char *prog)
0079 {
0080 BUILD_BUG_ON(ARRAY_SIZE(help_opts) != ARRAY_SIZE(long_opts) - 1);
0081
0082 printf("Usage: %s [-%s]\n", prog, short_opts);
0083
0084 for (int i = 0; long_opts[i].name; i++) {
0085 printf(" -%c, --%-12s\t%s\n", long_opts[i].val,
0086 long_opts[i].name, help_opts[i]);
0087 }
0088
0089 exit(1);
0090 }
0091
0092 void parse_args(int argc, char **argv)
0093 {
0094 int c;
0095
0096 while ((c = getopt_long_only(argc, argv, short_opts, long_opts,
0097 NULL)) != -1) {
0098 switch (c) {
0099 case 'm':
0100 movable_node_enabled = true;
0101 break;
0102 case 'v':
0103 verbose = 1;
0104 break;
0105 default:
0106 usage(argv[0]);
0107 }
0108 }
0109 }
0110
0111 void print_prefixes(const char *postfix)
0112 {
0113 for (int i = 0; i < nr_prefixes; i++)
0114 test_print("%s%s", prefixes[i], DELIM);
0115 test_print(postfix);
0116 }
0117
0118 void test_fail(void)
0119 {
0120 if (verbose) {
0121 ksft_test_result_fail(": ");
0122 print_prefixes("failed\n");
0123 }
0124 }
0125
0126 void test_pass(void)
0127 {
0128 if (verbose) {
0129 ksft_test_result_pass(": ");
0130 print_prefixes("passed\n");
0131 }
0132 }
0133
0134 void test_print(const char *fmt, ...)
0135 {
0136 if (verbose) {
0137 int saved_errno = errno;
0138 va_list args;
0139
0140 va_start(args, fmt);
0141 errno = saved_errno;
0142 vprintf(fmt, args);
0143 va_end(args);
0144 }
0145 }
0146
0147 void prefix_reset(void)
0148 {
0149 memset(prefixes, 0, PREFIXES_MAX * sizeof(char *));
0150 nr_prefixes = 0;
0151 }
0152
0153 void prefix_push(const char *prefix)
0154 {
0155 assert(nr_prefixes < PREFIXES_MAX);
0156 prefixes[nr_prefixes] = prefix;
0157 nr_prefixes++;
0158 }
0159
0160 void prefix_pop(void)
0161 {
0162 if (nr_prefixes > 0) {
0163 prefixes[nr_prefixes - 1] = 0;
0164 nr_prefixes--;
0165 }
0166 }