|
13 | 13 | #include <stddef.h> |
14 | 14 |
|
15 | 15 | /** |
16 | | - * @brief Initialise the kernel heap. |
17 | | - * |
18 | | - * Sets up internal data structures required for dynamic memory allocation. |
19 | | - * Should be called early during kernel initialisation. |
| 16 | + * @brief Initialises the kernel’s dynamic memory and DMA-friendly “low heap”. |
| 17 | + * |
| 18 | + * @details |
| 19 | + * `init_heap()` brings up two complementary allocation domains and reconciles the |
| 20 | + * bootloader’s memory hand-off into something the kernel can safely and efficiently |
| 21 | + * allocate from: |
| 22 | + * |
| 23 | + * 1) **Low heap (fixed, DMA-friendly window).** |
| 24 | + * - Automatically locates a *contiguous 12 MB* region of **USABLE** RAM below 4 GiB |
| 25 | + * and assigns it to `LOW_HEAP_START` / `LOW_HEAP_MAX` (both `uint32_t`). |
| 26 | + * - This window is reserved exclusively for the bump allocator used by |
| 27 | + * `kmalloc_low()` and returns **32-bit physical addresses** suitable for legacy |
| 28 | + * devices and DMA engines that cannot address high memory. |
| 29 | + * - The low-heap window is deliberately **excluded** from the general allocator to |
| 30 | + * avoid fragmentation and to guarantee that drivers always have the expected |
| 31 | + * 12 MB of low physical memory available. |
| 32 | + * |
| 33 | + * 2) **General heap (primary + additional regions).** |
| 34 | + * - Chooses the *largest* **USABLE** memmap entry as the primary arena and |
| 35 | + * initialises the general allocator (`ta_init`) over it, **carving out** the |
| 36 | + * low-heap window if they overlap. |
| 37 | + * - Iterates over all remaining **USABLE** entries and adds them with |
| 38 | + * `ta_add_region`, again **clipping out** the low-heap window so it is never |
| 39 | + * accidentally pooled into the general heap. |
| 40 | + * |
| 41 | + * 3) **Selective reclamation of bootloader allocations.** |
| 42 | + * - Walks all **Bootloader Reclaimable** (BLR) entries and returns them to the |
| 43 | + * general heap *except* when either of the following is true: |
| 44 | + * • the region is “small” (currently < 1 MB), which typically holds loader |
| 45 | + * scaffolding such as page tables, descriptor tables, or tiny request |
| 46 | + * structs; or |
| 47 | + * • the region contains any *live* pointer supplied by the bootloader |
| 48 | + * (e.g., Limine response structures, GDT base, CR3), in which case the |
| 49 | + * whole BLR span is kept. |
| 50 | + * - This yields the large BLR “scratch” arenas while conservatively preserving |
| 51 | + * small or still-referenced chunks. The result is that almost all of the |
| 52 | + * bootloader’s memory footprint becomes usable to the kernel immediately. |
| 53 | + * |
| 54 | + * **What is *not* added to the general heap** |
| 55 | + * - **Kernel+Modules** regions (the kernel image and loaded modules). |
| 56 | + * - The **Framebuffer** region. |
| 57 | + * - Any **ACPI NVS**, **ACPI Reclaimable**, **Bad Memory** or **Reserved** ranges. |
| 58 | + * |
| 59 | + * **Why this design?** |
| 60 | + * - The low heap provides a guaranteed, contiguous, sub-4 GB pool for drivers and |
| 61 | + * DMA without requiring the kernel to juggle bounce buffers or IOMMU mappings. |
| 62 | + * - Carving the low heap out once, and everywhere, prevents subtle re-introduction |
| 63 | + * into the general allocator. |
| 64 | + * - Conservative BLR reclamation gives you back the big win (hundreds of MB on |
| 65 | + * typical firmware) with minimal complexity, while avoiding the risk of freeing |
| 66 | + * loader memory that is still referenced during early boot. |
| 67 | + * |
| 68 | + * Should be called **once**, early in kernel initialisation, before any dynamic |
| 69 | + * memory use by subsystems or drivers. |
20 | 70 | */ |
21 | 71 | void init_heap(void); |
22 | 72 |
|
|
0 commit comments