Nucleus
Barry Stack-based page frame allocator 4f822f6 (3 years, 3 months ago)
diff --git a/memory/frame.c b/memory/frame.c
new file mode 100644
index 0000000..35b2fed
--- /dev/null
+++ b/memory/frame.c
@@ -0,0 +1,70 @@
+/*
+ * 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);
+ }
+}