Commit b8dcef87 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'memblock-v5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock

Pull memblock updates from Mike Rapoport:

 - An optimization in memblock_add_range() to reduce array traversals

 - Improvements to the memblock test suite

* tag 'memblock-v5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock:
  memblock test: Modify the obsolete description in README
  memblock tests: fix compilation errors
  memblock tests: change build options to run-time options
  memblock tests: remove completed TODO items
  memblock tests: set memblock_debug to enable memblock_dbg() messages
  memblock tests: add verbose output to memblock tests
  memblock tests: Makefile: add arguments to control verbosity
  memblock: avoid some repeat when add new range
parents 15886321 04d94909
...@@ -597,6 +597,17 @@ static int __init_memblock memblock_add_range(struct memblock_type *type, ...@@ -597,6 +597,17 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
type->total_size = size; type->total_size = size;
return 0; return 0;
} }
/*
* The worst case is when new range overlaps all existing regions,
* then we'll need type->cnt + 1 empty regions in @type. So if
* type->cnt * 2 + 1 is less than type->max, we know
* that there is enough empty regions in @type, and we can insert
* regions directly.
*/
if (type->cnt * 2 + 1 < type->max)
insert = true;
repeat: repeat:
/* /*
* The following is executed twice. Once with %false @insert and * The following is executed twice. Once with %false @insert and
......
...@@ -45,9 +45,8 @@ help: ...@@ -45,9 +45,8 @@ help:
@echo ' clean - Remove generated files and symlinks in the directory' @echo ' clean - Remove generated files and symlinks in the directory'
@echo '' @echo ''
@echo 'Configuration:' @echo 'Configuration:'
@echo ' make MEMBLOCK_DEBUG=1 - enable memblock_dbg() messages'
@echo ' make NUMA=1 - simulate enabled NUMA' @echo ' make NUMA=1 - simulate enabled NUMA'
@echo ' make MOVABLE_NODE=1 - override `movable_node_is_enabled`'
@echo ' definition to simulate movable NUMA nodes'
@echo ' make 32BIT_PHYS_ADDR_T=1 - Use 32 bit physical addresses' @echo ' make 32BIT_PHYS_ADDR_T=1 - Use 32 bit physical addresses'
vpath %.c ../../lib vpath %.c ../../lib
......
...@@ -33,12 +33,23 @@ To run the tests, build the main target and run it: ...@@ -33,12 +33,23 @@ To run the tests, build the main target and run it:
$ make && ./main $ make && ./main
A successful run produces no output. It is also possible to override different A successful run produces no output. It is possible to control the behavior
configuration parameters. For example, to simulate enabled NUMA, use: by passing options from command line. For example, to include verbose output,
append the `-v` options when you run the tests:
$ ./main -v
This will print information about which functions are being tested and the
number of test cases that passed.
For the full list of options from command line, see `./main --help`.
It is also possible to override different configuration parameters to change
the test functions. For example, to simulate enabled NUMA, use:
$ make NUMA=1 $ make NUMA=1
For the full list of options, see `make help`. For the full list of build options, see `make help`.
Project structure Project structure
================= =================
......
TODO TODO
===== =====
1. Add verbose output (e.g., what is being tested and how many tests cases are 1. Add tests trying to memblock_add() or memblock_reserve() 129th region.
passing)
2. Add flags to Makefile:
+ verbosity level
+ enable memblock_dbg() messages (i.e. pass "-D CONFIG_DEBUG_MEMORY_INIT"
flag)
3. Add tests trying to memblock_add() or memblock_reserve() 129th region.
This will trigger memblock_double_array(), make sure it succeeds. This will trigger memblock_double_array(), make sure it succeeds.
*Important:* These tests require valid memory ranges, use dummy physical *Important:* These tests require valid memory ranges, use dummy physical
memory block from common.c to implement them. It is also very memory block from common.c to implement them. It is also very
likely that the current MEM_SIZE won't be enough for these likely that the current MEM_SIZE won't be enough for these
test cases. Use realloc to adjust the size accordingly. test cases. Use realloc to adjust the size accordingly.
4. Add test cases using this functions (implement them for both directions): 2. Add test cases using this functions (implement them for both directions):
+ memblock_alloc_raw() + memblock_alloc_raw()
+ memblock_alloc_exact_nid_raw() + memblock_alloc_exact_nid_raw()
+ memblock_alloc_try_nid_raw() + memblock_alloc_try_nid_raw()
5. Add tests for memblock_alloc_node() to check if the correct NUMA node is set 3. Add tests for memblock_alloc_node() to check if the correct NUMA node is set
for the new region for the new region
...@@ -2,6 +2,17 @@ ...@@ -2,6 +2,17 @@
#ifndef _MM_INTERNAL_H #ifndef _MM_INTERNAL_H
#define _MM_INTERNAL_H #define _MM_INTERNAL_H
/*
* Enable memblock_dbg() messages
*/
#ifdef MEMBLOCK_DEBUG
static int memblock_debug = 1;
#endif
#define pr_warn_ratelimited(fmt, ...) printf(fmt, ##__VA_ARGS__)
bool mirrored_kernelcore = false;
struct page {}; struct page {};
void memblock_free_pages(struct page *page, unsigned long pfn, void memblock_free_pages(struct page *page, unsigned long pfn,
......
...@@ -7,13 +7,11 @@ ...@@ -7,13 +7,11 @@
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/types.h> #include <linux/types.h>
extern bool movable_node_enabled;
static inline bool movable_node_is_enabled(void) static inline bool movable_node_is_enabled(void)
{ {
#ifdef MOVABLE_NODE return movable_node_enabled;
return true;
#else
return false;
#endif
} }
#endif #endif
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
#include "tests/alloc_api.h" #include "tests/alloc_api.h"
#include "tests/alloc_helpers_api.h" #include "tests/alloc_helpers_api.h"
#include "tests/alloc_nid_api.h" #include "tests/alloc_nid_api.h"
#include "tests/common.h"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
parse_args(argc, argv);
memblock_basic_checks(); memblock_basic_checks();
memblock_alloc_checks(); memblock_alloc_checks();
memblock_alloc_helpers_checks(); memblock_alloc_helpers_checks();
......
...@@ -6,14 +6,14 @@ ifeq ($(NUMA), 1) ...@@ -6,14 +6,14 @@ ifeq ($(NUMA), 1)
CFLAGS += -D CONFIG_NUMA CFLAGS += -D CONFIG_NUMA
endif endif
# Simulate movable NUMA memory regions
ifeq ($(MOVABLE_NODE), 1)
CFLAGS += -D MOVABLE_NODE
endif
# Use 32 bit physical addresses. # Use 32 bit physical addresses.
# Remember to install 32-bit version of dependencies. # Remember to install 32-bit version of dependencies.
ifeq ($(32BIT_PHYS_ADDR_T), 1) ifeq ($(32BIT_PHYS_ADDR_T), 1)
CFLAGS += -m32 -U CONFIG_PHYS_ADDR_T_64BIT CFLAGS += -m32 -U CONFIG_PHYS_ADDR_T_64BIT
LDFLAGS += -m32 LDFLAGS += -m32
endif endif
# Enable memblock_dbg() messages
ifeq ($(MEMBLOCK_DEBUG), 1)
CFLAGS += -D MEMBLOCK_DEBUG
endif
This diff is collapsed.
...@@ -21,6 +21,8 @@ static int alloc_from_simple_generic_check(void) ...@@ -21,6 +21,8 @@ static int alloc_from_simple_generic_check(void)
void *allocated_ptr = NULL; void *allocated_ptr = NULL;
char *b; char *b;
PREFIX_PUSH();
phys_addr_t size = SZ_16; phys_addr_t size = SZ_16;
phys_addr_t min_addr; phys_addr_t min_addr;
...@@ -31,14 +33,16 @@ static int alloc_from_simple_generic_check(void) ...@@ -31,14 +33,16 @@ static int alloc_from_simple_generic_check(void)
allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
b = (char *)allocated_ptr; b = (char *)allocated_ptr;
assert(allocated_ptr); ASSERT_NE(allocated_ptr, NULL);
assert(*b == 0); ASSERT_EQ(*b, 0);
ASSERT_EQ(rgn->size, size);
ASSERT_EQ(rgn->base, min_addr);
assert(rgn->size == size); ASSERT_EQ(memblock.reserved.cnt, 1);
assert(rgn->base == min_addr); ASSERT_EQ(memblock.reserved.total_size, size);
assert(memblock.reserved.cnt == 1); test_pass_pop();
assert(memblock.reserved.total_size == size);
return 0; return 0;
} }
...@@ -64,6 +68,8 @@ static int alloc_from_misaligned_generic_check(void) ...@@ -64,6 +68,8 @@ static int alloc_from_misaligned_generic_check(void)
void *allocated_ptr = NULL; void *allocated_ptr = NULL;
char *b; char *b;
PREFIX_PUSH();
phys_addr_t size = SZ_32; phys_addr_t size = SZ_32;
phys_addr_t min_addr; phys_addr_t min_addr;
...@@ -75,14 +81,16 @@ static int alloc_from_misaligned_generic_check(void) ...@@ -75,14 +81,16 @@ static int alloc_from_misaligned_generic_check(void)
allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
b = (char *)allocated_ptr; b = (char *)allocated_ptr;
assert(allocated_ptr); ASSERT_NE(allocated_ptr, NULL);
assert(*b == 0); ASSERT_EQ(*b, 0);
assert(rgn->size == size); ASSERT_EQ(rgn->size, size);
assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES); ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);
assert(memblock.reserved.cnt == 1); ASSERT_EQ(memblock.reserved.cnt, 1);
assert(memblock.reserved.total_size == size); ASSERT_EQ(memblock.reserved.total_size, size);
test_pass_pop();
return 0; return 0;
} }
...@@ -110,6 +118,8 @@ static int alloc_from_top_down_high_addr_check(void) ...@@ -110,6 +118,8 @@ static int alloc_from_top_down_high_addr_check(void)
struct memblock_region *rgn = &memblock.reserved.regions[0]; struct memblock_region *rgn = &memblock.reserved.regions[0];
void *allocated_ptr = NULL; void *allocated_ptr = NULL;
PREFIX_PUSH();
phys_addr_t size = SZ_32; phys_addr_t size = SZ_32;
phys_addr_t min_addr; phys_addr_t min_addr;
...@@ -120,12 +130,14 @@ static int alloc_from_top_down_high_addr_check(void) ...@@ -120,12 +130,14 @@ static int alloc_from_top_down_high_addr_check(void)
allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
assert(allocated_ptr); ASSERT_NE(allocated_ptr, NULL);
assert(rgn->size == size); ASSERT_EQ(rgn->size, size);
assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES); ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);
assert(memblock.reserved.cnt == 1); ASSERT_EQ(memblock.reserved.cnt, 1);
assert(memblock.reserved.total_size == size); ASSERT_EQ(memblock.reserved.total_size, size);
test_pass_pop();
return 0; return 0;
} }
...@@ -151,6 +163,8 @@ static int alloc_from_top_down_no_space_above_check(void) ...@@ -151,6 +163,8 @@ static int alloc_from_top_down_no_space_above_check(void)
struct memblock_region *rgn = &memblock.reserved.regions[0]; struct memblock_region *rgn = &memblock.reserved.regions[0];
void *allocated_ptr = NULL; void *allocated_ptr = NULL;
PREFIX_PUSH();
phys_addr_t r1_size = SZ_64; phys_addr_t r1_size = SZ_64;
phys_addr_t r2_size = SZ_2; phys_addr_t r2_size = SZ_2;
phys_addr_t total_size = r1_size + r2_size; phys_addr_t total_size = r1_size + r2_size;
...@@ -165,12 +179,14 @@ static int alloc_from_top_down_no_space_above_check(void) ...@@ -165,12 +179,14 @@ static int alloc_from_top_down_no_space_above_check(void)
allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
assert(allocated_ptr); ASSERT_NE(allocated_ptr, NULL);
assert(rgn->base == min_addr - r1_size); ASSERT_EQ(rgn->base, min_addr - r1_size);
assert(rgn->size == total_size); ASSERT_EQ(rgn->size, total_size);
ASSERT_EQ(memblock.reserved.cnt, 1);
ASSERT_EQ(memblock.reserved.total_size, total_size);
assert(memblock.reserved.cnt == 1); test_pass_pop();
assert(memblock.reserved.total_size == total_size);
return 0; return 0;
} }
...@@ -186,6 +202,8 @@ static int alloc_from_top_down_min_addr_cap_check(void) ...@@ -186,6 +202,8 @@ static int alloc_from_top_down_min_addr_cap_check(void)
struct memblock_region *rgn = &memblock.reserved.regions[0]; struct memblock_region *rgn = &memblock.reserved.regions[0];
void *allocated_ptr = NULL; void *allocated_ptr = NULL;
PREFIX_PUSH();
phys_addr_t r1_size = SZ_64; phys_addr_t r1_size = SZ_64;
phys_addr_t min_addr; phys_addr_t min_addr;
phys_addr_t start_addr; phys_addr_t start_addr;
...@@ -199,12 +217,14 @@ static int alloc_from_top_down_min_addr_cap_check(void) ...@@ -199,12 +217,14 @@ static int alloc_from_top_down_min_addr_cap_check(void)
allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
assert(allocated_ptr); ASSERT_NE(allocated_ptr, NULL);
assert(rgn->base == start_addr); ASSERT_EQ(rgn->base, start_addr);
assert(rgn->size == MEM_SIZE); ASSERT_EQ(rgn->size, MEM_SIZE);
ASSERT_EQ(memblock.reserved.cnt, 1);
ASSERT_EQ(memblock.reserved.total_size, MEM_SIZE);
assert(memblock.reserved.cnt == 1); test_pass_pop();
assert(memblock.reserved.total_size == MEM_SIZE);
return 0; return 0;
} }
...@@ -230,6 +250,8 @@ static int alloc_from_bottom_up_high_addr_check(void) ...@@ -230,6 +250,8 @@ static int alloc_from_bottom_up_high_addr_check(void)
struct memblock_region *rgn = &memblock.reserved.regions[0]; struct memblock_region *rgn = &memblock.reserved.regions[0];
void *allocated_ptr = NULL; void *allocated_ptr = NULL;
PREFIX_PUSH();
phys_addr_t size = SZ_32; phys_addr_t size = SZ_32;
phys_addr_t min_addr; phys_addr_t min_addr;
...@@ -240,12 +262,14 @@ static int alloc_from_bottom_up_high_addr_check(void) ...@@ -240,12 +262,14 @@ static int alloc_from_bottom_up_high_addr_check(void)
allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
assert(allocated_ptr); ASSERT_NE(allocated_ptr, NULL);
assert(rgn->size == size); ASSERT_EQ(rgn->size, size);
assert(rgn->base == memblock_start_of_DRAM()); ASSERT_EQ(rgn->base, memblock_start_of_DRAM());
ASSERT_EQ(memblock.reserved.cnt, 1);
ASSERT_EQ(memblock.reserved.total_size, size);
assert(memblock.reserved.cnt == 1); test_pass_pop();
assert(memblock.reserved.total_size == size);
return 0; return 0;
} }
...@@ -270,6 +294,8 @@ static int alloc_from_bottom_up_no_space_above_check(void) ...@@ -270,6 +294,8 @@ static int alloc_from_bottom_up_no_space_above_check(void)
struct memblock_region *rgn = &memblock.reserved.regions[0]; struct memblock_region *rgn = &memblock.reserved.regions[0];
void *allocated_ptr = NULL; void *allocated_ptr = NULL;
PREFIX_PUSH();
phys_addr_t r1_size = SZ_64; phys_addr_t r1_size = SZ_64;
phys_addr_t min_addr; phys_addr_t min_addr;
phys_addr_t r2_size; phys_addr_t r2_size;
...@@ -284,12 +310,14 @@ static int alloc_from_bottom_up_no_space_above_check(void) ...@@ -284,12 +310,14 @@ static int alloc_from_bottom_up_no_space_above_check(void)
allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
assert(allocated_ptr); ASSERT_NE(allocated_ptr, NULL);
assert(rgn->base == memblock_start_of_DRAM()); ASSERT_EQ(rgn->base, memblock_start_of_DRAM());
assert(rgn->size == r1_size); ASSERT_EQ(rgn->size, r1_size);
assert(memblock.reserved.cnt == 2); ASSERT_EQ(memblock.reserved.cnt, 2);
assert(memblock.reserved.total_size == r1_size + r2_size); ASSERT_EQ(memblock.reserved.total_size, r1_size + r2_size);
test_pass_pop();
return 0; return 0;
} }
...@@ -304,6 +332,8 @@ static int alloc_from_bottom_up_min_addr_cap_check(void) ...@@ -304,6 +332,8 @@ static int alloc_from_bottom_up_min_addr_cap_check(void)
struct memblock_region *rgn = &memblock.reserved.regions[0]; struct memblock_region *rgn = &memblock.reserved.regions[0];
void *allocated_ptr = NULL; void *allocated_ptr = NULL;
PREFIX_PUSH();
phys_addr_t r1_size = SZ_64; phys_addr_t r1_size = SZ_64;
phys_addr_t min_addr; phys_addr_t min_addr;
phys_addr_t start_addr; phys_addr_t start_addr;
...@@ -315,12 +345,14 @@ static int alloc_from_bottom_up_min_addr_cap_check(void) ...@@ -315,12 +345,14 @@ static int alloc_from_bottom_up_min_addr_cap_check(void)
allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
assert(allocated_ptr); ASSERT_NE(allocated_ptr, NULL);
assert(rgn->base == start_addr); ASSERT_EQ(rgn->base, start_addr);
assert(rgn->size == r1_size); ASSERT_EQ(rgn->size, r1_size);
assert(memblock.reserved.cnt == 1); ASSERT_EQ(memblock.reserved.cnt, 1);
assert(memblock.reserved.total_size == r1_size); ASSERT_EQ(memblock.reserved.total_size, r1_size);
test_pass_pop();
return 0; return 0;
} }
...@@ -328,6 +360,7 @@ static int alloc_from_bottom_up_min_addr_cap_check(void) ...@@ -328,6 +360,7 @@ static int alloc_from_bottom_up_min_addr_cap_check(void)
/* Test case wrappers */ /* Test case wrappers */
static int alloc_from_simple_check(void) static int alloc_from_simple_check(void)
{ {
test_print("\tRunning %s...\n", __func__);
memblock_set_bottom_up(false); memblock_set_bottom_up(false);
alloc_from_simple_generic_check(); alloc_from_simple_generic_check();
memblock_set_bottom_up(true); memblock_set_bottom_up(true);
...@@ -338,6 +371,7 @@ static int alloc_from_simple_check(void) ...@@ -338,6 +371,7 @@ static int alloc_from_simple_check(void)
static int alloc_from_misaligned_check(void) static int alloc_from_misaligned_check(void)
{ {
test_print("\tRunning %s...\n", __func__);
memblock_set_bottom_up(false); memblock_set_bottom_up(false);
alloc_from_misaligned_generic_check(); alloc_from_misaligned_generic_check();
memblock_set_bottom_up(true); memblock_set_bottom_up(true);
...@@ -348,6 +382,7 @@ static int alloc_from_misaligned_check(void) ...@@ -348,6 +382,7 @@ static int alloc_from_misaligned_check(void)
static int alloc_from_high_addr_check(void) static int alloc_from_high_addr_check(void)
{ {
test_print("\tRunning %s...\n", __func__);
memblock_set_bottom_up(false); memblock_set_bottom_up(false);
alloc_from_top_down_high_addr_check(); alloc_from_top_down_high_addr_check();
memblock_set_bottom_up(true); memblock_set_bottom_up(true);
...@@ -358,6 +393,7 @@ static int alloc_from_high_addr_check(void) ...@@ -358,6 +393,7 @@ static int alloc_from_high_addr_check(void)
static int alloc_from_no_space_above_check(void) static int alloc_from_no_space_above_check(void)
{ {
test_print("\tRunning %s...\n", __func__);
memblock_set_bottom_up(false); memblock_set_bottom_up(false);
alloc_from_top_down_no_space_above_check(); alloc_from_top_down_no_space_above_check();
memblock_set_bottom_up(true); memblock_set_bottom_up(true);
...@@ -368,6 +404,7 @@ static int alloc_from_no_space_above_check(void) ...@@ -368,6 +404,7 @@ static int alloc_from_no_space_above_check(void)
static int alloc_from_min_addr_cap_check(void) static int alloc_from_min_addr_cap_check(void)
{ {
test_print("\tRunning %s...\n", __func__);
memblock_set_bottom_up(false); memblock_set_bottom_up(false);
alloc_from_top_down_min_addr_cap_check(); alloc_from_top_down_min_addr_cap_check();
memblock_set_bottom_up(true); memblock_set_bottom_up(true);
...@@ -378,6 +415,12 @@ static int alloc_from_min_addr_cap_check(void) ...@@ -378,6 +415,12 @@ static int alloc_from_min_addr_cap_check(void)
int memblock_alloc_helpers_checks(void) int memblock_alloc_helpers_checks(void)
{ {
const char *func_testing = "memblock_alloc_from";
prefix_reset();
prefix_push(func_testing);
test_print("Running %s tests...\n", func_testing);
reset_memblock_attributes(); reset_memblock_attributes();
dummy_physical_memory_init(); dummy_physical_memory_init();
...@@ -389,5 +432,7 @@ int memblock_alloc_helpers_checks(void) ...@@ -389,5 +432,7 @@ int memblock_alloc_helpers_checks(void)
dummy_physical_memory_cleanup(); dummy_physical_memory_cleanup();
prefix_pop();
return 0; return 0;
} }
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "tests/common.h" #include "tests/common.h"
#include <string.h> #include <string.h>
#include <getopt.h>
#include <linux/memory_hotplug.h>
#include <linux/build_bug.h>
#define INIT_MEMBLOCK_REGIONS 128 #define INIT_MEMBLOCK_REGIONS 128
#define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS #define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
#define PREFIXES_MAX 15
#define DELIM ": "
static struct test_memory memory_block; static struct test_memory memory_block;
static const char __maybe_unused *prefixes[PREFIXES_MAX];
static int __maybe_unused nr_prefixes;
static const char *short_opts = "mv";
static const struct option long_opts[] = {
{"movable-node", 0, NULL, 'm'},
{"verbose", 0, NULL, 'v'},
{NULL, 0, NULL, 0}
};
static const char * const help_opts[] = {
"disallow allocations from regions marked as hotplugged\n\t\t\t"
"by simulating enabling the \"movable_node\" kernel\n\t\t\t"
"parameter",
"enable verbose output, which includes the name of the\n\t\t\t"
"memblock function being tested, the name of the test,\n\t\t\t"
"and whether the test passed or failed."
};
static int verbose;
/* sets global variable returned by movable_node_is_enabled() stub */
bool movable_node_enabled;
void reset_memblock_regions(void) void reset_memblock_regions(void)
{ {
...@@ -46,3 +74,93 @@ void dummy_physical_memory_cleanup(void) ...@@ -46,3 +74,93 @@ void dummy_physical_memory_cleanup(void)
{ {
free(memory_block.base); free(memory_block.base);
} }
static void usage(const char *prog)
{
BUILD_BUG_ON(ARRAY_SIZE(help_opts) != ARRAY_SIZE(long_opts) - 1);
printf("Usage: %s [-%s]\n", prog, short_opts);
for (int i = 0; long_opts[i].name; i++) {
printf(" -%c, --%-12s\t%s\n", long_opts[i].val,
long_opts[i].name, help_opts[i]);
}
exit(1);
}
void parse_args(int argc, char **argv)
{
int c;
while ((c = getopt_long_only(argc, argv, short_opts, long_opts,
NULL)) != -1) {
switch (c) {
case 'm':
movable_node_enabled = true;
break;
case 'v':
verbose = 1;
break;
default:
usage(argv[0]);
}
}
}
void print_prefixes(const char *postfix)
{
for (int i = 0; i < nr_prefixes; i++)
test_print("%s%s", prefixes[i], DELIM);
test_print(postfix);
}
void test_fail(void)
{
if (verbose) {
ksft_test_result_fail(": ");
print_prefixes("failed\n");
}
}
void test_pass(void)
{
if (verbose) {
ksft_test_result_pass(": ");
print_prefixes("passed\n");
}
}
void test_print(const char *fmt, ...)
{
if (verbose) {
int saved_errno = errno;
va_list args;
va_start(args, fmt);
errno = saved_errno;
vprintf(fmt, args);
va_end(args);
}
}
void prefix_reset(void)
{
memset(prefixes, 0, PREFIXES_MAX * sizeof(char *));
nr_prefixes = 0;
}
void prefix_push(const char *prefix)
{
assert(nr_prefixes < PREFIXES_MAX);
prefixes[nr_prefixes] = prefix;
nr_prefixes++;
}
void prefix_pop(void)
{
if (nr_prefixes > 0) {
prefixes[nr_prefixes - 1] = 0;
nr_prefixes--;
}
}
...@@ -7,9 +7,49 @@ ...@@ -7,9 +7,49 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/printk.h>
#include <../selftests/kselftest.h>
#define MEM_SIZE SZ_16K #define MEM_SIZE SZ_16K
/**
* ASSERT_EQ():
* Check the condition
* @_expected == @_seen
* If false, print failed test message (if in VERBOSE mode) and then assert
*/
#define ASSERT_EQ(_expected, _seen) do { \
if ((_expected) != (_seen)) \
test_fail(); \
assert((_expected) == (_seen)); \
} while (0)
/**
* ASSERT_NE():
* Check the condition
* @_expected != @_seen
* If false, print failed test message (if in VERBOSE mode) and then assert
*/
#define ASSERT_NE(_expected, _seen) do { \
if ((_expected) == (_seen)) \
test_fail(); \
assert((_expected) != (_seen)); \
} while (0)
/**
* ASSERT_LT():
* Check the condition
* @_expected < @_seen
* If false, print failed test message (if in VERBOSE mode) and then assert
*/
#define ASSERT_LT(_expected, _seen) do { \
if ((_expected) >= (_seen)) \
test_fail(); \
assert((_expected) < (_seen)); \
} while (0)
#define PREFIX_PUSH() prefix_push(__func__)
/* /*
* Available memory registered with memblock needs to be valid for allocs * Available memory registered with memblock needs to be valid for allocs
* test to run. This is a convenience wrapper for memory allocated in * test to run. This is a convenience wrapper for memory allocated in
...@@ -30,5 +70,19 @@ void reset_memblock_attributes(void); ...@@ -30,5 +70,19 @@ void reset_memblock_attributes(void);
void setup_memblock(void); void setup_memblock(void);
void dummy_physical_memory_init(void); void dummy_physical_memory_init(void);
void dummy_physical_memory_cleanup(void); void dummy_physical_memory_cleanup(void);
void parse_args(int argc, char **argv);
void test_fail(void);
void test_pass(void);
void test_print(const char *fmt, ...);
void prefix_reset(void);
void prefix_push(const char *prefix);
void prefix_pop(void);
static inline void test_pass_pop(void)
{
test_pass();
prefix_pop();
}
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment