summaryrefslogtreecommitdiff
path: root/src/kernel/mm/vm.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2025-12-09 00:57:38 +0800
committerRichard Qin <richard.qin.x@gmail.com>2025-12-09 00:57:38 +0800
commitc36e1b5e5e069ce1735dcc2a94aa45ba72ea2441 (patch)
tree34be19b553615cfe36a556452e3b7ebad5276216 /src/kernel/mm/vm.cc
parent8cf8be522133548ee25fdcb0258ddf3950a68bcf (diff)
downloadlume-c36e1b5e5e069ce1735dcc2a94aa45ba72ea2441.tar.gz
lume-c36e1b5e5e069ce1735dcc2a94aa45ba72ea2441.tar.xz
feat: Initial PMM implementation
Introduce the foundational Physical Memory Manager (PMM) and restructure the project for modularity. Implemented basic PMM and related memory management headers (mm/pmm.h, mm/vm.h). Updated Makefile and build process to support new modular structure.
Diffstat (limited to 'src/kernel/mm/vm.cc')
-rw-r--r--src/kernel/mm/vm.cc100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/kernel/mm/vm.cc b/src/kernel/mm/vm.cc
new file mode 100644
index 0000000..3c14d40
--- /dev/null
+++ b/src/kernel/mm/vm.cc
@@ -0,0 +1,100 @@
+#include "kernel/mm.h"
+#include "kernel/pmm.h"
+#include "drivers/uart.h"
+#include "common/types.h"
+
+extern "C" char text_start[];
+extern "C" char text_end[];
+extern "C" char rodata_start[];
+extern "C" char rodata_end[];
+extern "C" char data_start[];
+extern "C" char kernel_end[];
+
+namespace VM
+{
+ pagetable_t kernel_pagetable;
+
+ #define PX(level, va) ((((uint64)va) >> (12 + 9 * (level))) & 0x1FF)
+ #define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)
+ #define PTE2PA(pte) (((pte) >> 10) << 12)
+
+ pte_t *walk(pagetable_t pagetable, uint64 va, int alloc)
+ {
+ for (int level = 2; level > 0; level--)
+ {
+ pte_t *pte = &pagetable[PX(level, va)];
+
+ if (*pte & PTE_V)
+ {
+ pagetable = (pagetable_t)PTE2PA(*pte);
+ }
+ else
+ {
+ if (!alloc)
+ return 0;
+
+ pagetable = (pagetable_t)PMM::alloc_page();
+ if (!pagetable)
+ return 0;
+
+ *pte = PA2PTE(pagetable) | PTE_V;
+ }
+ }
+ return &pagetable[PX(0, va)];
+ }
+
+ int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
+ {
+ uint64 a, last;
+ pte_t *pte;
+
+ a = (va / PGSIZE) * PGSIZE;
+ last = ((va + size - 1) / PGSIZE) * PGSIZE;
+
+ for(;;)
+ {
+ if((pte = walk(pagetable, a, 1)) == 0)
+ return -1;
+
+ if (*pte & PTE_V)
+ {
+ Drivers::uart_puts("Remap error\n");
+ return -1;
+ }
+
+ *pte = PA2PTE(pa) | perm | PTE_V;
+
+ if (a == last)
+ break;
+ a += PGSIZE;
+ pa += PGSIZE;
+ }
+ return 0;
+ }
+
+ void kvminit()
+ {
+ kernel_pagetable = (pagetable_t)PMM::alloc_page();
+
+ mappages(kernel_pagetable, 0x10000000, 0x10000, 0x10000000, PTE_R | PTE_W);
+
+ mappages(kernel_pagetable, (uint64)text_start, (uint64)text_end - (uint64)text_start,
+ (uint64)text_start, PTE_R | PTE_X);
+
+ mappages(kernel_pagetable, (uint64)data_start, PHYSTOP - (uint64)data_start,
+ (uint64)data_start, PTE_R | PTE_W);
+
+ mappages(kernel_pagetable, (uint64)rodata_start, (uint64)rodata_end - (uint64)rodata_start,
+ (uint64)rodata_start, PTE_R);
+
+ }
+ void kvminithart()
+ {
+ asm volatile("sfence.vma zero, zero");
+
+ uint64 satp_val = MAKE_SATP(kernel_pagetable);
+ asm volatile("csrw satp, %0" : : "r"(satp_val));
+
+ asm volatile("sfence.vma zero, zero");
+ }
+} \ No newline at end of file