diff options
Diffstat (limited to 'src/kernel/mm/pmm.cc')
| -rw-r--r-- | src/kernel/mm/pmm.cc | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/kernel/mm/pmm.cc b/src/kernel/mm/pmm.cc new file mode 100644 index 0000000..9b68fcd --- /dev/null +++ b/src/kernel/mm/pmm.cc @@ -0,0 +1,71 @@ +#include "kernel/pmm.h" +#include "drivers/uart.h" + +extern "C" char kernel_end[]; + +namespace PMM +{ + struct Run + { + struct Run *next; + }; + + struct + { + struct Run *freelist; + } kmem; + + inline uint64_t PGROUNDUP(uint64_t a) + { + return (a + PGSIZE - 1) & ~(PGSIZE - 1); + } + + void init() + { + uint64_t start = PGROUNDUP((uint64_t)kernel_end); + + Drivers::uart_puts("PMM: Initializing from"); + + for (uint64_t p = start; p + PGSIZE <= PHYSTOP; p += PGSIZE) + { + free_page((void *)p); + } + } + + void free_page(void* pa) + { + struct Run *r; + if (((uint64_t)pa % PGSIZE) != 0 || (uint64_t)pa < (uint64_t)kernel_end || (uint64_t)pa >= PHYSTOP) + { + Drivers::uart_puts("PMM: Error - Invalid free address\n"); + return; + } + r = (struct Run*)pa; + + r->next = kmem.freelist; + kmem.freelist = r; + + } + + void* alloc_page() + { + struct Run* r; + + r = kmem.freelist; + if (r) + { + kmem.freelist = r->next; + + uint64_t *p = (uint64_t *)r; + for (int i = 0; i < PGSIZE / 8; i++) + { + p[i] = 0; + } + } + else + { + Drivers::uart_puts("PMM: Out of memory!\n"); + } + return (void *)r; + } +}
\ No newline at end of file |
