summaryrefslogtreecommitdiff
path: root/src/kernel/libs/page.c
diff options
context:
space:
mode:
authorBrett Weiland <brett_weiland@bpcspace.com>2021-03-19 10:54:25 -0500
committerBrett Weiland <brett_weiland@bpcspace.com>2021-03-19 10:54:25 -0500
commit66289aa8ecfa07b20bad424eb9860b196641ef52 (patch)
tree9fb3915b5cb18d9f2c1f4648d3bf3fb56396509f /src/kernel/libs/page.c
first commit
Diffstat (limited to 'src/kernel/libs/page.c')
-rw-r--r--src/kernel/libs/page.c107
1 files changed, 107 insertions, 0 deletions
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 <printf.h>
+#include <paging.h>
+#include <stdint.h>
+
+// 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;
+}