aboutsummaryrefslogtreecommitdiff
path: root/kernel/mm
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2025-01-11 12:30:43 -0500
committerRaghuram Subramani <raghus2247@gmail.com>2025-01-11 12:30:43 -0500
commit5cbf0b467e91953d8d072470825ffdf5bd23e049 (patch)
treed52b41ade1c9b5513156553a172759841d3ccac6 /kernel/mm
parent350eb7ff40a007992d28fe597002bc1a3f76e585 (diff)
virtual_mm: Disfunctional implementation of VMM
Diffstat (limited to 'kernel/mm')
-rw-r--r--kernel/mm/virtual_mm/virtual_mm.c104
1 files changed, 101 insertions, 3 deletions
diff --git a/kernel/mm/virtual_mm/virtual_mm.c b/kernel/mm/virtual_mm/virtual_mm.c
index 6350c11..0f55950 100644
--- a/kernel/mm/virtual_mm/virtual_mm.c
+++ b/kernel/mm/virtual_mm/virtual_mm.c
@@ -18,6 +18,8 @@
#include <stdint.h>
+#include <kernel/halt.h>
+
#include <libk/stdio.h>
#include <mm/physical_mm.h>
@@ -26,8 +28,7 @@
extern uint32_t kernel_start;
extern uint32_t kernel_end;
-uint32_t initial_page_directory[PAGE_DIRECTORY_SIZE];
-uint32_t initial_page_table[PAGE_TABLE_SIZE];
+uint32_t *current_page_directory = 0;
bool
virtual_mm_allocate_page(uint32_t *pt_entry)
@@ -75,5 +76,102 @@ virtual_mm_lookup_directory(uint32_t *page_directory, uint32_t virtual_addr)
ALWAYS_INLINE void
virtual_mm_load_page_directory(uint32_t *page_directory)
{
- __asm__("movl %0, %%cr0" ::"r"(page_directory));
+ __asm__("movl %0, %%eax" ::"r"(page_directory) : "%eax");
+ /* For some reason, that colon is required; else the assembler thinks that
+ * %eax doesn't exist :^) */
+ __asm__("movl %%eax, %%cr3" ::: "%eax");
+}
+
+bool
+virtual_mm_switch_page_directory(uint32_t *page_directory)
+{
+ if (!page_directory)
+ return false;
+ current_page_directory = page_directory;
+ virtual_mm_load_page_directory(page_directory);
+
+ return true;
+}
+
+/* TODO: I have absolutely _no_ idea if this works */
+void
+virtual_mm_flush_tlb_entry(uint32_t *virtual_addr)
+{
+ __asm__("cli;"
+ "invlpg (%0);"
+ "sti" ::"r"(virtual_addr));
+}
+
+bool
+virtual_mm_map_page(uint32_t *physical_addr, uint32_t *virtual_addr)
+{
+ uint32_t *pd_entry
+ = &current_page_directory[PAGE_DIRECTORY_INDEX((uint32_t) virtual_addr)];
+
+ /* If the page directory entry isn't present */
+ if (!PTE_IS_PRESENT(*pd_entry)) {
+ uint32_t *page_table = physical_mm_allocate_block();
+ if (!page_table)
+ return false;
+
+ *pd_entry = 0;
+ ADD_ATTRIB(pd_entry, SET_PDE_PRESENT(1));
+ ADD_ATTRIB(pd_entry, SET_PDE_WRITABLE(1));
+ ADD_ATTRIB(pd_entry, SET_PDE_FRAME((uint32_t) page_table));
+ }
+
+ uint32_t *page_table = (uint32_t *) GET_PDE_FRAME(pd_entry);
+ uint32_t *pt_entry = &page_table[PAGE_TABLE_INDEX((uint32_t) virtual_addr)];
+ *pt_entry = 0;
+
+ ADD_ATTRIB(pt_entry, SET_PTE_PRESENT(1));
+ ADD_ATTRIB(pt_entry, SET_PTE_FRAME((uint32_t) physical_addr));
+
+ return true;
+}
+
+ALWAYS_INLINE static void
+virtual_mm_enable_paging(void)
+{
+ __asm__("movl %%cr0, %%eax;"
+ "orl $0x80000000, %%eax;"
+ "movl %%eax, %%cr0" ::
+ : "eax");
+}
+
+void
+virtual_mm_initialize(void)
+{
+ uint32_t *table = physical_mm_allocate_block();
+ if (!table)
+ ASSERT_NOT_REACHED();
+
+ for (uint32_t i = 0; i < 1024; i++)
+ table[i] = 0;
+
+ /* Identity map the first 4MiB (maps 4KiB 1024 times) */
+ for (uint32_t i = 0, physical_addr = 0, virtual_addr = 0; i < 1024;
+ i++, physical_addr += 4096, virtual_addr += 4096) {
+ uint32_t page = 0;
+ ADD_ATTRIB(&page, SET_PTE_PRESENT(1));
+ ADD_ATTRIB(&page, SET_PTE_FRAME(physical_addr));
+
+ table[PAGE_TABLE_INDEX(virtual_addr)] = page;
+ }
+
+ uint32_t *page_directory = physical_mm_allocate_block();
+ if (!page_directory)
+ ASSERT_NOT_REACHED();
+
+ for (uint32_t i = 0; i < 1024; i++)
+ page_directory[i] = 0;
+
+ uint32_t *pd_entry = &page_directory[PAGE_DIRECTORY_INDEX(0)];
+ ADD_ATTRIB(pd_entry, SET_PDE_PRESENT(1));
+ ADD_ATTRIB(pd_entry, SET_PDE_WRITABLE(1));
+ ADD_ATTRIB(pd_entry, SET_PDE_FRAME((uint32_t) table));
+
+ current_page_directory = page_directory;
+ virtual_mm_switch_page_directory(current_page_directory);
+ virtual_mm_enable_paging();
}