diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-06-04 00:48:15 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-06-04 00:48:15 +0300 |
| commit | 52e5c94314fa8e10efded82db85d181ed32f00bd (patch) | |
| tree | 869dd5a01c24effe32266518d057c87106c73a44 | |
| parent | 3ace1ddd76b9c04f3ed23883de6279b4485612e8 (diff) | |
| download | kmi-52e5c94314fa8e10efded82db85d181ed32f00bd.tar.gz kmi-52e5c94314fa8e10efded82db85d181ed32f00bd.zip | |
visionfive2 boots until debugging is initialized
| -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 | ||||
| -rw-r--r-- | common/debug.c | 14 | ||||
| -rw-r--r-- | common/string.c | 8 | ||||
| -rw-r--r-- | include/arch/vmem.h | 7 |
6 files changed, 60 insertions, 13 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 diff --git a/common/debug.c b/common/debug.c index 2cd4570..346934a 100644 --- a/common/debug.c +++ b/common/debug.c @@ -123,6 +123,12 @@ static struct uart_8250 *port = 0; */ static int __serial_tx_empty() { + /** + * @todo visionfive2 loops on lsr indefinitely, why? + * answer: because apparently visionfive2 uart has reg-shift = 2, + * meaning the registers are spaced apart more in memory than my naive + * struct. + * */ return port->lsr & LSR_THRE; } @@ -177,7 +183,13 @@ static struct dbg_info __dbg_from_fdt(const void *fdt) const char *stdout = fdt_getprop(fdt, chosen_offset, "stdout-path", NULL); - int stdout_offset = fdt_path_offset(fdt, stdout); + /* discard options */ + size_t baselen = strlen(stdout); + const char *options = strchr(stdout, ':'); + if (options) + baselen = options - stdout; + + int stdout_offset = fdt_path_offset_namelen(fdt, stdout, baselen); /* get serial device type */ const char *dev_name = (const char *)fdt_getprop(fdt, stdout_offset, diff --git a/common/string.c b/common/string.c index a76c875..359a938 100644 --- a/common/string.c +++ b/common/string.c @@ -105,13 +105,13 @@ __weak char *strchr(const char *str, int chr) const char *s1 = str; ssize_t num = strlen(s1); - while (num-- && *(s1--) != chr) + while (num-- && *(s1++) != chr) ; if (num < 0) return 0; - return (char *)(s1 + 1); + return (char *)(s1 - 1); } #undef strtok @@ -339,10 +339,10 @@ static int __hexval(char c) return c - '0'; if (c >= 'a' && c <= 'f') - return c - 'a'; + return 10 + c - 'a'; if (c >= 'A' && c <= 'F') - return c - 'A'; + return 10 + c - 'A'; return -1; } diff --git a/include/arch/vmem.h b/include/arch/vmem.h index 3f73a8f..d2f031d 100644 --- a/include/arch/vmem.h +++ b/include/arch/vmem.h @@ -98,8 +98,11 @@ stat_t mod_vpage(struct vmem *branch, vm_t vaddr, pm_t paddr, vmflags_t flags); stat_t stat_vpage(struct vmem *branch, vm_t vaddr, pm_t *paddr, enum mm_order *order, vmflags_t *flags); -/** Flush tlb of current processor. */ -void flush_tlb(); +/** Flush tlb entry where associated with address \p addr. */ +void flush_tlb(uintptr_t addr); + +/** Flush full tlb of current address space. */ +void flush_tlb_full(); /** Flush tlbs of all processors. */ void flush_tlb_all(); |
