firecracker-microvm/firecracker · error

Only 2MiB hugetlb pages are supported

Error message

Only 2MiB hugetlb pages are supported

What it means

Error "Only 2MiB hugetlb pages are supported" thrown in firecracker-microvm/firecracker.

Source

Thrown at src/vmm/src/vstate/memory.rs:168

        //  1. Round requested_size up to page size -> `size_page_multiple`.
        //  2. mmap(`size_page_multiple + GUEST_MEMORY_ALIGNMENT - page_size`) -> `ptr`.
        //     `ptr` is page-aligned, so the worst-case distance to the next 2 MiB boundary
        //     is `GUEST_MEMORY_ALIGNMENT - page_size` bytes. This guarantees the allocation
        //     contains at least one 2 MiB-aligned region of `size_page_multiple` bytes.
        //  3. Compute `aligned_ptr` = first 2 MiB boundary ≥ `ptr`.
        //  4. munmap the head (`ptr..aligned_ptr`) and tail (`aligned_ptr + size_page_multiple..end`).
        //  5. Return the 2 MiB-aligned region of `size_page_multiple` bytes.
        //
        // Note: when `hugetlb_flags` is set, `page_size` equals `GUEST_MEMORY_ALIGNMENT` (2 MiB),
        // so `alloc_size == size_page_multiple` (no over-allocation). This is correct because the
        // kernel guarantees hugetlb mappings are already aligned to the huge page size.
        if requested_size == 0 {
            return Err(MemoryError::ZeroSize);
        }
        let page_size = match hugetlb_flags {
            0 => host_page_size(),
            flags if flags == libc::MAP_HUGETLB | libc::MAP_HUGE_2MB => mib_to_bytes(2),
            _ => unreachable!("Only 2MiB hugetlb pages are supported"),
        };
        let size_page_multiple = align_up!(requested_size, page_size);

        // Over-allocate to guarantee we can find a 2 MiB-aligned sub-region of the desired size.
        // The over-allocation is `GUEST_MEMORY_ALIGNMENT - page_size` because the mmap return
        // address is page-aligned, so we need at most that many extra bytes to reach the next
        // 2 MiB boundary. For hugetlb (page_size == 2 MiB), this is zero — no over-allocation
        // needed since the kernel already returns 2 MiB-aligned addresses.
        let alloc_size = size_page_multiple + GUEST_MEMORY_ALIGNMENT - page_size;

        // SAFETY: anonymous private mapping with no fd; does not alias existing memory.
        // The returned region is PROT_NONE (inaccessible) until the caller re-maps it.
        let ptr = unsafe {
            libc::mmap(
                std::ptr::null_mut(),
                alloc_size,
                libc::PROT_NONE,
                hugetlb_flags | libc::MAP_PRIVATE | libc::MAP_NORESERVE | libc::MAP_ANONYMOUS,

View on GitHub (pinned to 9384f395f5)

Solutions

  1. Configure the VM memory to use 2MiB hugetlb pages; other hugepage sizes are unsupported.
  2. Mount a hugetlbfs with 2MiB page size and point the memory backend at it.

When it happens

Trigger: Thrown at src/vmm/src/vstate/memory.rs:168 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of firecracker-microvm/firecracker@9384f395f5 (2026-08-19). Data as JSON: /api/errors/991642f2905accd5. Report an issue: GitHub.