|
| 1 | +================== |
| 2 | +Memblock simulator |
| 3 | +================== |
| 4 | + |
| 5 | +Introduction |
| 6 | +============ |
| 7 | + |
| 8 | +Memblock is a boot time memory allocator[1] that manages memory regions before |
| 9 | +the actual memory management is initialized. Its APIs allow to register physical |
| 10 | +memory regions, mark them as available or reserved, allocate a block of memory |
| 11 | +within the requested range and/or in specific NUMA node, and many more. |
| 12 | + |
| 13 | +Because it is used so early in the booting process, testing and debugging it is |
| 14 | +difficult. This test suite, usually referred as memblock simulator, is |
| 15 | +an attempt at testing the memblock mechanism. It runs one monolithic test that |
| 16 | +consist of a series of checks that exercise both the basic operations and |
| 17 | +allocation functionalities of memblock. The main data structure of the boot time |
| 18 | +memory allocator is initialized at the build time, so the checks here reuse its |
| 19 | +instance throughout the duration of the test. To ensure that tests don't affect |
| 20 | +each other, region arrays are reset in between. |
| 21 | + |
| 22 | +As this project uses the actual memblock code and has to run in user space, |
| 23 | +some of the kernel definitions were stubbed by the initial commit that |
| 24 | +introduced memblock simulator (commit 16802e55dea9 ("memblock tests: Add |
| 25 | +skeleton of the memblock simulator")) and a few preparation commits just |
| 26 | +before it. Most of them don't match the kernel implementation, so one should |
| 27 | +consult them first before making any significant changes to the project. |
| 28 | + |
| 29 | +Usage |
| 30 | +===== |
| 31 | + |
| 32 | +To run the tests, build the main target and run it: |
| 33 | + |
| 34 | +$ make && ./main |
| 35 | + |
| 36 | +A successful run produces no output. It is also possible to override different |
| 37 | +configuration parameters. For example, to simulate enabled NUMA, use: |
| 38 | + |
| 39 | +$ make NUMA=1 |
| 40 | + |
| 41 | +For the full list of options, see `make help`. |
| 42 | + |
| 43 | +Project structure |
| 44 | +================= |
| 45 | + |
| 46 | +The project has one target, main, which calls a group of checks for basic and |
| 47 | +allocation functions. Tests for each group are defined in dedicated files, as it |
| 48 | +can be seen here: |
| 49 | + |
| 50 | +memblock |
| 51 | +|-- asm ------------------, |
| 52 | +|-- lib |-- implement function and struct stubs |
| 53 | +|-- linux ------------------' |
| 54 | +|-- scripts |
| 55 | +| |-- Makefile.include -- handles `make` parameters |
| 56 | +|-- tests |
| 57 | +| |-- alloc_api.(c|h) -- memblock_alloc tests |
| 58 | +| |-- alloc_helpers_api.(c|h) -- memblock_alloc_from tests |
| 59 | +| |-- alloc_nid_api.(c|h) -- memblock_alloc_try_nid tests |
| 60 | +| |-- basic_api.(c|h) -- memblock_add/memblock_reserve/... tests |
| 61 | +| |-- common.(c|h) -- helper functions for resetting memblock; |
| 62 | +|-- main.c --------------. dummy physical memory definition |
| 63 | +|-- Makefile `- test runner |
| 64 | +|-- README |
| 65 | +|-- TODO |
| 66 | +|-- .gitignore |
| 67 | + |
| 68 | +Simulating physical memory |
| 69 | +========================== |
| 70 | + |
| 71 | +Some allocation functions clear the memory in the process, so it is required for |
| 72 | +memblock to track valid memory ranges. To achieve this, the test suite registers |
| 73 | +with memblock memory stored by test_memory struct. It is a small wrapper that |
| 74 | +points to a block of memory allocated via malloc. For each group of allocation |
| 75 | +tests, dummy physical memory is allocated, added to memblock, and then released |
| 76 | +at the end of the test run. The structure of a test runner checking allocation |
| 77 | +functions is as follows: |
| 78 | + |
| 79 | +int memblock_alloc_foo_checks(void) |
| 80 | +{ |
| 81 | + reset_memblock_attributes(); /* data structure reset */ |
| 82 | + dummy_physical_memory_init(); /* allocate and register memory */ |
| 83 | + |
| 84 | + (...allocation checks...) |
| 85 | + |
| 86 | + dummy_physical_memory_cleanup(); /* free the memory */ |
| 87 | +} |
| 88 | + |
| 89 | +There's no need to explicitly free the dummy memory from memblock via |
| 90 | +memblock_free() call. The entry will be erased by reset_memblock_regions(), |
| 91 | +called at the beginning of each test. |
| 92 | + |
| 93 | +Known issues |
| 94 | +============ |
| 95 | + |
| 96 | +1. Requesting a specific NUMA node via memblock_alloc_node() does not work as |
| 97 | + intended. Once the fix is in place, tests for this function can be added. |
| 98 | + |
| 99 | +2. Tests for memblock_alloc_low() can't be easily implemented. The function uses |
| 100 | + ARCH_LOW_ADDRESS_LIMIT marco, which can't be changed to point at the low |
| 101 | + memory of the memory_block. |
| 102 | + |
| 103 | +References |
| 104 | +========== |
| 105 | + |
| 106 | +1. Boot time memory management documentation page: |
| 107 | + https://www.kernel.org/doc/html/latest/core-api/boot-time-mm.html |
0 commit comments