diff options
Diffstat (limited to 'src/kernel/mem.c')
-rw-r--r-- | src/kernel/mem.c | 63 |
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 |