summaryrefslogtreecommitdiff
path: root/src/kernel/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/mem.c')
-rw-r--r--src/kernel/mem.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/kernel/mem.c b/src/kernel/mem.c
new file mode 100644
index 0000000..2e8173d
--- /dev/null
+++ b/src/kernel/mem.c
@@ -0,0 +1,63 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include "panic.h"
+
+#define DYNAMIC_START (0x10000000)
+#define DYNAMIC_END (DYNAMIC_START + 65536 * 4096)
+#define PAGE_TO_ADDR(n) ((void *)(DYNAMIC_START | ((n) << 12)))
+#define ADDR_TO_PAGE(n) (((uint32_t)(n) & ~DYNAMIC_START) >> 12)
+
+#define MMAP_START (0x00010000)
+#define PAGE_USED(n) ((*(uint8_t *)(MMAP_START + (n >> 3)) >> (n & 7)) & 1)
+#define CLEAR_PAGE(n) *(uint8_t *)(MMAP_START + (n >> 3)) &= ~(1 << (n & 7))
+#define SET_PAGE(n) *(uint8_t *)(MMAP_START + (n >> 3)) |= 1 << (n & 7)
+
+extern const void kernel_bss_end;
+
+uint16_t pages_left;
+
+void init_mmap() {
+ volatile uint8_t *end_ptr = (uint8_t *)(DYNAMIC_END - 1);
+ uint8_t end_val = *end_ptr;
+ *end_ptr = (uint8_t)~end_val;
+ if (*end_ptr != (uint8_t)~end_val)
+ panic("Not enough memory. Must have at least 512MiB.");
+
+ for (uint32_t *m = (uint32_t *)MMAP_START; m < (uint32_t *)(MMAP_START + (65536 / 8)); ++m)
+ *m = 0;
+
+ uint16_t kernel_bss_pages = (((uint32_t)&kernel_bss_end - DYNAMIC_START - 1) >> 12) + 1;
+ for (uint16_t i = 0; i < kernel_bss_pages; ++i)
+ SET_PAGE(i);
+
+ pages_left = 65536 - kernel_bss_pages;
+}
+
+//very inneficient algorithm, just returns first hole big enough.
+//a smarter algorithm might pick the smallest one available,
+//and go by bytes (or dwords) instead of bits where possible.
+void *allocate_pages(uint16_t n) {
+ uint16_t run = 0;
+
+ for (uint32_t page = 0; page < 65536; ++page) {
+ if (PAGE_USED(page))
+ run = 0;
+ else if (++run == n) {
+ uint16_t start = page - run + 1;
+ for (uint32_t i = start; i <= page; ++i)
+ SET_PAGE(i);
+ pages_left -= n;
+ return PAGE_TO_ADDR(start);
+ }
+ }
+
+ return 0;
+}
+
+//in the future, change this to go by bytes or dwords instead of bits.
+void free_pages(void *ptr, uint16_t n) {
+ uint16_t page = ADDR_TO_PAGE(ptr);
+ for (uint32_t i = page; i < page + n; ++i)
+ CLEAR_PAGE(i);
+ pages_left += n;
+} \ No newline at end of file