From 0f73efbdc329cac2b85a1ad6dbf6ec89ac9b0731 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 26 Oct 2020 20:17:08 -0400 Subject: [PATCH] add mm module to manage free physical page regions --- src/hos_main.c | 3 ++ src/mbinfo.c | 2 ++ src/mm.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/mm.h | 11 ++++++++ 4 files changed, 90 insertions(+) create mode 100644 src/mm.c create mode 100644 src/mm.h diff --git a/src/hos_main.c b/src/hos_main.c index 0582d05..2ea1fd5 100644 --- a/src/hos_main.c +++ b/src/hos_main.c @@ -3,6 +3,7 @@ #include "mbinfo.h" #include "klog.h" #include "gdt.h" +#include "mm.h" void hos_main(uint32_t mbinfo_addr) { @@ -17,5 +18,7 @@ void hos_main(uint32_t mbinfo_addr) } klog_init(); klog_printf("Welcome to HOS!\n"); + mm_init(); mbinfo_load(); + klog_printf("Found %dKB of usable RAM\n", mm_get_total_ram() / 1024u); } diff --git a/src/mbinfo.c b/src/mbinfo.c index b3739f2..9133410 100644 --- a/src/mbinfo.c +++ b/src/mbinfo.c @@ -3,6 +3,7 @@ #include "mem.h" #include #include "klog.h" +#include "mm.h" static uint32_t mbinfo[2048]; @@ -46,6 +47,7 @@ static void mbinfo_process_tag(const multiboot2_info_tag_t * tag) klog_printf("Memory region %16lx : %16lx\n", entry->base_addr, entry->length); + mm_register_ram_region(entry->base_addr, entry->length); } entry = (multiboot2_info_memory_map_entry_t *)((uintptr_t)entry + mmap_info->entry_size); } diff --git a/src/mm.c b/src/mm.c new file mode 100644 index 0000000..39dc112 --- /dev/null +++ b/src/mm.c @@ -0,0 +1,74 @@ +#include "mm.h" +#include "klog.h" + +#define PAGE_SIZE 4096u + +typedef struct mm_page_entry_s { + size_t count; + struct mm_page_entry_s * next; +} mm_region_entry_t; + +static mm_region_entry_t * mm_next_free_region; +static size_t mm_free_page_count; +static size_t mm_total_ram; + +extern uint8_t _hos_mem_start; +extern uint8_t _hos_mem_end; + +static void mm_add_ram_region(uint32_t base, uint32_t size) +{ + mm_region_entry_t * region = (mm_region_entry_t *)base; + size_t pages = size / PAGE_SIZE; + region->count = pages; + region->next = mm_next_free_region; + mm_next_free_region = region; + mm_total_ram += size; + mm_free_page_count = pages; +} + +void mm_register_ram_region(uint64_t base, uint32_t size) +{ + size &= ~(PAGE_SIZE - 1u); + /* Ignore any RAM region above 4GB. */ + if (base >= 0x100000000ull) + { + return; + } + if ((base + size) > 0x100000000ull) + { + size = (uint32_t)(0x100000000ull - base); + } + /* Add regions before and after kernel RAM. */ + uint32_t region_base = (uint32_t)base; + if (region_base < (uint32_t)&_hos_mem_start) + { + /* RAM region begins before kernel RAM. */ + uint32_t this_sz = size; + if ((region_base + this_sz) > (uint32_t)&_hos_mem_start) + { + this_sz = (uint32_t)&_hos_mem_start - region_base; + } + mm_add_ram_region(region_base, this_sz); + } + if ((region_base + size) > (uint32_t)&_hos_mem_end) + { + /* RAM region ends after kernel RAM. */ + uint32_t this_sz = size; + if (region_base < (uint32_t)&_hos_mem_end) + { + this_sz = (region_base + size) - (uint32_t)&_hos_mem_end; + region_base = (uint32_t)&_hos_mem_end; + } + mm_add_ram_region(region_base, this_sz); + } +} + +void mm_init(void) +{ + mm_total_ram = &_hos_mem_end - &_hos_mem_start; +} + +size_t mm_get_total_ram(void) +{ + return mm_total_ram; +} diff --git a/src/mm.h b/src/mm.h new file mode 100644 index 0000000..0661fa9 --- /dev/null +++ b/src/mm.h @@ -0,0 +1,11 @@ +#ifndef MM_H +#define MM_H + +#include +#include + +void mm_init(void); +void mm_register_ram_region(uint64_t base, uint32_t size); +size_t mm_get_total_ram(void); + +#endif