BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / blob / 4f822f67ee63ef4245ad6bfcd0e3fe04ff6f34a0 / memory / frame.c

// Related

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);
	}
}