diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-05-24 23:28:37 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-05-24 23:28:37 +0300 |
| commit | 018624dd5b1692b88f7b2e85652ea7b898043b6d (patch) | |
| tree | 0aa018640dc6bd5ebca7120df95dca4269be61d6 | |
| parent | 4123ec776d3769728e1e12379887da34c12ee8f8 (diff) | |
| download | kmi-018624dd5b1692b88f7b2e85652ea7b898043b6d.tar.gz kmi-018624dd5b1692b88f7b2e85652ea7b898043b6d.zip | |
make process loading more generic
| -rw-r--r-- | arch/riscv64/include/proc.h | 9 | ||||
| -rw-r--r-- | arch/riscv64/kernel/proc.c | 21 | ||||
| -rw-r--r-- | arch/riscv64/kernel/vmem.c | 18 | ||||
| -rw-r--r-- | common/main.c | 10 | ||||
| -rw-r--r-- | common/proc.c | 58 | ||||
| -rw-r--r-- | common/tcb.c | 53 | ||||
| -rw-r--r-- | common/uapi/conf.c | 2 | ||||
| -rw-r--r-- | common/uapi/proc.c | 5 | ||||
| -rw-r--r-- | include/apos/conf.h | 2 | ||||
| -rw-r--r-- | include/apos/mem_regions.h | 1 | ||||
| -rw-r--r-- | include/apos/proc.h | 4 | ||||
| -rw-r--r-- | include/apos/tcb.h | 8 | ||||
| -rw-r--r-- | include/arch/proc.h | 20 | ||||
| -rw-r--r-- | include/arch/vmem.h | 1 |
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 *); |
