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 13 static struct test_memory memory_block; 14 static const char __maybe_unused *prefixes[PREFIXES_MAX]; 15 static int __maybe_unused nr_prefixes; 16 17 static const char *short_opts = "mv"; 18 static const struct option long_opts[] = { 19 {"movable-node", 0, NULL, 'm'}, 20 {"verbose", 0, NULL, 'v'}, 21 {NULL, 0, NULL, 0} 22 }; 23 24 static 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 33 static int verbose; 34 35 /* sets global variable returned by movable_node_is_enabled() stub */ 36 bool movable_node_enabled; 37 38 void 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 53 void 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 61 void setup_memblock(void) 62 { 63 reset_memblock_regions(); 64 memblock_add((phys_addr_t)memory_block.base, MEM_SIZE); 65 } 66 67 void dummy_physical_memory_init(void) 68 { 69 memory_block.base = malloc(MEM_SIZE); 70 assert(memory_block.base); 71 } 72 73 void dummy_physical_memory_cleanup(void) 74 { 75 free(memory_block.base); 76 } 77 78 static 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 92 void 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 111 void 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 118 void test_fail(void) 119 { 120 if (verbose) { 121 ksft_test_result_fail(": "); 122 print_prefixes("failed\n"); 123 } 124 } 125 126 void test_pass(void) 127 { 128 if (verbose) { 129 ksft_test_result_pass(": "); 130 print_prefixes("passed\n"); 131 } 132 } 133 134 void 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 147 void prefix_reset(void) 148 { 149 memset(prefixes, 0, PREFIXES_MAX * sizeof(char *)); 150 nr_prefixes = 0; 151 } 152 153 void prefix_push(const char *prefix) 154 { 155 assert(nr_prefixes < PREFIXES_MAX); 156 prefixes[nr_prefixes] = prefix; 157 nr_prefixes++; 158 } 159 160 void prefix_pop(void) 161 { 162 if (nr_prefixes > 0) { 163 prefixes[nr_prefixes - 1] = 0; 164 nr_prefixes--; 165 } 166 } 167