diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-10-01 20:36:15 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-10-01 20:36:15 +0300 |
| commit | b30ee14270a44e48167934b9b3923b4280bdc855 (patch) | |
| tree | fe900fd442e834f857927e9094ce7cbdda59b9fd /arch/riscv/common | |
| parent | 2d173beb3392aff35c8a33f4ac001bf63bb9adc6 (diff) | |
| download | kmi-b30ee14270a44e48167934b9b3923b4280bdc855.tar.gz kmi-b30ee14270a44e48167934b9b3923b4280bdc855.zip | |
First jump to virtual memory!
+ Lots of bughunting to do, probably lots of off-by-one and so on
errors, and I make a lot of naive and possibly dangerous assumptions.
But cool start nonetheless. Should also come up with some method of
exchanging data between the init and actual kernel, probably some struct
of some sort. TODO
Diffstat (limited to 'arch/riscv/common')
| -rw-r--r-- | arch/riscv/common/vmem.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/arch/riscv/common/vmem.c b/arch/riscv/common/vmem.c new file mode 100644 index 0000000..17db777 --- /dev/null +++ b/arch/riscv/common/vmem.c @@ -0,0 +1,51 @@ +#include <apos/string.h> +#include <apos/pmem.h> +#include <pages.h> +#include <vmem.h> + +extern const size_t mm_shifts[10]; +extern const size_t mm_widths[10]; +extern const size_t mm_sizes[10]; + +#define pte_ppn(pte) (((paddr_t)(pte)) >> 10) +#define pte_flags(pte) (((paddr_t)(pte)) & 0xff) +#define to_pte(p, f) ((paddr_to_pnum(p) << 10) + (f)) +#define pte_addr(pte) (pnum_to_paddr(pte_ppn(pte))) + +/* probably not actually this simple, right? */ +void map_vmem(struct vm_branch_t *branch, + paddr_t paddr, vaddr_t vaddr, + uint8_t flags, enum mm_order_t order) +{ + enum mm_order_t top = MAX_ORDER; + while(top != order){ + size_t idx = paddr_to_index(vaddr, top); + + if(!branch->leaf[idx]){ + paddr_t new_leaf = alloc_page(MM_KPAGE, 0); + branch->leaf[idx] = (struct vm_branch_t *)to_pte(new_leaf, VM_V); + memset((void *)new_leaf, 0, sizeof(struct vm_branch_t)); + } + + branch = (struct vm_branch_t *)pte_addr(branch->leaf[idx]); + top--; + } + + size_t idx = paddr_to_index(vaddr, top); + branch->leaf[idx] = (struct vm_branch_t *)to_pte(paddr, flags); +} + +void unmap_vmem(struct vm_branch_t *branch, + vaddr_t vaddr, enum mm_order_t order) +{ + while(order){ + size_t idx = paddr_to_index(vaddr, order); + branch = (struct vm_branch_t *)pte_addr(branch->leaf[idx]); + } + + size_t idx = paddr_to_index(vaddr, order); + if(branch->leaf[idx]) + free_page(order, pte_addr(branch->leaf[idx])); + + branch->leaf[idx] = 0; +} |
