aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv64/kernel')
-rw-r--r--arch/riscv64/kernel/core_bringup.S9
-rw-r--r--arch/riscv64/kernel/entry.S2
-rw-r--r--arch/riscv64/kernel/proc.c14
-rw-r--r--arch/riscv64/kernel/smp.c35
-rw-r--r--arch/riscv64/kernel/start.S11
-rw-r--r--arch/riscv64/kernel/vmem.c30
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;
}