lkl: initialize mm constants before mem_init()#622
Conversation
max_mapnr is accessed through the following call chain: mem_init() -> memblock_free_all() -> free_low_memory_core_early() -> memmap_init_reserved_pages() -> reserve_bootmem_region() -> pfn_valid() -> (pfn - ARCH_PFN_OFFSET) < max_mapnr In lkl, max_mapnr is currently initialized in mem_init(), but only after memblock_free_all() runs. This means pfn_valid() can see an uninitialized max_mapnr and incorrectly return false for pfns that should be valid. For example, reserve_bootmem_region() should mark such pages as reserved, but due to this bug it does not. Other architectures, such as riscv, x86, and arm64, initialize mm constants before mem_init() from setup_arch(). Do the equivalent for lkl by initializing max_pfn, max_low_pfn, min_low_pfn, and max_mapnr in bootmem_init(). Signed-off-by: Ruihan Li <lrh2000@pku.edu.cn>
|
Thanks for your review!
During the boot process, I reserve some pages for special communication purposes with the host. Then, during communication, I assert the reserved flag in case I access the wrong page. However, the assertion fails, so I spend some time trying to figure out why.
I don't think we can check the page flags outside the kernel. So I don't think we can add a test in That being said, if we just want more assertions, I think we check add a Lines 55 to 56 in 952bb32 void __init mem_init(void)
{
memblock_free_all();
+ BUG_ON(!PageReserved(virt_to_page(zero_page)));
} |
|
Thanks @lrh2000, it that case we could probably could add a kunit test for it. Not a high priority though. |
max_mapnr is accessed through the following call chain:
In lkl, max_mapnr is currently initialized in mem_init(), but only after memblock_free_all() runs. This means pfn_valid() can see an uninitialized max_mapnr and incorrectly return false for pfns that should be valid.
For example, reserve_bootmem_region() should mark such pages as reserved, but due to this bug it does not.
Other architectures, such as riscv, x86, and arm64, initialize mm constants before mem_init() from setup_arch(). Do the equivalent for lkl by initializing max_pfn, max_low_pfn, min_low_pfn, and max_mapnr in bootmem_init().