{"record":{"id":"991642f2905accd5","repo":"firecracker-microvm/firecracker","slug":"only-2mib-hugetlb-pages-are-supported","errorCode":null,"errorMessage":"Only 2MiB hugetlb pages are supported","messagePattern":"Only 2MiB hugetlb pages are supported","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/vmm/src/vstate/memory.rs","lineNumber":168,"sourceCode":"        //  1. Round requested_size up to page size -> `size_page_multiple`.\n        //  2. mmap(`size_page_multiple + GUEST_MEMORY_ALIGNMENT - page_size`) -> `ptr`.\n        //     `ptr` is page-aligned, so the worst-case distance to the next 2 MiB boundary\n        //     is `GUEST_MEMORY_ALIGNMENT - page_size` bytes. This guarantees the allocation\n        //     contains at least one 2 MiB-aligned region of `size_page_multiple` bytes.\n        //  3. Compute `aligned_ptr` = first 2 MiB boundary ≥ `ptr`.\n        //  4. munmap the head (`ptr..aligned_ptr`) and tail (`aligned_ptr + size_page_multiple..end`).\n        //  5. Return the 2 MiB-aligned region of `size_page_multiple` bytes.\n        //\n        // Note: when `hugetlb_flags` is set, `page_size` equals `GUEST_MEMORY_ALIGNMENT` (2 MiB),\n        // so `alloc_size == size_page_multiple` (no over-allocation). This is correct because the\n        // kernel guarantees hugetlb mappings are already aligned to the huge page size.\n        if requested_size == 0 {\n            return Err(MemoryError::ZeroSize);\n        }\n        let page_size = match hugetlb_flags {\n            0 => host_page_size(),\n            flags if flags == libc::MAP_HUGETLB | libc::MAP_HUGE_2MB => mib_to_bytes(2),\n            _ => unreachable!(\"Only 2MiB hugetlb pages are supported\"),\n        };\n        let size_page_multiple = align_up!(requested_size, page_size);\n\n        // Over-allocate to guarantee we can find a 2 MiB-aligned sub-region of the desired size.\n        // The over-allocation is `GUEST_MEMORY_ALIGNMENT - page_size` because the mmap return\n        // address is page-aligned, so we need at most that many extra bytes to reach the next\n        // 2 MiB boundary. For hugetlb (page_size == 2 MiB), this is zero — no over-allocation\n        // needed since the kernel already returns 2 MiB-aligned addresses.\n        let alloc_size = size_page_multiple + GUEST_MEMORY_ALIGNMENT - page_size;\n\n        // SAFETY: anonymous private mapping with no fd; does not alias existing memory.\n        // The returned region is PROT_NONE (inaccessible) until the caller re-maps it.\n        let ptr = unsafe {\n            libc::mmap(\n                std::ptr::null_mut(),\n                alloc_size,\n                libc::PROT_NONE,\n                hugetlb_flags | libc::MAP_PRIVATE | libc::MAP_NORESERVE | libc::MAP_ANONYMOUS,","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/firecracker-microvm/firecracker/blob/9384f395f5d47f05b68a657525e209f8aa9c8264/src/vmm/src/vstate/memory.rs#L150-L186","documentation":"Error \"Only 2MiB hugetlb pages are supported\" thrown in firecracker-microvm/firecracker.","triggerScenarios":"Thrown at src/vmm/src/vstate/memory.rs:168 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Configure the VM memory to use 2MiB hugetlb pages; other hugepage sizes are unsupported.","Mount a hugetlbfs with 2MiB page size and point the memory backend at it."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"9384f395f5d47f05b68a657525e209f8aa9c8264","analyzedAt":"2026-08-19T05:27:02.517Z","contentChangedAt":"2026-08-19T05:27:02.517Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}