aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-05-24 23:28:37 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2022-05-24 23:28:37 +0300
commit018624dd5b1692b88f7b2e85652ea7b898043b6d (patch)
tree0aa018640dc6bd5ebca7120df95dca4269be61d6
parent4123ec776d3769728e1e12379887da34c12ee8f8 (diff)
downloadkmi-018624dd5b1692b88f7b2e85652ea7b898043b6d.tar.gz
kmi-018624dd5b1692b88f7b2e85652ea7b898043b6d.zip
make process loading more generic
-rw-r--r--arch/riscv64/include/proc.h9
-rw-r--r--arch/riscv64/kernel/proc.c21
-rw-r--r--arch/riscv64/kernel/vmem.c18
-rw-r--r--common/main.c10
-rw-r--r--common/proc.c58
-rw-r--r--common/tcb.c53
-rw-r--r--common/uapi/conf.c2
-rw-r--r--common/uapi/proc.c5
-rw-r--r--include/apos/conf.h2
-rw-r--r--include/apos/mem_regions.h1
-rw-r--r--include/apos/proc.h4
-rw-r--r--include/apos/tcb.h8
-rw-r--r--include/arch/proc.h20
-rw-r--r--include/arch/vmem.h1
14 files changed, 133 insertions, 79 deletions
diff --git a/arch/riscv64/include/proc.h b/arch/riscv64/include/proc.h
new file mode 100644
index 0000000..c0bf3af
--- /dev/null
+++ b/arch/riscv64/include/proc.h
@@ -0,0 +1,9 @@
+#ifndef APOS_RISCV_PROC_H
+#define APOS_RISCV_PROC_H
+
+/**
+ * @file proc.h
+ * riscv64-specific process-related stuff. Currently empty.
+ */
+
+#endif /* APOS_RISCV_PROC_H */
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index bbe9782..c95021d 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -8,33 +8,32 @@
#include "regs.h"
#include "csr.h"
-stat_t jump_to_userspace(struct tcb *t, int argc, char **argv)
+/* TODO: actually map fdt into the target address space */
+stat_t run_init(struct tcb *t, void *fdt)
{
- csr_write(CSR_SEPC, t->entry);
csr_write(CSR_SSCRATCH, t);
- __asm__ volatile ("mv sp, %0\n" : : "r" (t->proc_stack_top) : "memory");
+ __asm__ volatile ("mv sp, %0\n" : : "r" (t->thread_stack_top) : "memory");
+ __asm__ volatile ("mv a0, %0\n" : : "r" (fdt) : );
__asm__ volatile ("sret\n" ::: "memory");
/* we should never reach this */
return ERR_ADDR;
}
-stat_t return_to_userspace(struct tcb *t)
+stat_t set_return(vm_t v)
{
- /* lol */
- return ERR_ADDR;
+ csr_write(CSR_SEPC, v);
+ return OK;
}
stat_t prepare_thread(struct tcb *t)
{
/* get location of registers in memory */
/* TODO: check alignment, should be fine but just to be sure */
- struct riscv_regs *r = (struct riscv_regs *)t;
- r--;
+ struct riscv_regs *r = (struct riscv_regs *)(--t);
- r->sp = (long)t->proc_stack_top;
+ /* insert important values into register slots */
+ r->sp = (long)t->thread_stack_top;
r->tp = (long)t;
- /* set entry point */
- csr_write(CSR_SEPC, t->entry);
return OK;
}
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c
index cd5e4c4..73db4dc 100644
--- a/arch/riscv64/kernel/vmem.c
+++ b/arch/riscv64/kernel/vmem.c
@@ -96,12 +96,12 @@ static void __destroy_branch(struct vmem *b)
if (!b)
return;
- for (size_t i = 0; i < BASE_PAGE_SIZE / sizeof(pm_t); ++i) {
+ for (size_t i = 0; i < RISCV_NUM_LEAVES; ++i) {
if (is_branch(b->leaf[i]))
__destroy_branch((struct vmem *)pte_addr(b->leaf[i]));
-
- free_page(MM_KPAGE, (pm_t)pte_addr(b->leaf[i]));
}
+
+ free_page(MM_KPAGE, (pm_t)__pa(b));
}
stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags,
@@ -150,7 +150,7 @@ void flush_tlb_all()
__asm__ volatile ("sfence.vma\n" ::: "memory");
}
-static void __start_vmem(struct vmem *branch, enum mm_mode m)
+static void __use_vmem(struct vmem *branch, enum mm_mode m)
{
branch = (struct vmem *)__pa(branch);
@@ -173,7 +173,7 @@ struct vmem *init_vmem(void *fdt)
UNUSED(fdt);
struct vmem *b = create_vmem();
/* update which memory branch to use */
- __start_vmem(b, Sv39);
+ use_vmem(b);
return b;
}
@@ -186,9 +186,15 @@ struct vmem *create_vmem()
return b;
}
+stat_t use_vmem(struct vmem *b)
+{
+ __use_vmem(b, Sv39);
+ return OK;
+}
+
stat_t destroy_vmem(struct vmem *b)
{
- free_page(MM_KPAGE, (pm_t)b);
+ __destroy_branch(b);
return OK;
}
diff --git a/common/main.c b/common/main.c
index 9585f3d..a608266 100644
--- a/common/main.c
+++ b/common/main.c
@@ -10,6 +10,7 @@
#include <apos/debug.h>
#include <apos/vmem.h>
#include <arch/arch.h>
+#include <arch/proc.h>
#include <arch/irq.h>
#include <libfdt.h>
@@ -23,6 +24,7 @@ void __main main(void *fdt)
setup_arch(fdt);
init_pmem(fdt);
+ /* setup temporary virtual memory */
struct vmem *b = init_vmem(fdt);
/* start up debugging in kernel IO */
@@ -30,5 +32,11 @@ void __main main(void *fdt)
init_irq(fdt);
init_timer(fdt);
- init_proc(fdt, b);
+ init_proc(fdt);
+ /* free temporary virtual memory now that we're in the init process
+ * space */
+ destroy_vmem(b);
+
+ /* start running init program */
+ run_init(cur_tcb(), fdt);
}
diff --git a/common/proc.c b/common/proc.c
index f09e7c1..3f6da6d 100644
--- a/common/proc.c
+++ b/common/proc.c
@@ -9,62 +9,34 @@
#include <apos/string.h>
#include <apos/initrd.h>
#include <arch/arch.h>
+#include <arch/proc.h>
-/* TODO: add error checking */
-static vm_t __setup_call_stack(struct tcb *t, size_t bytes)
+stat_t prepare_proc(struct tcb *t, vm_t bin, vm_t interp)
{
- pm_t offset = 0;
- size_t pages = __pages(bytes);
- vmflags_t flags = VM_V | VM_R | VM_W | VM_U;
- for (size_t i = 1; i <= pages; ++i) {
- offset = alloc_page(BASE_PAGE, offset);
- map_vpage(t->b_r, offset, PROC_STACK_TOP - BASE_PAGE_SIZE * i,
- flags, BASE_PAGE);
- }
+ vm_t entry = load_elf(t, bin, interp);
+ if (!entry)
+ return ERR_INVAL;
- return PROC_STACK_TOP - BASE_PAGE_SIZE * pages;
+ alloc_stacks(t);
+ prepare_thread(t);
+ set_return(entry);
+ return OK;
}
-static vm_t __setup_proc_stack(struct tcb *t, size_t bytes)
-{
- return alloc_uvmem(t, bytes, VM_V | VM_R | VM_W | VM_U);
-}
-
-stat_t init_proc(void *fdt, struct vmem *b)
+stat_t init_proc(void *fdt)
{
init_tcbs();
/* TODO: cleanup or something */
- struct tcb *t = create_thread(NULL);
+ struct tcb *t = create_proc(NULL);
if (!t)
return ERR_OOMEM;
- /* use existing branch */
- t->b_r = b;
- init_uvmem(t, UVMEM_START, UVMEM_END);
-
- /* TODO: this stuff should be placed in __sys_exec */
- /* the binary gets to choose first what memory regions it requires */
- t->entry = load_elf(t, get_init_base(fdt), 0);
- if (!t->entry)
- return ERR_ADDR;
-
- t->proc_stack = __setup_proc_stack(t, __proc_stack_size);
- if (!t->proc_stack)
- return ERR_ADDR;
-
- t->proc_stack_top = t->proc_stack + __proc_stack_size;
-
- t->call_stack = __setup_call_stack(t, __call_stack_size);
- if (!t->call_stack)
- return ERR_ADDR;
- t->call_stack_top = t->call_stack + __call_stack_size;
-
- flush_tlb();
-
/* set current tcb */
use_tcb(t);
+ use_vmem(t->b_r);
- /* TODO: move fdt into process space */
- return jump_to_userspace(t, 1, 0);
+ /* allocate stacks after ELF file to make sure nothing of importance
+ * clashes */
+ return prepare_proc(t, get_init_base(fdt), 0);
}
diff --git a/common/tcb.c b/common/tcb.c
index 6904208..0809829 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -6,6 +6,7 @@
#include <apos/tcb.h>
#include <arch/cpu.h>
#include <apos/mem.h>
+#include <apos/conf.h>
#include <apos/pmem.h>
#include <apos/vmem.h>
#include <apos/nodes.h>
@@ -54,6 +55,45 @@ static id_t __alloc_tid(struct tcb *t)
return ERR_NF;
}
+/* TODO: add error checking */
+static vm_t __setup_call_stack(struct tcb *t, size_t bytes)
+{
+ pm_t offset = 0;
+ size_t pages = __pages(bytes);
+ vmflags_t flags = VM_V | VM_R | VM_W | VM_U;
+ for (size_t i = 1; i <= pages; ++i) {
+ offset = alloc_page(BASE_PAGE, offset);
+ map_vpage(t->b_r, offset, PROC_STACK_TOP - BASE_PAGE_SIZE * i,
+ flags, BASE_PAGE);
+ }
+
+ return PROC_STACK_TOP - BASE_PAGE_SIZE * pages;
+}
+
+static vm_t __setup_thread_stack(struct tcb *t, size_t bytes)
+{
+ return alloc_uvmem(t, bytes, VM_V | VM_R | VM_W | VM_U);
+}
+
+stat_t alloc_stacks(struct tcb *t)
+{
+ struct tcb *p = is_proc(t) ? t : t->proc;
+
+ t->thread_stack = __setup_thread_stack(p, __thread_stack_size);
+ if (!t->thread_stack)
+ return ERR_OOMEM;
+
+ t->call_stack = __setup_call_stack(p, __call_stack_size);
+ if (!t->call_stack)
+ return ERR_OOMEM;
+
+ /* TODO: this only allows for a global stack size, what if a user wants
+ * per thread stack sizes? */
+ t->thread_stack_top = t->thread_stack + __thread_stack_size;
+ t->call_stack_top = t->call_stack + __call_stack_size;
+ return OK;
+}
+
struct tcb *create_thread(struct tcb *p)
{
hard_assert(tcbs, 0);
@@ -70,13 +110,17 @@ struct tcb *create_thread(struct tcb *p)
tcbs[tid] = t;
t->tid = tid;
- if (p) {
+ if (likely(p)) {
t->pid = p->pid;
t->proc = p;
} else {
+ init_uvmem(t, UVMEM_START, UVMEM_END);
t->pid = t->tid;
+ p = t;
}
+ t->b_r = create_vmem();
+
return t;
}
@@ -93,13 +137,12 @@ struct tcb *create_proc(struct tcb *p)
hard_assert(tcbs, 0);
/* create a new thread outside the current process */
- struct tcb *n = create_thread(0);
- n->b_r = create_vmem();
+ struct tcb *n = create_thread(NULL);
+ if (!n)
+ return 0;
if (likely(p))
__clone_proc(p, n); /* we have a parent thread */
- else
- init_uvmem(n, UVMEM_START, UVMEM_END);
return n;
}
diff --git a/common/uapi/conf.c b/common/uapi/conf.c
index a30333b..86846b2 100644
--- a/common/uapi/conf.c
+++ b/common/uapi/conf.c
@@ -9,7 +9,7 @@
#include <apos/sizes.h>
#include <apos/uapi.h>
-size_t __proc_stack_size = SZ_2M;
+size_t __thread_stack_size = SZ_2M;
size_t __call_stack_size = SZ_2M;
SYSCALL_DEFINE2(conf)(sys_arg_t param, sys_arg_t val)
diff --git a/common/uapi/proc.c b/common/uapi/proc.c
index c898339..f8ceaa5 100644
--- a/common/uapi/proc.c
+++ b/common/uapi/proc.c
@@ -5,6 +5,7 @@
#include <apos/elf.h>
#include <apos/uapi.h>
+#include <apos/proc.h>
#include <apos/bits.h>
#include <apos/mem_regions.h>
@@ -53,9 +54,7 @@ SYSCALL_DEFINE2(exec)(sys_arg_t bin, sys_arg_t interp){
if (interp)
clear_bit(b->flags, MR_KEEP);
- /* TODO: set entry? */
- load_elf(r, b, i);
- return (struct sys_ret){ OK, 0 };
+ return (struct sys_ret){ prepare_proc(r, bin, interp), 0 };
}
SYSCALL_DEFINE2(signal)(sys_arg_t tid, sys_arg_t signal){
diff --git a/include/apos/conf.h b/include/apos/conf.h
index 2b861dc..c2653cd 100644
--- a/include/apos/conf.h
+++ b/include/apos/conf.h
@@ -9,7 +9,7 @@
#include <apos/types.h>
-extern size_t __proc_stack_size;
+extern size_t __thread_stack_size;
extern size_t __call_stack_size;
#endif /* APOS_CONF_H */
diff --git a/include/apos/mem_regions.h b/include/apos/mem_regions.h
index c9c4a5c..54e4e2b 100644
--- a/include/apos/mem_regions.h
+++ b/include/apos/mem_regions.h
@@ -21,7 +21,6 @@
struct mem_region_root {
struct sp_root free_regions;
struct sp_root used_regions;
- struct mem_region *first;
};
struct mem_region {
diff --git a/include/apos/proc.h b/include/apos/proc.h
index 6b4044d..182ae16 100644
--- a/include/apos/proc.h
+++ b/include/apos/proc.h
@@ -10,7 +10,7 @@
#include <apos/tcb.h>
#include <apos/vmem.h>
-stat_t jump_to_userspace(struct tcb *t, int argc, char **argv);
-stat_t init_proc(void *fdt, struct vmem *b);
+stat_t prepare_proc(struct tcb *t, vm_t bin, vm_t interp);
+stat_t init_proc(void *fdt);
#endif /* APOS_PROC_H */
diff --git a/include/apos/tcb.h b/include/apos/tcb.h
index 572041d..2b602f6 100644
--- a/include/apos/tcb.h
+++ b/include/apos/tcb.h
@@ -32,15 +32,12 @@ struct tcb {
vm_t callback;
- vm_t proc_stack;
- vm_t proc_stack_top;
+ vm_t thread_stack;
+ vm_t thread_stack_top;
vm_t call_stack;
vm_t call_stack_top;
- /* entry point */
- vm_t entry;
-
/* vm root branch */
struct vmem *b_r;
@@ -63,5 +60,6 @@ void use_tcb(struct tcb *);
struct tcb *get_tcb(id_t tid);
stat_t clone_tcb_maps(struct tcb *);
+stat_t alloc_stacks(struct tcb *);
#endif /* APOS_TCB_H */
diff --git a/include/arch/proc.h b/include/arch/proc.h
new file mode 100644
index 0000000..1dcb0af
--- /dev/null
+++ b/include/arch/proc.h
@@ -0,0 +1,20 @@
+#ifndef APOS_ARCH_PROC_H
+#define APOS_ARCH_PROC_H
+
+/**
+ * @file proc.h
+ * Arch-specific process related stuff.
+ */
+
+#if defined(riscv64)
+#include "../../arch/riscv64/include/proc.h"
+#elif defined(riscv32)
+#include "../../arch/riscv32/include/proc.h"
+#endif
+
+stat_t set_return(vm_t r);
+/*TODO: should this be in arch/tcb.h or something? */
+stat_t prepare_thread(struct tcb *t);
+stat_t run_init(struct tcb *t, void *fdt);
+
+#endif /* APOS_ARCH_PROC_H */
diff --git a/include/arch/vmem.h b/include/arch/vmem.h
index 29dab99..b39d905 100644
--- a/include/arch/vmem.h
+++ b/include/arch/vmem.h
@@ -33,6 +33,7 @@ vm_t setup_kernel_io(struct vmem *b, vm_t paddr);
#endif
struct vmem *create_vmem();
+stat_t use_vmem(struct vmem *);
stat_t destroy_vmem(struct vmem *);
stat_t clone_uvmem(struct vmem *, struct vmem *);