Skip to content

lkl: initialize mm constants before mem_init()#622

Merged
tavip merged 1 commit intolkl:masterfrom
lrh2000:mm-init-const
Apr 14, 2026
Merged

lkl: initialize mm constants before mem_init()#622
tavip merged 1 commit intolkl:masterfrom
lrh2000:mm-init-const

Conversation

@lrh2000
Copy link
Copy Markdown

@lrh2000 lrh2000 commented Apr 8, 2026

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().

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>
Copy link
Copy Markdown
Member

@tavip tavip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @lrh2000 ! How did you run into this issue, is there a way to add a test for this?

@lrh2000
Copy link
Copy Markdown
Author

lrh2000 commented Apr 13, 2026

Thanks for your review!

How did you run into this issue

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.

is there a way to add a test for this?

I don't think we can check the page flags outside the kernel. So I don't think we can add a test in tools/lkl. Is it what you mean here?

That being said, if we just want more assertions, I think we check add a BUG_ON in mem_init() to check whether the zero page is marked as a reserved page. It will fail before this PR but it should pass after this PR. However, I'm not sure if we want to do this.

empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
memset(empty_zero_page, 0, PAGE_SIZE);

 void __init mem_init(void)
 {
 	memblock_free_all();
 
+	BUG_ON(!PageReserved(virt_to_page(zero_page)));
 }

@tavip
Copy link
Copy Markdown
Member

tavip commented Apr 14, 2026

Thanks @lrh2000, it that case we could probably could add a kunit test for it. Not a high priority though.

@tavip tavip merged commit 5a01672 into lkl:master Apr 14, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants