Nucleus
Barry Stack-based page frame allocator 4f822f6 (3 years, 3 months ago)
/*
* 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 <stdint.h>
#include <stddef.h>
#include "memory.h"
/* 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)
free_frame(memMap[i].baseHigh + memMap[i].base + j);
}
}