123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- ==================
- Memblock simulator
- ==================
- Introduction
- ============
- Memblock is a boot time memory allocator[1] that manages memory regions before
- the actual memory management is initialized. Its APIs allow to register physical
- memory regions, mark them as available or reserved, allocate a block of memory
- within the requested range and/or in specific NUMA node, and many more.
- Because it is used so early in the booting process, testing and debugging it is
- difficult. This test suite, usually referred as memblock simulator, is
- an attempt at testing the memblock mechanism. It runs one monolithic test that
- consist of a series of checks that exercise both the basic operations and
- allocation functionalities of memblock. The main data structure of the boot time
- memory allocator is initialized at the build time, so the checks here reuse its
- instance throughout the duration of the test. To ensure that tests don't affect
- each other, region arrays are reset in between.
- As this project uses the actual memblock code and has to run in user space,
- some of the kernel definitions were stubbed by the initial commit that
- introduced memblock simulator (commit 16802e55dea9 ("memblock tests: Add
- skeleton of the memblock simulator")) and a few preparation commits just
- before it. Most of them don't match the kernel implementation, so one should
- consult them first before making any significant changes to the project.
- Usage
- =====
- To run the tests, build the main target and run it:
- $ make && ./main
- A successful run produces no output. It is possible to control the behavior
- 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
- For the full list of build options, see `make help`.
- Project structure
- =================
- The project has one target, main, which calls a group of checks for basic and
- allocation functions. Tests for each group are defined in dedicated files, as it
- can be seen here:
- memblock
- |-- asm ------------------,
- |-- lib |-- implement function and struct stubs
- |-- linux ------------------'
- |-- scripts
- | |-- Makefile.include -- handles `make` parameters
- |-- tests
- | |-- alloc_api.(c|h) -- memblock_alloc tests
- | |-- alloc_helpers_api.(c|h) -- memblock_alloc_from tests
- | |-- alloc_nid_api.(c|h) -- memblock_alloc_try_nid tests
- | |-- basic_api.(c|h) -- memblock_add/memblock_reserve/... tests
- | |-- common.(c|h) -- helper functions for resetting memblock;
- |-- main.c --------------. dummy physical memory definition
- |-- Makefile `- test runner
- |-- README
- |-- TODO
- |-- .gitignore
- Simulating physical memory
- ==========================
- Some allocation functions clear the memory in the process, so it is required for
- memblock to track valid memory ranges. To achieve this, the test suite registers
- with memblock memory stored by test_memory struct. It is a small wrapper that
- points to a block of memory allocated via malloc. For each group of allocation
- tests, dummy physical memory is allocated, added to memblock, and then released
- at the end of the test run. The structure of a test runner checking allocation
- functions is as follows:
- int memblock_alloc_foo_checks(void)
- {
- reset_memblock_attributes(); /* data structure reset */
- dummy_physical_memory_init(); /* allocate and register memory */
- (...allocation checks...)
- dummy_physical_memory_cleanup(); /* free the memory */
- }
- There's no need to explicitly free the dummy memory from memblock via
- memblock_free() call. The entry will be erased by reset_memblock_regions(),
- called at the beginning of each test.
- Known issues
- ============
- 1. Requesting a specific NUMA node via memblock_alloc_node() does not work as
- intended. Once the fix is in place, tests for this function can be added.
- 2. Tests for memblock_alloc_low() can't be easily implemented. The function uses
- ARCH_LOW_ADDRESS_LIMIT marco, which can't be changed to point at the low
- memory of the memory_block.
- References
- ==========
- 1. Boot time memory management documentation page:
- https://www.kernel.org/doc/html/latest/core-api/boot-time-mm.html
|