Skip to content

protos/limine: read the memory map count after the snapshot alloc - #688

Merged
Mintsuki merged 1 commit into
Limine-Bootloader:trunkfrom
hotline1337:fix/hhdm
Oct 6, 2026
Merged

Mintsuki merged 1 commit into
Limine-Bootloader:trunkfrom
hotline1337:fix/hhdm

Conversation

@hotline1337

Copy link
Copy Markdown
Contributor

Summary

  • build_pagemap() and build_identity_map() in common/protos/limine.c read memmap_entries after the snapshot allocation instead of before it.
  • The snapshot buffer is allocated with room for the entries the allocation itself can add (up to 2), so the copy can no longer drop the tail of the sorted map.

Background & Problem

Both pagemap builders take a private copy of the memory map before mapping it into the higher half direct map:

size_t _memmap_entries = memmap_entries;
struct memmap_entry *_memmap =
    ext_mem_alloc_counted(_memmap_entries, sizeof(struct memmap_entry));
for (size_t i = 0; i < _memmap_entries; i++)
    _memmap[i] = memmap[i];

ext_mem_alloc() serves allocations from the top of a usable entry (common/mm/pmm.s2.c, trying below 4 GiB first on x86). Reserving that range appends a new MEMMAP_BOOTLOADER_RECLAIMABLE entry to the map (pmm_new_entry()), and pmm_sanitise_entries() then sorts and merges. When the new entry cannot merge with a same-type neighbour, memmap_entries grows by 1 - but the copy loop is still bounded by the count read before the allocation. The entries at the end of the freshly sorted map are silently dropped, and whatever they describe is never mapped into the HHDM (nor seen by the framebuffer mapping loop, which walks the same copy in build_pagemap()).

As reported in #687: on a Lenovo V15 G4 IRU (UEFI, GOP framebuffer 1920x1080 at 0x4000000000, the highest memory map entry) the dropped entry is the framebuffer: the kernel's first write to the screen through the HHDM faults before it has installed an IDT, and the machine hangs on a black screen. Opening the entry in the menu editor first works around it - the editor keeps a 4 KiB buffer around, shifting later allocations down by a page so that this one merges and the map does not grow.

The reporter verified the same code in 12.3.1, 12.5.2, 12.7.0, 12.8.0, 12.9.1, and trunk (bc8b9536). QEMU does not reproduce it (with 1 to 8 GiB of RAM the allocation always merged): it takes both a splitting allocation and a highest entry the HHDM has to map, and on most machines the top of the map is reserved MMIO, which the HHDM leaves out.

Changes

  1. common/protos/limine.c, in both builders: allocate memmap_entries + 2 entries and read _memmap_entries after the allocation, so the copy reflects the map as it exists after its own allocation.
  2. The headroom is 2, not the more obvious 1: a single ext_mem_alloc() boils down to one pmm_new_entry() call, which appends the allocation entry itself, plus at most one split remainder - the latter only in the x86 case where the chosen usable entry spans the 4 GiB boundary and the allocation is clipped to the below-4-GiB limit (the "nested" case in pmm_new_entry()). Merging can only shrink the count, so +2 covers the provable worst case.

AI assistance disclosure

The fix itself was created with material AI help (gemini-4-argon), and the commit carries the corresponding Assisted-by: trailer.

Fixes #687

…cation

Assisted-by: Antigravity:gemini-4-argon
Signed-off-by: hotline1337 <denuvo@tuta.io>
@Mintsuki
Mintsuki merged commit 70a376c into Limine-Bootloader:trunk Oct 6, 2026
1 of 2 checks passed
@Mintsuki

Mintsuki commented Oct 6, 2026

Copy link
Copy Markdown
Member

LGTM, thanks!

@nil0ft

nil0ft commented Oct 6, 2026

Copy link
Copy Markdown

Thanks!

nil0ft pushed a commit to SlopLabs/slopos that referenced this pull request Oct 6, 2026
PR #688 asks memmap_entries + 2 where the tested patch asks + 1.
+2 is the bound: a usable entry across 4 GiB splits in three. On
the laptop both ask for one page at one address, so the tested
boot stands for #688. With the split forced under QEMU, 12.9.1
drops the top entry and both diffs keep it.

Refs Limine-Bootloader/Limine#687, Limine-Bootloader/Limine#688
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.

3 participants