aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv64')
-rw-r--r--arch/riscv64/conf/kernel-link.S19
-rw-r--r--arch/riscv64/kernel/arch.c13
-rw-r--r--arch/riscv64/kernel/arch.h16
-rw-r--r--arch/riscv64/kernel/proc.c38
-rw-r--r--arch/riscv64/kernel/smp.c6
-rw-r--r--arch/riscv64/kernel/start.S15
-rw-r--r--arch/riscv64/kernel/vmem.c12
-rw-r--r--arch/riscv64/source.mk8
8 files changed, 80 insertions, 47 deletions
diff --git a/arch/riscv64/conf/kernel-link.S b/arch/riscv64/conf/kernel-link.S
index 88f2e75..e395e4a 100644
--- a/arch/riscv64/conf/kernel-link.S
+++ b/arch/riscv64/conf/kernel-link.S
@@ -5,12 +5,6 @@ OUTPUT_ARCH(riscv)
ENTRY(main)
SECTIONS {
- /* This is apparently necessary. I *think* it is to tell the linker that
- * the kernel should be able to run in the bottom half of the address
- * space, but I don't know for sure and this feels like a fairly major
- * hack.
- * @todo look into this further.
- */
. = ABSOLUTE(VM_KERNEL);
__kernel_start = .;
.text ALIGN(4K) : AT(0) {
@@ -18,6 +12,14 @@ SECTIONS {
*(.text*);
}
+ /* place bss in between different load sections to force objcopy to
+ * output zeroes for it */
+ .bss : {
+ *(.sbss*)
+ *(.bss*)
+ *(COMMON)
+ }
+
.rodata : {
*(.rodata*)
}
@@ -27,12 +29,7 @@ SECTIONS {
*(.sdata*)
}
- .bss : {
- *(.sbss*) *(.bss*) *(COMMON)
- }
-
__kernel_end = .;
- __kernel_size = __kernel_end - __kernel_start;
.garbage : {
*(.note*)
diff --git a/arch/riscv64/kernel/arch.c b/arch/riscv64/kernel/arch.c
index 4561d8b..5dc50cf 100644
--- a/arch/riscv64/kernel/arch.c
+++ b/arch/riscv64/kernel/arch.c
@@ -13,7 +13,18 @@
#include "csr.h"
#include "arch.h"
-id_t __cpuid_to_hartid[MAX_CPUS];
+/** Array where indexing is done with CPU IDs, giving the corresponding hart ID. */
+static id_t __cpuid_to_hartid[MAX_CPUS];
+
+id_t cpuid_to_hartid(id_t cpu)
+{
+ return __cpuid_to_hartid[cpu];
+}
+
+void set_hartid(id_t cpu, id_t hartid)
+{
+ __cpuid_to_hartid[cpu] = hartid;
+}
id_t hartid_to_cpuid(id_t hart)
{
diff --git a/arch/riscv64/kernel/arch.h b/arch/riscv64/kernel/arch.h
index d38dad0..789b416 100644
--- a/arch/riscv64/kernel/arch.h
+++ b/arch/riscv64/kernel/arch.h
@@ -12,9 +12,6 @@
#include <kmi/vmem.h>
-/** Actual map of cpu id to hart id. */
-extern id_t __cpuid_to_hartid[MAX_CPUS];
-
/**
* Map cpu id to hart id.
* Defined as a macro to allow for stuff like
@@ -23,15 +20,24 @@ extern id_t __cpuid_to_hartid[MAX_CPUS];
* @endcode
*
* @param x Hart ID.
+ * @return Corresponding CPU ID.
+ */
+id_t cpuid_to_hartid(id_t x);
+
+/**
+ * Create mapping between \p cpuid and \p hartid.
+ *
+ * @param cpuid CPU ID to map to \p hartid.
+ * @param hartid Hart ID to map to \p CPU ID.
*/
-#define cpuid_to_hartid(x) __cpuid_to_hartid[x]
+void set_hartid(id_t cpuid, id_t hartid);
/**
* Find the cpu id that corresponds to hart id.
*
* @param hart Hart to find corresponding cpu id for.
* @return Corresponding cpu id. 0 if not found, though this should maybe be a
- * panic situation.
+ * panic situation. Currently just sets the core to sleep.
*/
id_t hartid_to_cpuid(id_t hart);
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index 73b0984..19bd52f 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -9,6 +9,7 @@
#include <kmi/tcb.h>
#include <kmi/elf.h>
#include <kmi/bkl.h>
+#include <kmi/debug.h>
#include <kmi/string.h>
#include <arch/proc.h>
@@ -16,6 +17,27 @@
#include "regs.h"
#include "csr.h"
+/** Assembly implementation for actually jumping to the init process, defined in
+ * start.S. Quite a few constants that could be implemented in assembly as well
+ * but this is maybe a bit more convenient.
+ *
+ * @param pid Should always be 0 to indicate that the kernel is the originator.
+ * @param tid Thread ID of the current thread.
+ * @param code Should always be SYS_USER_SPAWNED to indicate that a new core has
+ * come online.
+ * @param fdt Address of flattened device tree within userspace memory.
+ * @param initrd Ditto for initial ramdisk.
+ * @param proc Process ID, should be constant 1.
+ * @param stack_top Stack address.
+ */
+__noreturn void riscv_run_init(sys_arg_t pid,
+ sys_arg_t tid,
+ sys_arg_t code,
+ sys_arg_t fdt,
+ sys_arg_t initrd,
+ sys_arg_t proc, /* not strictly speaking necessary but eh */
+ sys_arg_t stack_top);
+
void run_init(struct tcb *t, vm_t fdt, vm_t initrd)
{
csr_write(CSR_SSCRATCH, t);
@@ -28,20 +50,10 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd)
* works for now.
*/
vm_t stack_top = t->thread_stack + t->thread_stack_size;
+ info("jumping to %lx\n", (long)t->callback);
+
bkl_unlock();
- __asm__ volatile ("mv sp, %0\n"
- "li a0, %1\n"
- "mv a1, %2\n"
- "li a2, %3\n"
- "mv a3, %4\n"
- "mv a4, %5\n"
- "li a5, %6\n"
- "sret\n"
- :
- : "r" (stack_top),
- "K" (0), "r" (t->tid), "K" (SYS_USER_SPAWNED),
- "r" (fdt), "r" (initrd), "K" (1)
- : "memory");
+ riscv_run_init(0, t->tid, SYS_USER_SPAWNED, fdt, initrd, 1, stack_top);
/* we should never reach this */
unreachable();
}
diff --git a/arch/riscv64/kernel/smp.c b/arch/riscv64/kernel/smp.c
index e48a216..425d3ce 100644
--- a/arch/riscv64/kernel/smp.c
+++ b/arch/riscv64/kernel/smp.c
@@ -59,7 +59,7 @@ void smp_bringup(struct vmem *b, void *fdt)
extern void riscv_bringup(void);
/* mark first hart available */
- cpuid_to_hartid(0) = -1;
+ set_hartid(0, -1);
/* assume we're in default Sv mode, in the future this will have to be
* fixed if we start implementing Sv48 etc. */
@@ -87,12 +87,12 @@ void smp_bringup(struct vmem *b, void *fdt)
if (r.value == SBI_HART_STARTED) {
/* there should ever only be one started hart */
assert(cpuid_to_hartid(0) == -1);
- cpuid_to_hartid(0) = hartid;
+ set_hartid(0, hartid);
continue;
}
/** @todo should check that cpus doesn't go over MAX_CPUS */
- cpuid_to_hartid(cpus++) = hartid;
+ set_hartid(cpus++, hartid);
/** @todo try to remember to free these as well */
smp_init_stacks[hartid] = (void *)alloc_page(BASE_PAGE) +
diff --git a/arch/riscv64/kernel/start.S b/arch/riscv64/kernel/start.S
index 5a2ed61..3f2b3cb 100644
--- a/arch/riscv64/kernel/start.S
+++ b/arch/riscv64/kernel/start.S
@@ -1,10 +1,12 @@
+#include "asm.h"
+
#if GENERIC_UBOOT
# define MAIN main_go
#else
# define MAIN main
#endif
-.section .kernel.start
+.section ".kernel.start", "ax"
.global _start
_start:
/* get load address */
@@ -15,6 +17,12 @@ lla sp, riscv_init_stack
li t0, 4096
add sp, sp, t0
+lla t0, __kernel_start
+lla t1, __kernel_end
+lla t2, kernel_size
+sub t0, t1, t0
+sr t0, 0(t2)
+
/* set thread pointer to zero so we don't accidentally try to use a tcb */
li tp, 0
@@ -32,3 +40,8 @@ add sp, sp, t1
lui t0, %hi(kernel)
addi t0, t0, %lo(kernel)
jr t0
+
+.global riscv_run_init
+riscv_run_init:
+mv sp, a6
+sret
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c
index cb1eba0..9473f38 100644
--- a/arch/riscv64/kernel/vmem.c
+++ b/arch/riscv64/kernel/vmem.c
@@ -148,7 +148,7 @@ static bool __unused(pm_t b)
*/
static pm_t *__find_vmem(struct vmem *b, vm_t v, enum mm_order *o)
{
- enum mm_order top = __mm_max_order;
+ enum mm_order top = max_order();
if (o)
*o = MM_O0;
do {
@@ -287,7 +287,7 @@ stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags,
enum mm_order order)
{
struct vmem *root = branch;
- enum mm_order top = __mm_max_order;
+ enum mm_order top = max_order();
/* eventually we may want to keep track of page accesses,
* but for now they're mainly a nuisance. */
@@ -316,7 +316,7 @@ stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags,
branch->leaf[idx] =
(struct vmem *)to_pte((pm_t)__pa(paddr), vp_flags(flags));
- __add_graves(root, vm_to_index(vaddr, __mm_max_order));
+ __add_graves(root, vm_to_index(vaddr, max_order()));
return OK;
}
@@ -351,7 +351,7 @@ stat_t unmap_vpage(struct vmem *branch, vm_t vaddr)
pm_t *pte = __find_vmem(branch, vaddr, 0);
if (pte) {
*pte = GRAVESTONE;
- __remove_graves(branch, vm_to_index(vaddr, __mm_max_order));
+ __remove_graves(branch, vm_to_index(vaddr, max_order()));
return OK;
}
@@ -423,10 +423,10 @@ __aligned(4096) struct vmem kvmem;
/* adding a third page entry would let us map the kernel at any 4KiB boundary
* but eh, Linux seems fine with 2MiB so I guess I shall be as well. */
-struct vmem *init_mapping()
+struct vmem *init_mapping(uintptr_t load_addr)
{
rpc_pages = order_size(MM_O1) / BASE_PAGE_SIZE;
- kvmem.leaf[0] = (struct vmem *)to_pte(get_load_addr(),
+ kvmem.leaf[0] = (struct vmem *)to_pte(load_addr,
VM_A | VM_G | VM_D | VM_R | VM_W |
VM_X | VM_V);
diff --git a/arch/riscv64/source.mk b/arch/riscv64/source.mk
index 6e72c85..0c10bbc 100644
--- a/arch/riscv64/source.mk
+++ b/arch/riscv64/source.mk
@@ -1,15 +1,9 @@
KERNEL_LOCAL != echo $(ARCH_SOURCE)/kernel/*.[cS]
-KERNEL_SOURCES += $(KERNEL_LOCAL)
-INIT_SOURCES += $(ARCH_SOURCE)/init/*.[cS]
+KERNEL_SOURCES := $(KERNEL_SOURCES) $(KERNEL_LOCAL)
# this doesn't work for rv32, but fine for now */
ARCH_CFLAGS := $(ARCH_CFLAGS) -mcmodel=medany
-# oof, LLVM's riscv support has become better since I last looked into
-# it, but for some reason LTO still causes a crash. Meaning it has to be
-# disabled again, though for a different reason than last time
-OPTFLAGS != [ "$(LLVM)" != "0" ] && echo $(OPTFLAGS:-flto=) || echo $(OPTFLAGS)
-
run:
$(ARCH_SOURCE)/conf/mkimage.sh $(ARCH)