From 45f420a338ea02225bb8a98c9aca5eed8d6a23ae Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Sun, 2 Jun 2024 00:26:57 +0200 Subject: Initial commit --- kernel/vm.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 kernel/vm.c (limited to 'kernel/vm.c') diff --git a/kernel/vm.c b/kernel/vm.c new file mode 100644 index 0000000..c1adbe7 --- /dev/null +++ b/kernel/vm.c @@ -0,0 +1,108 @@ +#include "kernel/vm.h" +#include "kernel/kalloc.h" +#include "kernel/lib.h" +#include "kernel/riscv.h" + +enum +{ + VM_VALID = 1, + VM_USER = 16, + VM_GLOBAL = 32, + VM_ACCESSED = 64, + VM_DIRTY = 128, +}; + +struct PageTable +{ + uint32_t entries[1024]; +}; +typedef struct PageTable PageTable; +static_assert(sizeof(PageTable) == PAGE_SIZE); + +static PageTable* kroot = nullptr; + +static inline bool is_aligned(uint32_t p) +{ + return (p & (PAGE_SIZE - 1)) == 0; +} + +static inline void* offset_page(void* p) +{ + return (void*)((char*)p + PAGE_SIZE); +} + +void kvm_map_one(PageTable* root, void* va, void* pa, uint32_t mode) +{ + uint32_t vpn[] = { + ((uint32_t)va >> 12) & 0x3ff, + ((uint32_t)va >> 22) & 0x3ff, + }; + + uint32_t fl = root->entries[vpn[1]]; + if (!(fl & VM_VALID)) + { + PageTable* child = (PageTable*)kzalloc(); + fl = (((uint32_t)child >> 2) & 0xffff'fc00) | VM_VALID; + root->entries[vpn[1]] = fl; + } + + PageTable* child = (PageTable*)((fl & 0xffff'fc00) << 2); + + uint32_t ppn[] = { + ((uint32_t)pa >> 12) & 0x3ff, + ((uint32_t)pa >> 22) & 0x3ff, + }; + + child->entries[vpn[0]] = (ppn[1] << 20) | (ppn[0] << 10) | VM_VALID | mode; +} + +void kvm_map(void* va, void* pa, uint32_t size, uint32_t mode) +{ + if (!is_aligned((uint32_t)va)) panic("kvm_map: virtual address not aligned"); + if (!is_aligned((uint32_t)pa)) panic("kvm_map: physical address not aligned"); + if (!is_aligned(size)) panic("kvm_map: size not aligned"); + + for (; size > 0; size -= PAGE_SIZE) + { + kvm_map_one(kroot, va, pa, mode); + va = offset_page(va); + pa = offset_page(pa); + } +} + +extern char _text_start; +extern char _text_end; + +extern char _rodata_start; +extern char _rodata_end; + +extern char _data_start; +extern char _data_end; + +extern char _bss_start; +extern char _bss_end; + +extern char _stack_start; +extern char _stack_end; + +extern char _heap_start; +extern char _heap_end; + +void kvm_init() +{ + kroot = (PageTable*)kzalloc(); + + kvm_map(&_text_start, &_text_start, &_text_end - &_text_start, VM_R | VM_X); + kvm_map(&_rodata_start, &_rodata_start, &_rodata_end - &_rodata_start, VM_R); + kvm_map(&_data_start, &_data_start, &_data_end - &_data_start, VM_RW); + kvm_map(&_bss_start, &_bss_start, &_bss_end - &_bss_start, VM_RW); + kvm_map(&_heap_start, &_heap_start, &_heap_end - &_heap_start, VM_RW); + kvm_map(&_stack_start, &_stack_start, &_stack_end - &_stack_start, VM_RW); + + kvm_map((void*)0x1000'0000, (void*)0x1000'0000, PAGE_SIZE, VM_RW); // UART + kvm_map((void*)0x0c00'0000, (void*)0x0c00'0000, 0x8000, VM_RW); // APLIC-M + kvm_map((void*)0x0d00'0000, (void*)0x0d00'0000, 0x8000, VM_RW); // APLIC-S + + w_satp(SATP_MODE_SV32 | ((uint32_t)kroot >> 12)); + sfence_vma(); +} -- cgit