diff options
Diffstat (limited to 'arch/riscv64/kernel')
| -rw-r--r-- | arch/riscv64/kernel/core_bringup.S | 9 | ||||
| -rw-r--r-- | arch/riscv64/kernel/entry.S | 2 | ||||
| -rw-r--r-- | arch/riscv64/kernel/proc.c | 14 | ||||
| -rw-r--r-- | arch/riscv64/kernel/smp.c | 35 | ||||
| -rw-r--r-- | arch/riscv64/kernel/start.S | 11 | ||||
| -rw-r--r-- | arch/riscv64/kernel/vmem.c | 30 |
6 files changed, 74 insertions, 27 deletions
diff --git a/arch/riscv64/kernel/core_bringup.S b/arch/riscv64/kernel/core_bringup.S index 83b017c..8a5a6f5 100644 --- a/arch/riscv64/kernel/core_bringup.S +++ b/arch/riscv64/kernel/core_bringup.S @@ -12,12 +12,17 @@ riscv_bringup: sfence.vma /* fetch the stack allocated to us at our hart index in smp_init_stacks */ - lla t0, smp_init_stacks + lui t0, %hi(smp_init_stacks) + addi t0, t0, %lo(smp_init_stacks) slli t1, a0, RW_SHIFT add t0, t0, t1 lr sp, 0(t0) mv tp, sp + /* calculate actual address in kernelspace where we should jump to */ + /* a0 has RAM base */ + lui t0, %hi(core_bringup) + addi t0, t0, %lo(core_bringup) + /* jump to C to handle rest of bringup */ - lla t0, core_bringup jr t0 diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S index e37d5cc..6096844 100644 --- a/arch/riscv64/kernel/entry.S +++ b/arch/riscv64/kernel/entry.S @@ -130,7 +130,7 @@ fast_dispatch: csrr t5, CSR_SEPC sr t5, offsetof_exec(tp) /* jump to C */ - jal dispatch + call dispatch /* if we had a thread switch, load kernel stack of current thread and * restore its context */ /* get associated kernel stack */ diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c index a4746b4..af4b2f3 100644 --- a/arch/riscv64/kernel/proc.c +++ b/arch/riscv64/kernel/proc.c @@ -18,9 +18,8 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd) { - /** \todo actually map fdt and initrd into the target address space */ csr_write(CSR_SSCRATCH, t); - csr_write(CSR_SEPC, t->exec); + csr_write(CSR_SEPC, t->callback); /* gcc gives a warning 'the value of the stack pointer after an asm * statement must be the same as it was before the statement', so this * is technically speaking undefined behavior, I think. @@ -31,13 +30,16 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd) vm_t stack_top = t->thread_stack + t->thread_stack_size; bkl_unlock(); __asm__ volatile ("mv sp, %0\n" - "mv a0, %1\n" - "mv a1, %2\n" + "li a0, %1\n" + "li a1, %2\n" "mv a2, %3\n" + "mv a3, %4\n" + "mv a4, %5\n" "sret\n" : - : "r" (stack_top), "r" (t->tid), "r" (fdt), - "r" (initrd) + : "r" (stack_top), + "K"(0), "K"(SYS_USER_BOOTED), + "r" (t->tid), "r" (fdt), "r" (initrd) : "memory"); /* we should never reach this */ unreachable(); diff --git a/arch/riscv64/kernel/smp.c b/arch/riscv64/kernel/smp.c index 74cc930..a878b90 100644 --- a/arch/riscv64/kernel/smp.c +++ b/arch/riscv64/kernel/smp.c @@ -7,9 +7,13 @@ */ #include <kmi/debug.h> -#include <arch/smp.h> +#include <kmi/bkl.h> #include <kmi/tcb.h> #include <libfdt.h> + +#include <arch/proc.h> +#include <arch/arch.h> +#include <arch/smp.h> #include "arch.h" #include "sbi.h" @@ -94,7 +98,10 @@ void smp_bringup(struct vmem *b, void *fdt) smp_init_stacks[hartid] = (void *)alloc_page(BASE_PAGE) + BASE_PAGE_SIZE; - pm_t bringup = (pm_t)__pa(riscv_bringup); + /* fixup physical address of bringup */ + pm_t bringup = (pm_t)riscv_bringup; + bringup = bringup - VM_KERNEL + get_load_addr(); + r = sbi_hart_start(hartid, bringup, satp); if (r.error) { @@ -111,8 +118,9 @@ void smp_bringup(struct vmem *b, void *fdt) * * @param hartid Hart that's being brought up. */ -void core_bringup(long hartid) +__noreturn void core_bringup(long hartid) { + bkl_lock(); /* assume smp_bringup assigned our cpuid correctly */ id_t cpuid = hartid_to_cpuid(hartid); @@ -125,12 +133,25 @@ void core_bringup(long hartid) /* add us as a thread to init program that cpu 0 is hopefully running by * now */ - struct tcb *t = create_thread(cpu_tcb(0)); + struct tcb *init = get_tcb(1); + assert(init); + + struct tcb *t = create_thread(init); + assert(t); + + alloc_stack(t); + /* init is special in that all threads jump to the entrypoint of the + * program */ + t->callback = init->callback; + t->exec = init->exec; t->cpu_id = cpuid; + /** @todo this is pretty hacky, should really be a separate function? */ + setup_irq(NULL); + setup_arch(NULL); tcb_assign(t); use_tcb(t); - /* eventually we should jump to init and start running stuff, but for - * now take it easy */ - while (1); + info("core %ld releasing BKL\n", (long)cpuid); + run_init(t, NULL, NULL); + unreachable(); } diff --git a/arch/riscv64/kernel/start.S b/arch/riscv64/kernel/start.S index 73a442e..5a2ed61 100644 --- a/arch/riscv64/kernel/start.S +++ b/arch/riscv64/kernel/start.S @@ -24,12 +24,11 @@ ret .section .text -/* a0 is fdt, a1 is load_addr, a2 is d, a3 is ram_base, a4 is DMAP */ +/* a0 is fdt, a1 is load_addr, a2 is d, a3 is ram_base */ .global to_kernelspace to_kernelspace: -lla t0, kernel -add t0, t0, a4 -sub t0, t0, a3 -add sp, sp, a4 -sub sp, sp, a3 +li t1, VM_DMAP +add sp, sp, t1 +lui t0, %hi(kernel) +addi t0, t0, %lo(kernel) jr t0 diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index 97b9cce..68869a3 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -416,14 +416,19 @@ long riscv_init_stack[4096 / sizeof(long)]; * and so the kernel itself has to be on a 4K boundary. */ __aligned(4096) struct vmem bootvmem; -struct vmem *direct_mapping() +/** Page entry for mapping kernel on a O1 page level, similar to how Linux does + * it. */ +__aligned(4096) struct vmem kvmem; + +struct vmem *init_mapping() { rpc_pages = order_size(MM_O1) / BASE_PAGE_SIZE; + kvmem.leaf[0] = (struct vmem *)to_pte(get_load_addr(), + VM_A | VM_G | VM_D | VM_R | VM_W | VM_X | VM_V); __populate_dmap(&bootvmem); populate_kvmem(&bootvmem); __use_vmem(&bootvmem, DEFAULT_Sv_MODE); - return &bootvmem; } @@ -456,16 +461,31 @@ void destroy_vmem(struct vmem *b) __destroy_branch(b); } +static void map_kernel(struct vmem *b) +{ + intptr_t addr = (pm_t)&kvmem; + + /* virtual memory is negative, unsure if this applies everywhere but I + * guess it's good enough for us */ + if (addr < 0) + addr = addr - VM_KERNEL + get_load_addr(); + + b->leaf[KERNEL_PAGE] = (struct vmem *)to_pte((pm_t)addr, VM_V); +} + stat_t populate_kvmem(struct vmem *b) { 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) + for (size_t i = KSTART_PAGE; i < KERNEL_PAGE; ++i) b->leaf[i] = (struct vmem *)to_pte( - get_ram_base() + TOP_PAGE_SIZE * (i - KSTART_PAGE), + TOP_PAGE_SIZE * (i - KSTART_PAGE), flags); - /* map in IO region */ + /* map in IO region if debugging is specified */ map_io_dbg(b); + + /* map actual kernel */ + map_kernel(b); return OK; } |
