162306a36Sopenharmony_ci================== 262306a36Sopenharmony_ciMemblock simulator 362306a36Sopenharmony_ci================== 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciIntroduction 662306a36Sopenharmony_ci============ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ciMemblock is a boot time memory allocator[1] that manages memory regions before 962306a36Sopenharmony_cithe actual memory management is initialized. Its APIs allow to register physical 1062306a36Sopenharmony_cimemory regions, mark them as available or reserved, allocate a block of memory 1162306a36Sopenharmony_ciwithin the requested range and/or in specific NUMA node, and many more. 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciBecause it is used so early in the booting process, testing and debugging it is 1462306a36Sopenharmony_cidifficult. This test suite, usually referred as memblock simulator, is 1562306a36Sopenharmony_cian attempt at testing the memblock mechanism. It runs one monolithic test that 1662306a36Sopenharmony_ciconsist of a series of checks that exercise both the basic operations and 1762306a36Sopenharmony_ciallocation functionalities of memblock. The main data structure of the boot time 1862306a36Sopenharmony_cimemory allocator is initialized at the build time, so the checks here reuse its 1962306a36Sopenharmony_ciinstance throughout the duration of the test. To ensure that tests don't affect 2062306a36Sopenharmony_cieach other, region arrays are reset in between. 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciAs this project uses the actual memblock code and has to run in user space, 2362306a36Sopenharmony_cisome of the kernel definitions were stubbed by the initial commit that 2462306a36Sopenharmony_ciintroduced memblock simulator (commit 16802e55dea9 ("memblock tests: Add 2562306a36Sopenharmony_ciskeleton of the memblock simulator")) and a few preparation commits just 2662306a36Sopenharmony_cibefore it. Most of them don't match the kernel implementation, so one should 2762306a36Sopenharmony_ciconsult them first before making any significant changes to the project. 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ciUsage 3062306a36Sopenharmony_ci===== 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciTo run the tests, build the main target and run it: 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci$ make && ./main 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciA successful run produces no output. It is possible to control the behavior 3762306a36Sopenharmony_ciby passing options from command line. For example, to include verbose output, 3862306a36Sopenharmony_ciappend the `-v` options when you run the tests: 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci$ ./main -v 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ciThis will print information about which functions are being tested and the 4362306a36Sopenharmony_cinumber of test cases that passed. 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciFor the full list of options from command line, see `./main --help`. 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ciIt is also possible to override different configuration parameters to change 4862306a36Sopenharmony_cithe test functions. For example, to simulate enabled NUMA, use: 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci$ make NUMA=1 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciFor the full list of build options, see `make help`. 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ciProject structure 5562306a36Sopenharmony_ci================= 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciThe project has one target, main, which calls a group of checks for basic and 5862306a36Sopenharmony_ciallocation functions. Tests for each group are defined in dedicated files, as it 5962306a36Sopenharmony_cican be seen here: 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cimemblock 6262306a36Sopenharmony_ci|-- asm ------------------, 6362306a36Sopenharmony_ci|-- lib |-- implement function and struct stubs 6462306a36Sopenharmony_ci|-- linux ------------------' 6562306a36Sopenharmony_ci|-- scripts 6662306a36Sopenharmony_ci| |-- Makefile.include -- handles `make` parameters 6762306a36Sopenharmony_ci|-- tests 6862306a36Sopenharmony_ci| |-- alloc_api.(c|h) -- memblock_alloc tests 6962306a36Sopenharmony_ci| |-- alloc_helpers_api.(c|h) -- memblock_alloc_from tests 7062306a36Sopenharmony_ci| |-- alloc_nid_api.(c|h) -- memblock_alloc_try_nid tests 7162306a36Sopenharmony_ci| |-- basic_api.(c|h) -- memblock_add/memblock_reserve/... tests 7262306a36Sopenharmony_ci| |-- common.(c|h) -- helper functions for resetting memblock; 7362306a36Sopenharmony_ci|-- main.c --------------. dummy physical memory definition 7462306a36Sopenharmony_ci|-- Makefile `- test runner 7562306a36Sopenharmony_ci|-- README 7662306a36Sopenharmony_ci|-- TODO 7762306a36Sopenharmony_ci|-- .gitignore 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciSimulating physical memory 8062306a36Sopenharmony_ci========================== 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ciSome allocation functions clear the memory in the process, so it is required for 8362306a36Sopenharmony_cimemblock to track valid memory ranges. To achieve this, the test suite registers 8462306a36Sopenharmony_ciwith memblock memory stored by test_memory struct. It is a small wrapper that 8562306a36Sopenharmony_cipoints to a block of memory allocated via malloc. For each group of allocation 8662306a36Sopenharmony_citests, dummy physical memory is allocated, added to memblock, and then released 8762306a36Sopenharmony_ciat the end of the test run. The structure of a test runner checking allocation 8862306a36Sopenharmony_cifunctions is as follows: 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciint memblock_alloc_foo_checks(void) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci reset_memblock_attributes(); /* data structure reset */ 9362306a36Sopenharmony_ci dummy_physical_memory_init(); /* allocate and register memory */ 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci (...allocation checks...) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci dummy_physical_memory_cleanup(); /* free the memory */ 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ciThere's no need to explicitly free the dummy memory from memblock via 10162306a36Sopenharmony_cimemblock_free() call. The entry will be erased by reset_memblock_regions(), 10262306a36Sopenharmony_cicalled at the beginning of each test. 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciKnown issues 10562306a36Sopenharmony_ci============ 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci1. Requesting a specific NUMA node via memblock_alloc_node() does not work as 10862306a36Sopenharmony_ci intended. Once the fix is in place, tests for this function can be added. 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci2. Tests for memblock_alloc_low() can't be easily implemented. The function uses 11162306a36Sopenharmony_ci ARCH_LOW_ADDRESS_LIMIT marco, which can't be changed to point at the low 11262306a36Sopenharmony_ci memory of the memory_block. 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciReferences 11562306a36Sopenharmony_ci========== 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci1. Boot time memory management documentation page: 11862306a36Sopenharmony_ci https://www.kernel.org/doc/html/latest/core-api/boot-time-mm.html 119