diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/riscv64/conf/boot.cmd | 9 | ||||
| -rw-r--r-- | arch/riscv64/init/init.c | 13 | ||||
| -rw-r--r-- | arch/riscv64/kernel/vmem.c | 22 |
3 files changed, 38 insertions, 6 deletions
diff --git a/arch/riscv64/conf/boot.cmd b/arch/riscv64/conf/boot.cmd index 47f395a..6c06200 100644 --- a/arch/riscv64/conf/boot.cmd +++ b/arch/riscv64/conf/boot.cmd @@ -2,3 +2,12 @@ fdt move ${fdt_addr} ${fdt_addr_r} fdt addr ${fdt_addr_r} load ${devtype} ${devnum} ${kernel_addr_r} kmi.itb bootm ${kernel_addr_r} ${kernel_addr_r} ${fdt_addr_r} + +# the above works for qemu, visionfive2 looks more like +# +# fdt move ${fdt_addr} ${fdt_addr_r} +# fdt addr ${fdt_addr_r} +# load virtio 0:1 0x80260000 kmi.bin +# load virtio 0:1 0x88300000 initrd +# fdt chosen 0x88300000 0x1000 +# go 0x80260000 ${fdt_addr_r} diff --git a/arch/riscv64/init/init.c b/arch/riscv64/init/init.c index 278b9db..38639d7 100644 --- a/arch/riscv64/init/init.c +++ b/arch/riscv64/init/init.c @@ -16,6 +16,13 @@ #include "../kernel/csr.h" +void flush_tlb_full() +{ + /** @todo could be nice to have a common set of features with kernel, + * but for now this is good enough. */ + __asm__ volatile ("sfence.vma\n" ::: "memory"); +} + /** * Create page table entry. * Copy from \ref arch/riscv64/kernel/vmem.c. @@ -50,7 +57,9 @@ static pm_t __fdt_ram_base(void *fdt) */ static void init_bootmem(uintptr_t load_addr, uintptr_t ram_base) { - size_t flags = VM_V | VM_X | VM_R | VM_W; + /* set all flags on, especially A and D since MMUs are allowed to raise + * exceptions that we're not ready to handle if they're unset. */ + size_t flags = VM_V | VM_X | VM_R | VM_W | VM_D | VM_A; extern char *__kernel; extern char *__kernel_size; @@ -83,6 +92,8 @@ static void init_bootmem(uintptr_t load_addr, uintptr_t ram_base) case Sv48: mode = SATP_MODE_Sv48; break; default: break; }; + + flush_tlb_full(); csr_write(CSR_SATP, mode | ((uintptr_t)root_branch >> 12)); } diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index 235884b..f29c325 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -203,6 +203,8 @@ stat_t clear_vpage_flags(struct vmem *branch, vm_t vaddr, vmflags_t flags) stat_t mod_vpage(struct vmem *branch, vm_t vaddr, pm_t paddr, vmflags_t flags) { + flags |= VM_A | VM_D; + enum mm_order order; pm_t *pte = __find_vmem(branch, vaddr, &order); if (pte) { @@ -296,6 +298,10 @@ stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags, struct vmem *root = branch; enum mm_order top = __mm_max_order; + /* eventually we may want to keep track of page accesses, + * but for now they're mainly a nuisance. */ + flags |= VM_A | VM_D; + while (top != order) { size_t idx = vm_to_index(vaddr, top); @@ -356,13 +362,19 @@ stat_t unmap_vpage(struct vmem *branch, vm_t vaddr) return ERR_NF; } -void flush_tlb() +void flush_tlb(uintptr_t addr) +{ + __asm__ volatile ("sfence.vma %0, x0\n" : : "r" (addr) : "memory"); +} + +void flush_tlb_full() { - __asm__ volatile ("sfence.vma %0\n" : : "r" (0) : "memory"); + __asm__ volatile ("sfence.vma %0\n" :: "r" (0) : "memory"); } void flush_tlb_all() { + /** @todo this only works on a single core atm. */ __asm__ volatile ("sfence.vma\n" ::: "memory"); } @@ -386,8 +398,8 @@ static void __use_vmem(struct vmem *branch, enum mm_mode m) else if (m == Sv48) mode = SATP_MODE_Sv48; + flush_tlb_full(); csr_write(CSR_SATP, mode | pn); - flush_tlb(); /* Sv57 && Sv64 in the future? */ /** @todo ASID table for maybe faster context switches? */ } @@ -424,7 +436,7 @@ stat_t destroy_vmem(struct vmem *b) stat_t populate_kvmem(struct vmem *b) { - size_t flags = VM_V | VM_R | VM_W | VM_X | VM_G; + size_t flags = VM_V | VM_R | VM_W | VM_X | VM_G | VM_D | VM_A; for (size_t i = KSTART_PAGE; i < IO_PAGE; ++i) b->leaf[i] = (struct vmem *)to_pte( get_ram_base() + TOP_PAGE_SIZE * (i - KSTART_PAGE), @@ -440,7 +452,7 @@ vm_t setup_kernel_io(struct vmem *b, vm_t paddr) { pm_t top_page = paddr / TOP_PAGE_SIZE; b->leaf[IO_PAGE] = (struct vmem *)to_pte(top_page * TOP_PAGE_SIZE, - VM_V | VM_R | VM_W); + VM_V | VM_R | VM_W | VM_A | VM_D); return -TOP_PAGE_SIZE + paddr - (top_page * TOP_PAGE_SIZE); } #endif |
