#pragma once // Memory layout #define EXTMEM 0x100000 // Start of extended memory // Top of usable physical memory. A *variable*, read from the firmware's E820 // map at boot -- see kernel/arch/x86_64/e820.c. It used to be the constant // below, which was not a limit on what the kernel used but an assertion that // exactly 224 MB existed: less and the allocator walked off the end of RAM, // more and it was invisible. // // The macro spelling is kept so that the twenty-odd call sites read the same as // they always did. It must not be used before e820_init(), which runs first // thing in main() for that reason. #ifndef __ASSEMBLER__ extern uint64 phystop; #define PHYSTOP phystop #endif // PHYSTOP alone describes memory as one run ending at a top address, which is // what a BIOS map usually looks like and what UEFI never does: OVMF drops an // ACPI NVS region at 0x800000, so the run containing the kernel ends at 8 MB // and everything above the hole was invisible. The usable regions are // therefore kept as a list as well, and kinit1() frees each one rather than // walking a single range from the kernel's end to the top. // // PHYSTOP still means what it always did -- the top of what kalloc may hand // out, and the bound kfree() rejects pages above -- so every existing call // site is unaffected. #define MEMREGION_MAX 64 #ifndef __ASSEMBLER__ struct memregion { uint64 base; // first byte, page aligned uint64 end; // one past the last byte, page aligned }; extern struct memregion mem_usable[MEMREGION_MAX]; extern int nmem_usable; // The top of the low region: where the DMA arena is carved from, and the // ceiling for kinit1(). Always below DIRECTMAP_BOOT, and separate from // `phystop` because a device is not obliged to be able to reach the top of // memory -- an RTL8139's buffer address register is thirty-two bits wide. extern uint64 lowtop; #endif // What to assume when the firmware gives us nothing usable: the old constant, // so that path behaves exactly as the kernel always did. #define PHYSTOP_FALLBACK 0xE000000ULL // The most RAM the kernel will use. // // This was 0xC0000000 -- three gigabytes -- because kvmalloc() mapped exactly // four 1 GB pages and the fourth was marked uncached for the PCI hole. On a // laptop with sixteen gigabytes that threw away thirteen of them, silently. // // kvmalloc() now maps as many 1 GB pages as the machine has RAM, so the limit // is the page table rather than a constant: the kernel PDPT has 512 entries // and ioremap takes what the direct map does not, so 256 GB of RAM still // leaves 248 GB of device window. A machine with more than this gets the rest // ignored, with a line saying so. // // It was 64 GB while handing memory to the allocator meant writing every page // of it at boot. kalloc.c keeps never-used memory as ranges now, so a bigger // machine costs nothing until its memory is used. #define PHYSTOP_MAX (256ULL << 30) // What the *loader's* page tables cover, and therefore the ceiling on anything // that runs before kvmalloc() builds the kernel's own. // // kinit1() frees pages by writing a free-list pointer into each one, so every // page it touches has to be mapped at the time. Before kvmalloc that means the // low four gigabytes and nothing else, which is why freeing memory happens in // two passes -- see kinit_high(). #define DIRECTMAP_BOOT (4ULL << 30) // Below this the kernel image, its page tables and the DMA arena do not fit. #define PHYSTOP_MIN (24ULL * 1024 * 1024) // Key addresses for address space layout #define KERNBASE 0xFFFF800000000000 // First kernel virtual address // Where the kernel is placed in physical memory, and linked above KERNBASE. // // 16 MB, not the 1 MB xv6 used. The kernel is 34 MB with the RAM disk in it, // and from 1 MB that ran across 8 MB, where OVMF keeps ACPI NVS memory -- // which outlives the firmware, so the kernel was copied over it after // ExitBootServices on every boot. Firmware keeps its leftovers low; above // 16 MB is where a machine is most reliably empty. kernel/kernel.ld repeats // this number and has to agree. #define KERNPHYS 0x1000000 #define KERNLINK (KERNBASE+KERNPHYS) // Address where kernel is linked // The LDLS window, in the top 2 GB, where a Linux module expects to live. See // ldls_vm_init() in kernel/arch/x86_64/vm.c. // // LDLS_VMEMMAP 1 GB Linux's `struct page` array, 64 bytes per frame -- // enough for 64 GB, not for all of PHYSTOP_MAX; a // frame above that has no struct page. Backed on demand. // LDLS_KALIAS 512 MB the kernel image again, from physical zero // LDLS_MODBASE 512 MB modules, their stacks and their vmalloc #define LDLS_VMEMMAP 0xFFFFFFFF40000000ULL #define LDLS_KALIAS 0xFFFFFFFF80000000ULL #define LDLS_MODBASE 0xFFFFFFFFA0000000ULL #define LDLS_MODEND 0xFFFFFFFFC0000000ULL // A kernel address, as a module sees it. #define LDLS_ALIAS(a) ((uint64)(a) - KERNBASE + LDLS_KALIAS) #ifndef __ASSEMBLER__ static inline addr_t v2p(void *a) { return ((addr_t)(a)) - ((addr_t)KERNBASE); } static inline void *p2v(addr_t a) { return (void *)((a) + ((addr_t)KERNBASE)); } #endif #define V2P(a) (((addr_t) (a)) - KERNBASE) #define P2V(a) (((void *) (a)) + KERNBASE) #define V2P_WO(x) ((x) - KERNBASE) // same as V2P, but without casts #define P2V_WO(x) ((x) + KERNBASE) // same as P2V, but without casts