diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2025-12-09 00:57:38 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2025-12-09 00:57:38 +0800 |
| commit | c36e1b5e5e069ce1735dcc2a94aa45ba72ea2441 (patch) | |
| tree | 34be19b553615cfe36a556452e3b7ebad5276216 /src/kernel/mm/vm.cc | |
| parent | 8cf8be522133548ee25fdcb0258ddf3950a68bcf (diff) | |
| download | lume-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.cc | 100 |
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 |
