aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv64/conf/init.c60
-rw-r--r--arch/riscv64/conf/kernel-link.S2
-rw-r--r--arch/riscv64/config.h6
-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
-rw-r--r--include/arch/vmem.h6
-rw-r--r--include/kmi/mem.h4
-rw-r--r--include/kmi/syscalls.h4
-rw-r--r--src/main.c5
-rw-r--r--src/pmem.c4
-rw-r--r--src/proc.c9
-rw-r--r--src/regions.c5
-rw-r--r--src/tcb.c6
17 files changed, 147 insertions, 65 deletions
diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c
index 6b1ce46..c61848e 100644
--- a/arch/riscv64/conf/init.c
+++ b/arch/riscv64/conf/init.c
@@ -274,24 +274,9 @@ static void *sys_req_sharedmem(long tid, unsigned long size, void **cbuf)
static char *rw_buf = 0;
static size_t rw_buf_size = 4096;
-void callback(long pid, long tid, long d0, long d1, long d2, long d3)
+static void sys_sleep()
{
- (void)tid;
- if (d0 == 1) {
- void *cbuf = 0;
- rw_buf = sys_req_sharedmem(pid, rw_buf_size, &cbuf);
- sys_ipc_resp((long)cbuf, rw_buf_size, 0, 0);
- __builtin_unreachable();
-
- } else if (d0 == 2) {
- puts("Received string: ");
- puts(rw_buf);
- sys_ipc_resp(0, 0, 0, 0);
- __builtin_unreachable();
- }
-
- sys_ipc_resp(0, 0, 0, 0);
- __builtin_unreachable();
+ ecall1(SYS_SLEEP);
}
#define CSR_TIME "0xc01"
@@ -300,8 +285,19 @@ void callback(long pid, long tid, long d0, long d1, long d2, long d3)
#define CSR_CYCLE "0xc00"
-void _start()
+static void handle_kernel(long a0, long a1, long d0, long d1, long d2, long d3)
{
+ if (a1 != SYS_USER_BOOTED)
+ return;
+
+ long tid = d0;
+ if (tid != 1) {
+ puts("Woo, more cores!\n");
+ while (1)
+ sys_sleep();
+ }
+
+ /* otherwise */
sys_noop();
puts("Hello, world!\n");
@@ -322,9 +318,6 @@ void _start()
print_value("Syscalls per second", n);
print_value("Executed cycles per second", cend - cstart);
- puts("Setting callback...");
- sys_ipc_server(callback);
-
puts("Starting fork():\n");
long pid = sys_fork();
if (pid != 0) {
@@ -387,3 +380,28 @@ void _start()
sys_poweroff(0);
}
+
+void _start(long a0, long a1, long d0, long d1, long d2, long d3)
+{
+ if (a0 == 0)
+ handle_kernel(a0, a1, d0, d1, d2, d3);
+
+ /* otherwise, implement test functionality */
+ long pid = a0;
+ long tid = a1;
+ if (d0 == 1) {
+ void *cbuf = 0;
+ rw_buf = sys_req_sharedmem(pid, rw_buf_size, &cbuf);
+ sys_ipc_resp((long)cbuf, rw_buf_size, 0, 0);
+ __builtin_unreachable();
+
+ } else if (d0 == 2) {
+ puts("Received string: ");
+ puts(rw_buf);
+ sys_ipc_resp(0, 0, 0, 0);
+ __builtin_unreachable();
+ }
+
+ sys_ipc_resp(0, 0, 0, 0);
+ __builtin_unreachable();
+}
diff --git a/arch/riscv64/conf/kernel-link.S b/arch/riscv64/conf/kernel-link.S
index 832a886..88f2e75 100644
--- a/arch/riscv64/conf/kernel-link.S
+++ b/arch/riscv64/conf/kernel-link.S
@@ -11,7 +11,7 @@ SECTIONS {
* hack.
* @todo look into this further.
*/
- . = VM_DMAP;
+ . = ABSOLUTE(VM_KERNEL);
__kernel_start = .;
.text ALIGN(4K) : AT(0) {
*(.kernel.start);
diff --git a/arch/riscv64/config.h b/arch/riscv64/config.h
index 2c513a5..952c0ca 100644
--- a/arch/riscv64/config.h
+++ b/arch/riscv64/config.h
@@ -32,6 +32,12 @@
/** Direct map offset. */
#define VM_DMAP (0xffffffc000000000) /* testing for now */
+/** Page reserved for kernel mapping in O1 */
+#define KERNEL_PAGE 510UL
+
+/** Kernel virtual address */
+#define VM_KERNEL (0xffffffff80000000)
+
/** Page reserved for kernel I/O. */
#define IO_PAGE 511UL
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;
}
diff --git a/include/arch/vmem.h b/include/arch/vmem.h
index 3daf232..e62c112 100644
--- a/include/arch/vmem.h
+++ b/include/arch/vmem.h
@@ -151,7 +151,7 @@ vm_t setup_kernel_io(struct vmem *b, vm_t paddr);
* @return The vmem node used to build the address space. Probably statically
* allocated.
*/
-struct vmem *direct_mapping();
+struct vmem *init_mapping();
/**
* Create new virtual memory space.
@@ -190,11 +190,9 @@ void clone_uvmem(struct vmem * restrict r, struct vmem * restrict b);
* @param load_addr Address where kernel was loaded to.
* @param direct_mapping Direct mapping vmem.
* @param ram_base Physical base address of ram.
- * @param dmap \ref VM_DMAP.
*/
__noreturn void to_kernelspace(void *fdt,
uintptr_t load_addr,
struct vmem *direct_mapping,
- pm_t ram_base,
- pm_t dmap);
+ pm_t ram_base);
#endif /* KMI_ARCH_PAGES_H */
diff --git a/include/kmi/mem.h b/include/kmi/mem.h
index d3c4da2..bf55c61 100644
--- a/include/kmi/mem.h
+++ b/include/kmi/mem.h
@@ -92,7 +92,7 @@
* @param x Physical address.
* @return Corresponding virtual address.
*/
-#define __va(x) (void *)(((uintptr_t)(x)) + VM_DMAP - get_ram_base())
+#define __va(x) (void *)(((uintptr_t)(x)) + VM_DMAP)
/**
* Convert virtual address to physical address in direct mapping.
@@ -100,7 +100,7 @@
* @param x Virtual address.
* @return Corresponding physical address.
*/
-#define __pa(x) (void *)(((uintptr_t)(x)) - VM_DMAP + get_ram_base())
+#define __pa(x) (void *)(((uintptr_t)(x)) - VM_DMAP)
/**
* Get page number of physical address.
diff --git a/include/kmi/syscalls.h b/include/kmi/syscalls.h
index a94cdf1..93b99a3 100644
--- a/include/kmi/syscalls.h
+++ b/include/kmi/syscalls.h
@@ -176,6 +176,10 @@ enum sys_user {
/** Thread has been orphaned. */
SYS_USER_ORPHANED,
+
+ /** Core has booted an init thread. Only used during booting, should be
+ * handled specially. */
+ SYS_USER_BOOTED,
};
/** Which notifications have arrived. */
diff --git a/src/main.c b/src/main.c
index aaf4cde..b51c519 100644
--- a/src/main.c
+++ b/src/main.c
@@ -114,9 +114,8 @@ __noreturn void main(unsigned long hart, void *fdt, uintptr_t load_addr)
init_mem(fdt);
- struct vmem *d = direct_mapping();
-
- to_kernelspace(fdt, load_addr, d, ram_base, VM_DMAP);
+ struct vmem *d = init_mapping();
+ to_kernelspace(fdt, load_addr, d, ram_base);
unreachable();
}
diff --git a/src/pmem.c b/src/pmem.c
index fac7731..5516d30 100644
--- a/src/pmem.c
+++ b/src/pmem.c
@@ -397,8 +397,10 @@ static pm_t __maybe_populate_bucket(size_t n, pm_t cont, enum mm_order order,
if (n) {
struct mm_bmap *bmap = (struct mm_bmap *)cont;
- if (populate)
+ if (populate) {
+ memset(bmap, 0, set_size);
bmap->size = n;
+ }
if (first && populate)
__attach_set(bucket, bmap);
diff --git a/src/proc.c b/src/proc.c
index eff962a..93e3aa5 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -59,17 +59,22 @@ stat_t init_proc(void *fdt, vm_t *proc_fdt, vm_t *proc_initrd)
/* allocate stacks etc after ELF file to make sure nothing of importance
* clashes */
prepare_proc(t, get_init_base(fdt), 0);
+
+ /** In the init process, can the entry be the callback? Is that too
+ * unergonomic? */
+ t->callback = t->exec;
+
/** \todo start one thread per core, with special handling for init in
* that each thread starts at the entry point of init? */
*proc_fdt = map_fixed_uvmem(t,
(pm_t)fdt, fdt_totalsize(fdt),
- VM_V | VM_R | VM_U);
+ MR_SHARED | VM_V | VM_R | VM_U);
pm_t initrd = (pm_t)__va(get_initrdbase(fdt));
*proc_initrd = map_fixed_uvmem(t,
initrd, get_initrdsize(fdt),
- VM_V | VM_R | VM_U);
+ MR_SHARED | VM_V | VM_R | VM_U);
info("mapped fdt at %lx\n", *proc_fdt);
info("mapped initrd at %lx\n", *proc_initrd);
diff --git a/src/regions.c b/src/regions.c
index 66ee546..f098f4f 100644
--- a/src/regions.c
+++ b/src/regions.c
@@ -316,7 +316,10 @@ struct mem_region *find_free_region(struct mem_region_root *r, size_t size,
vm_t start = align_up(t->start, offset);
size_t qsize = t->end - t->start;
- size_t bsize = t->end - start;
+
+ size_t bsize = 0;
+ if (t->end >= start)
+ bsize = t->end - start;
if (!quick_best && size <= qsize)
quick_best = t;
diff --git a/src/tcb.c b/src/tcb.c
index 27256e9..6915676 100644
--- a/src/tcb.c
+++ b/src/tcb.c
@@ -120,14 +120,14 @@ void free_stack(struct tcb *t)
struct tcb *create_thread(struct tcb *p)
{
- hard_assert(tcbs, 0);
+ assert(tcbs);
vm_t bottom = alloc_page(KERNEL_STACK_PAGE_ORDER);
/* move tcb to top of kernel stack, keeping alignment in check
* (hopefully) */
/** \todo check alignment */
- struct tcb *t = (struct tcb *)align_down(
- bottom + order_size(MM_O0) - sizeof(struct tcb), sizeof(long));
+ bottom = bottom + order_size(MM_O0) - sizeof(struct tcb);
+ struct tcb *t = (struct tcb *)align_down(bottom, sizeof(long));
memset(t, 0, sizeof(struct tcb));
id_t tid = __alloc_tid(t);