diff --git a/kernel/kernel.c b/kernel/kernel.c index a47fbea..bf8b1f0 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,5 +1,5 @@ - #include "libc/stdio.h" +#include "pmm.h" #include "printf/printf_support.h" #include "terminal/terminal.h" #include @@ -15,6 +15,12 @@ static volatile struct limine_entry_point_request entry_request = { .entry = entry, }; +struct limine_memmap_request limine_memmap_request = { + .id = LIMINE_MEMMAP_REQUEST, + .revision = 0, + .response = NULL, +}; + static void hcf(void) { asm("cli"); @@ -43,6 +49,11 @@ void entry(void) printf("Hello Kernel Mode!\n"); + pmm_t pmm; + pmm_init(&pmm, limine_memmap_request.response); + void* page = pmm_alloc_pages(&pmm, 1); + printf("ALLOCATED PAGE: %p\n", page); + cleanup: hcf(); } diff --git a/kernel/pmm.c b/kernel/pmm.c new file mode 100644 index 0000000..37eda24 --- /dev/null +++ b/kernel/pmm.c @@ -0,0 +1,67 @@ +#include "pmm.h" + +#include "utility/macro.h" + +void pmm_init(pmm_t* pmm, struct limine_memmap_response* limine_memmap) +{ + pmm_node_t* current = NULL; + + for (size_t i = 0; i < limine_memmap->entry_count; i++) { + struct limine_memmap_entry* entry = limine_memmap->entries[i]; + if (LIMINE_MEMMAP_USABLE == entry->type) { + pmm_node_t node = { .next = NULL, + .prev = current, + .base = (void*)(entry->base + PAGE_SIZE), + .no_pages = (entry->length / PAGE_SIZE) - 1, + .kind = PMM_NOT_ALLOCATED }; + pmm_node_t* node_ptr = (void*)entry->base; + *node_ptr = node; + + if (NULL == current) { + pmm->first_node = node_ptr; + } else { + current->next = node_ptr; + } + current = node_ptr; + } + } +} + +void* pmm_alloc_pages(pmm_t* pmm, size_t no_pages) +{ + pmm_node_t* current = pmm->first_node; + + while (NULL != current) { + if ((PMM_NOT_ALLOCATED == current->kind) + && (current->no_pages >= no_pages)) { + break; + } + + current = current->next; + } + + if (NULL == current) { + return NULL; + } + + size_t leftover_pages = current->no_pages - no_pages; + if (0 == leftover_pages) { + current->kind = PMM_ALLOCATED; + return current->base; + } + + pmm_node_t* new_node = // may has bug + add_pointer(pmm_node_t*, current->base, no_pages * PAGE_SIZE); + + new_node->next = current->next; + new_node->prev = current; + new_node->base = add_pointer(void*, new_node->base, PAGE_SIZE); + new_node->no_pages = leftover_pages - 1; + new_node->kind = PMM_NOT_ALLOCATED; + + current->next = new_node; + current->no_pages = no_pages; + current->kind = PMM_ALLOCATED; + + return current->base; +} diff --git a/kernel/pmm.h b/kernel/pmm.h new file mode 100644 index 0000000..1a61e1a --- /dev/null +++ b/kernel/pmm.h @@ -0,0 +1,24 @@ +#include +#include + +#define PAGE_SIZE ((size_t)0x1000) + +typedef enum { + PMM_NOT_ALLOCATED, + PMM_ALLOCATED, +} pmm_node_kind_t; + +typedef struct pmm_node_t { + struct pmm_node_t* next; + struct pmm_node_t* prev; + void* base; + size_t no_pages; + pmm_node_kind_t kind; +} pmm_node_t; + +typedef struct { + pmm_node_t* first_node; +} pmm_t; + +void pmm_init(pmm_t* pmm, struct limine_memmap_response* limine_memmap); +void* pmm_alloc_pages(pmm_t* pmm, size_t no_pages);