/* * This file controls the page frame allocator. It is the core of the physical * memory manager. The kernel heap and paging systems both sit on top of this. * It keeps track of which frames of physical memory a free and hands them out * as needed. */ #include #include #include #include /* Types of an E820 Memory Map Entry */ enum E820Type { E820_NONE, E820_USABLE, E820_RESERVED, E820_RECLAIMABLE, E820_NVS, E820_BAD, }; /* Structure of an E820 Memory Map Entry */ struct E820Entry { uint32_t size; uint32_t base, baseHigh; uint32_t length, lengthHigh; uint32_t type; } __attribute__((packed)); static uintptr_t nextFrame; /* Allocate a page frame */ uintptr_t alloc_frame(void) { uintptr_t frame = nextFrame; nextFrame = *((uintptr_t *) frame); *((uintptr_t *) frame) = 0; return frame; } /* Free a page frame */ void free_frame(uintptr_t frame) { *((uintptr_t *) frame) = nextFrame; nextFrame = frame; } /* Setup the page frame allocator */ void init_frames(uint32_t size, void *addr) { /* * When the kernel starts, the bootloader passes the kernel a map of * memory. This map must be read so the memory manager can avoid bad * areas of memory and areas that are mapped to hardware, ACPI, etc. */ size_t i, j; struct E820Entry *memMap = addr; for (i = 0; i < size / sizeof(struct E820Entry); i++) { if (memMap[i].baseHigh > 0 || memMap[i].base > 0xFFFFFFFF || memMap[i].type != E820_USABLE) continue; for (j = 0; j < memMap[i].length; j += PAGE_SIZE) { if ((memMap[i].base + j) >= 0x100000 && (memMap[i].base + j) < 0x180000) continue; free_frame(memMap[i].baseHigh + memMap[i].base + j); } } }