aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-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
5 files changed, 75 insertions, 53 deletions
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){