From 6cb8b4372a06c2904b970d5254d7916bb3580c02 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Thu, 9 Aug 2018 22:19:34 +0200 Subject: [PATCH] Implement page allocation --- core/klibc.c | 8 ++++++++ core/klibc.h | 1 + core/main.c | 15 ++++++++------- core/mem.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++---- core/mem.h | 3 +++ 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/core/klibc.c b/core/klibc.c index e0aea0c..5498b4d 100644 --- a/core/klibc.c +++ b/core/klibc.c @@ -9,3 +9,11 @@ void *memcpy(void *dst, const void *src, size_t n) } return dst; } + +void *memset(void *src, int c, size_t n) +{ + for (char *ptr = (char *)src; n > 0; n--, ptr++) { + *ptr = (char)c; + } + return src; +} diff --git a/core/klibc.h b/core/klibc.h index fa7011e..0b233c9 100644 --- a/core/klibc.h +++ b/core/klibc.h @@ -2,3 +2,4 @@ #include "stdarg.h" void *memcpy(void *dest, const void *src, size_t n ); +void *memset(void *s, int c, size_t n); diff --git a/core/main.c b/core/main.c index 14fb14f..b1ac5da 100644 --- a/core/main.c +++ b/core/main.c @@ -4,20 +4,21 @@ #include "interrupt.h" #include "io.h" #include "irq.h" +#include "klibc.h" #include "mem.h" #include "multiboot.h" #include "pit.h" #include "stdarg.h" #include "vga.h" -#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit))) +#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit))) void cpuid(int code, uint32_t *a, uint32_t *d) { asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx"); } - -// Multiboot information available here : https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#kernel_002ec +// Multiboot information available here : +// https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#kernel_002ec void kmain(unsigned long magic, unsigned long addr) { unsigned long upper_mem = 0; @@ -31,23 +32,23 @@ void kmain(unsigned long magic, unsigned long addr) if (magic == MULTIBOOT_BOOTLOADER_MAGIC) { // Get loaded by Grub wuth mutliboot version 1 multiboot_info_t *mbi = (multiboot_info_t *)addr; /* Are mem_* valid? */ - if (CHECK_FLAG(mbi->flags, 0)){ + if (CHECK_FLAG(mbi->flags, 0)) { printf("mem_lower = %dKB mem_upper %dKB\n", mbi->mem_lower, mbi->mem_upper); upper_mem = mbi->mem_upper; } /* Is boot_device valid? */ - if (CHECK_FLAG(mbi->flags, 1)){ + if (CHECK_FLAG(mbi->flags, 1)) { printf("boot_device = %d\n", mbi->boot_device); } /* Is the command line passed? */ - if (CHECK_FLAG(mbi->flags, 2)){ + if (CHECK_FLAG(mbi->flags, 2)) { printf("cmdline = %s\n", (char *)mbi->cmdline); } } - if(upper_mem == 0){ + if (upper_mem == 0) { printf("Cannot get upper phy mem bound. Using default value 32MB\n"); upper_mem = 32 * 1024; } diff --git a/core/mem.c b/core/mem.c index 4929278..4a11ad3 100644 --- a/core/mem.c +++ b/core/mem.c @@ -1,22 +1,68 @@ #include "mem.h" +#include "list.h" #include "vga.h" -struct mem_desc *page_desc = (struct mem_desc *)&__ld_kernel_end; +static struct mem_desc *page_desc = (struct mem_desc *)&__ld_kernel_end; +static struct mem_desc *free_page; +static struct mem_desc *used_page; +static unsigned long bottom_mem; +static unsigned long top_mem; + int memInit(unsigned long upper_mem) { - printf("Free Mem going from %d to %d\n", &__ld_kernel_end, upper_mem *1024); + printf("Free Mem going from %d to %d\n", &__ld_kernel_end, upper_mem * 1024); unsigned long memdesc_end = (unsigned long)page_desc + ((upper_mem) / (PAGE_SIZE / 1024)) * sizeof(struct mem_desc); uint lastUsed = (memdesc_end >> PAGE_SHIFT) + 1; + list_init(free_page); + list_init(used_page); + bottom_mem = lastUsed; + top_mem = upper_mem; for (uint i = 0; i < (upper_mem / (PAGE_SIZE / 1024)); i++) { struct mem_desc *mem = &page_desc[i]; - if (i < lastUsed) + if (i < lastUsed) { mem->ref = 1; - else + list_add_tail(used_page, mem); + } else { mem->ref = 0; + list_add_tail(free_page, mem); + } mem->phy_addr = i * PAGE_SIZE; } return 0; } + +struct mem_desc *addr2memDesc(unsigned long addr) +{ + if (addr > top_mem || addr < bottom_mem) + return NULL; + int idx = addr >> PAGE_SHIFT; + return page_desc + idx; +} + + +unsigned long allocPage(void) +{ + if (list_is_empty(free_page)) + return (unsigned long)NULL; + struct mem_desc *mem = list_pop_head(free_page); + mem->ref = 1; + list_add_tail(used_page, mem); + return mem->phy_addr; +} + +int unrefPage(unsigned long addr) +{ + struct mem_desc *mem = addr2memDesc(addr); + if (!mem) { + return -1; + } + mem->ref--; + if (mem->ref == 0) { + list_add_tail(free_page, mem); + } + + return 0; +} diff --git a/core/mem.h b/core/mem.h index 9d24821..e0929df 100644 --- a/core/mem.h +++ b/core/mem.h @@ -12,7 +12,10 @@ extern uint32_t __ld_kernel_end; struct mem_desc{ unsigned long phy_addr; unsigned long ref; + struct mem_desc *next, *prev; }; int memInit(unsigned long upper_mem); +unsigned long allocPage(void); +int unrefPage(unsigned long addr);