common.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. #define PREFIXES_MAX 15
  8. #define DELIM ": "
  9. #define BASIS 10000
  10. static struct test_memory memory_block;
  11. static const char __maybe_unused *prefixes[PREFIXES_MAX];
  12. static int __maybe_unused nr_prefixes;
  13. static const char *short_opts = "hmv";
  14. static const struct option long_opts[] = {
  15. {"help", 0, NULL, 'h'},
  16. {"movable-node", 0, NULL, 'm'},
  17. {"verbose", 0, NULL, 'v'},
  18. {NULL, 0, NULL, 0}
  19. };
  20. static const char * const help_opts[] = {
  21. "display this help message and exit",
  22. "disallow allocations from regions marked as hotplugged\n\t\t\t"
  23. "by simulating enabling the \"movable_node\" kernel\n\t\t\t"
  24. "parameter",
  25. "enable verbose output, which includes the name of the\n\t\t\t"
  26. "memblock function being tested, the name of the test,\n\t\t\t"
  27. "and whether the test passed or failed."
  28. };
  29. static int verbose;
  30. /* sets global variable returned by movable_node_is_enabled() stub */
  31. bool movable_node_enabled;
  32. void reset_memblock_regions(void)
  33. {
  34. memset(memblock.memory.regions, 0,
  35. memblock.memory.cnt * sizeof(struct memblock_region));
  36. memblock.memory.cnt = 0;
  37. memblock.memory.max = INIT_MEMBLOCK_REGIONS;
  38. memblock.memory.total_size = 0;
  39. memset(memblock.reserved.regions, 0,
  40. memblock.reserved.cnt * sizeof(struct memblock_region));
  41. memblock.reserved.cnt = 0;
  42. memblock.reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS;
  43. memblock.reserved.total_size = 0;
  44. }
  45. void reset_memblock_attributes(void)
  46. {
  47. memblock.memory.name = "memory";
  48. memblock.reserved.name = "reserved";
  49. memblock.bottom_up = false;
  50. memblock.current_limit = MEMBLOCK_ALLOC_ANYWHERE;
  51. }
  52. static inline void fill_memblock(void)
  53. {
  54. memset(memory_block.base, 1, PHYS_MEM_SIZE);
  55. }
  56. void setup_memblock(void)
  57. {
  58. reset_memblock_regions();
  59. memblock_add((phys_addr_t)memory_block.base, MEM_SIZE);
  60. fill_memblock();
  61. }
  62. /**
  63. * setup_numa_memblock:
  64. * Set up a memory layout with multiple NUMA nodes in a previously allocated
  65. * dummy physical memory.
  66. * @node_fracs: an array representing the fraction of MEM_SIZE contained in
  67. * each node in basis point units (one hundredth of 1% or 1/10000).
  68. * For example, if node 0 should contain 1/8 of MEM_SIZE,
  69. * node_fracs[0] = 1250.
  70. *
  71. * The nids will be set to 0 through NUMA_NODES - 1.
  72. */
  73. void setup_numa_memblock(const unsigned int node_fracs[])
  74. {
  75. phys_addr_t base;
  76. int flags;
  77. reset_memblock_regions();
  78. base = (phys_addr_t)memory_block.base;
  79. flags = (movable_node_is_enabled()) ? MEMBLOCK_NONE : MEMBLOCK_HOTPLUG;
  80. for (int i = 0; i < NUMA_NODES; i++) {
  81. assert(node_fracs[i] <= BASIS);
  82. phys_addr_t size = MEM_SIZE * node_fracs[i] / BASIS;
  83. memblock_add_node(base, size, i, flags);
  84. base += size;
  85. }
  86. fill_memblock();
  87. }
  88. void dummy_physical_memory_init(void)
  89. {
  90. memory_block.base = malloc(PHYS_MEM_SIZE);
  91. assert(memory_block.base);
  92. fill_memblock();
  93. }
  94. void dummy_physical_memory_cleanup(void)
  95. {
  96. free(memory_block.base);
  97. }
  98. phys_addr_t dummy_physical_memory_base(void)
  99. {
  100. return (phys_addr_t)memory_block.base;
  101. }
  102. static void usage(const char *prog)
  103. {
  104. BUILD_BUG_ON(ARRAY_SIZE(help_opts) != ARRAY_SIZE(long_opts) - 1);
  105. printf("Usage: %s [-%s]\n", prog, short_opts);
  106. for (int i = 0; long_opts[i].name; i++) {
  107. printf(" -%c, --%-12s\t%s\n", long_opts[i].val,
  108. long_opts[i].name, help_opts[i]);
  109. }
  110. exit(1);
  111. }
  112. void parse_args(int argc, char **argv)
  113. {
  114. int c;
  115. while ((c = getopt_long_only(argc, argv, short_opts, long_opts,
  116. NULL)) != -1) {
  117. switch (c) {
  118. case 'm':
  119. movable_node_enabled = true;
  120. break;
  121. case 'v':
  122. verbose = 1;
  123. break;
  124. default:
  125. usage(argv[0]);
  126. }
  127. }
  128. }
  129. void print_prefixes(const char *postfix)
  130. {
  131. for (int i = 0; i < nr_prefixes; i++)
  132. test_print("%s%s", prefixes[i], DELIM);
  133. test_print(postfix);
  134. }
  135. void test_fail(void)
  136. {
  137. if (verbose) {
  138. ksft_test_result_fail(": ");
  139. print_prefixes("failed\n");
  140. }
  141. }
  142. void test_pass(void)
  143. {
  144. if (verbose) {
  145. ksft_test_result_pass(": ");
  146. print_prefixes("passed\n");
  147. }
  148. }
  149. void test_print(const char *fmt, ...)
  150. {
  151. if (verbose) {
  152. int saved_errno = errno;
  153. va_list args;
  154. va_start(args, fmt);
  155. errno = saved_errno;
  156. vprintf(fmt, args);
  157. va_end(args);
  158. }
  159. }
  160. void prefix_reset(void)
  161. {
  162. memset(prefixes, 0, PREFIXES_MAX * sizeof(char *));
  163. nr_prefixes = 0;
  164. }
  165. void prefix_push(const char *prefix)
  166. {
  167. assert(nr_prefixes < PREFIXES_MAX);
  168. prefixes[nr_prefixes] = prefix;
  169. nr_prefixes++;
  170. }
  171. void prefix_pop(void)
  172. {
  173. if (nr_prefixes > 0) {
  174. prefixes[nr_prefixes - 1] = 0;
  175. nr_prefixes--;
  176. }
  177. }