From 66289aa8ecfa07b20bad424eb9860b196641ef52 Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Fri, 19 Mar 2021 10:54:25 -0500 Subject: first commit --- src/kernel/libs/page.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/kernel/libs/page.c (limited to 'src/kernel/libs/page.c') diff --git a/src/kernel/libs/page.c b/src/kernel/libs/page.c new file mode 100644 index 0000000..88d0c2f --- /dev/null +++ b/src/kernel/libs/page.c @@ -0,0 +1,107 @@ +#include +#include +#include + +// for now, this will always remain the same. +// If this ever isn't the case, we'll add paramaters to the paging functions. +// We will also never need to mess with many bits, +// as we are not implimenting security for a bare metal fractal generator. +// Also, is this really the cleanest way to do things? + +//after we get paging working, we can probably remove these structs and replace them with plain old uint_16ts. + +void debug_print_memory() { + struct memory_table *memtable = (struct memory_table *)&_meminfo_loc; + printf(" __________________________________________________________________________\n"); + printf("| type\tstart\t\t\tend\t\t\tsize\t\t |\n"); + printf("|--------------------------------------------------------------------------|\n"); + for(unsigned int i = 0; memtable[i].length > 0; i++) { + printf("| %u %u\t0x%p\t0x%p\t0x%p |\n", memtable[i].type, memtable[i].ACPI, memtable[i].base, (memtable[i].base + memtable[i].length), memtable[i].length); + } + printf("----------------------------------------------------------------------------\n"); +} + + +/** + * You can critisise the quality of this function all you want, it's messy due to planning mistakes + * and I'm planning on sanatising it. + * BUT, don't critisise it _just_ for using goto, that's bullshit. See the following links. + * + * https://www.kernel.org/doc/html/v4.17/process/coding-style.html "goto" section + * https://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/ +**/ + +bool map_page(uintptr_t virtual_addr, uintptr_t physical_addr, uint8_t size) { + printf("map page called\n"); + if((virtual_addr % (1 << size)) || (physical_addr % (1 << size))) { + return 0; + } + page_table *table = (page_table *)PAGEMAP_LOCATION; + int pte_i = (virtual_addr >> 12) & 0x1ff; + int pde_i = (virtual_addr >> 21) & 0x1ff; + int pdpe_i = (virtual_addr >> 30) & 0x1ff; + int pml4e_i = (virtual_addr >> 39) & 0x1ff; + //TODO remove this debugging info + printf("Virtual offsets:\npte:\t\t%i\npde:\t\t%i\npdpe:\t\t%i\npml4e\t\t%i\n", pte_i, pde_i, pdpe_i, pml4e_i); + + if(table->pml4e[pml4e_i].present) { + if(table->pml4e[pml4e_i].base_ptr != (uintptr_t)&table->pdpe[pdpe_i] >> 12) goto error; + if(table->pdpe[pdpe_i].present) { + if(size == PAGE_SIZE_1G) { + if(table->pdpe[pdpe_i].base_ptr == (uintptr_t)physical_addr >> 30 & 0x1ff) + return true; + goto error; + } + if(table->pdpe[pdpe_i].base_ptr != (uintptr_t)&table->pde[pde_i] >> 12) goto error; + + if(table->pde[pde_i].present) { + if(size == PAGE_SIZE_2M) { + if(table->pde[pde_i].base_ptr == (uintptr_t)physical_addr >> 21 & 0x1ff) + return true; + goto error; + } + if(table->pde[pde_i].base_ptr != (uintptr_t)&table->pte[pte_i] >> 12) goto error; + if(table->pte[pte_i].present) { + if(table->pte[pte_i].base_ptr != ((physical_addr >> 12) & 0x1ff)) goto error; + return true; + } + else goto mod_page_pte; + } + else goto mod_page_pde; + } + else goto mod_page_pdpe; + } + else { + table->pml4e[pml4e_i].base_ptr = (uintptr_t)&table->pdpe[pdpe_i] >> 12; + table->pdpe[pml4e_i].read_write = 1; + table->pml4e[pml4e_i].present = 1; +mod_page_pdpe: + table->pdpe[pdpe_i].read_write = 1; + if(size == PAGE_SIZE_1G) { + table->pdpe[pdpe_i].size = 1; + table->pdpe[pdpe_i].base_ptr = physical_addr >> 30; + table->pdpe[pdpe_i].present = 1; + return true; + } + table->pdpe[pdpe_i].base_ptr = (uintptr_t)&table->pde[pde_i] >> 12; + table->pdpe[pdpe_i].present = 1; +mod_page_pde: + table->pde[pde_i].read_write = 1; + if(size == PAGE_SIZE_2M) { + table->pde[pde_i].size = 1; + table->pde[pde_i].base_ptr = physical_addr >> 21; + table->pde[pde_i].present = 1; + return true; + } + table->pde[pde_i].base_ptr = (uintptr_t)&table->pte[pte_i] >> 12; + table->pde[pde_i].present = 1; +mod_page_pte: + table->pte[pte_i].base_ptr = (physical_addr >> 12); + table->pte[pte_i].read_write = 1; + table->pte[pte_i].present = 1; + return true; + } +error: + printf("Page allocation error!\n"); + return false; +} -- cgit v1.2.3