added physical memory manager

This commit is contained in:
2026-07-03 11:43:14 +01:00
parent cb2f49cb48
commit 6312e84262
4 changed files with 80 additions and 19 deletions
+25 -9
View File
@@ -32,10 +32,11 @@ Defined in `src/root.zig`, the shared loader↔kernel contract:
```zig
pub const MemoryKind = enum(u32) {
usable, // free RAM the kernel may allocate
reserved, // firmware / MMIO / kernel image — never hand out
reserved, // firmware / kernel image — real RAM, but never hand out
reclaimable, // usable once boot-time structures are done with
acpi_tables, // parse, then reclaim
acpi_nvs, // preserve across sleep
mmio, // device registers / reserved address space — not RAM at all
};
pub const MemoryRegion = extern struct {
@@ -70,12 +71,20 @@ pub const BootInfo = extern struct {
Two functions in `src/efi.zig`, called from `exitBootServices`:
- **`classify`** maps each UEFI memory type to a `MemoryKind`:
- **`classify`** maps each UEFI descriptor to a `MemoryKind`:
`conventional_memory → usable`; `boot_services_code`/`boot_services_data →
reclaimable` (free once we've exited); `acpi_reclaim_memory → acpi_tables`;
`acpi_memory_nvs → acpi_nvs`; **everything else → reserved** (the safe default).
Our own `loader_data` — the kernel image and these buffers — falls into
`reserved`, so it won't be handed out until the kernel deliberately reclaims it.
One subtlety: **a region that isn't writeback-cacheable (the descriptor's `wb`
attribute) is classified `mmio` regardless of type.** UEFI overloads
`reserved_memory_type` for both reserved RAM *and* reserved address-space windows
(PCIe config space, device BARs); the cache attribute is what actually tells them
apart, since only real RAM is writeback-cacheable. Without this, a QEMU q35 guest
reports ~12 GiB of "reserved" that is really a PCIe address hole near the 1 TB
mark — not memory at all.
- **`convertMemoryMap`** walks the UEFI descriptors (striding by
`descriptor_size`, *not* `@sizeOf`), classifies each, and writes danos
`MemoryRegion`s into an output buffer, coalescing adjacent same-kind regions.
@@ -111,17 +120,24 @@ for (regions) |r| {
}
```
Today `kmain` just prints the region count and total usable RAM — enough to prove
the handoff works. Booted in QEMU with 128 MiB, it reports something like:
`kmain` summarises the map to prove the handoff works. Booted in QEMU with
128 MiB, it reports:
```
mem regions: 35
usable RAM : 77 MiB
danos: physical memory
total RAM : 0.12 GiB (127 MiB) - RAM the firmware reported
usable : 77 MiB - free now; owned by the frame allocator
reclaimable: 44 MiB - UEFI boot-services memory, free after exit
reserved : 6 MiB - kernel image, ACPI, runtime services
regions : 35 - entries in the firmware memory map
```
with the balance being `reclaimable` boot-services memory (~44 MiB) and a large
`reserved` span that is mostly MMIO address space, not RAM. Those figures summing
back to ~128 MiB is the sanity check that nothing was dropped.
The `usable` figure is only ~77 of ~127 MiB because most of the rest is
`reclaimable` boot-services memory — real RAM we'll take back once we implement
reclaiming, not memory that's gone. `total` counts only writeback-cacheable RAM,
so the ~12 GiB PCIe address hole is excluded (it's `mmio`), and the three RAM
categories summing back to the firmware's total is the sanity check that nothing
was dropped.
## How Raspberry Pi will fit