From 9edd65c48ee75751327c6ee6d42a7009e726d667 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 10 Nov 2022 15:14:10 +0200 Subject: initial implementation of process copying + Not actually working (at least fully), need to continue debugging when I have time. --- arch/riscv64/conf/init | Bin 2144 -> 2560 bytes arch/riscv64/conf/init.c | 32 ++++++++++++++++++++++++++ arch/riscv64/conf/initrd | Bin 2560 -> 3072 bytes common/tcb.c | 8 +++---- common/uapi/proc.c | 4 ++-- common/vmem.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ include/apos/vmem.h | 2 ++ 7 files changed, 98 insertions(+), 6 deletions(-) diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init index b75076f..47e733f 100755 Binary files a/arch/riscv64/conf/init and b/arch/riscv64/conf/init differ diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c index feb5177..1886760 100644 --- a/arch/riscv64/conf/init.c +++ b/arch/riscv64/conf/init.c @@ -88,6 +88,26 @@ static void print_value(const char *s, uint64_t v) sys_putch('\n'); } +static uint64_t sys_fork() +{ + long register a0 asm ("a0") = SYS_FORK; + long register a1 asm ("a1") = 0; + ecall(); + if (a0 != 0) + print_value("fork() failed with error ", a0); + return a1; +} + +static uint64_t sys_swap(long tid) +{ + long register a0 asm ("a0") = SYS_SWAP; + long register a1 asm ("a1") = tid; + ecall(); + if (a0 != 0) + print_value("swap() failed with error ", a0); + return a0; +} + void _start() { sys_noop(); @@ -107,4 +127,16 @@ void _start() print_value("End ticks", i); print_value("Syscalls per second", n); + + puts("Starting fork():\n"); + long pid = sys_fork(); + if (pid != 0) { + print_value("Child pid: ", pid); + puts("Swapping to child...\n"); + sys_swap(pid); + puts("We shouldn't be here?\n"); + while(1); + } + + puts("Hello from child!\n"); } diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd index 3af4d2e..24f9fb4 100644 Binary files a/arch/riscv64/conf/initrd and b/arch/riscv64/conf/initrd differ diff --git a/common/tcb.c b/common/tcb.c index 417ca45..5f0e97b 100644 --- a/common/tcb.c +++ b/common/tcb.c @@ -172,14 +172,14 @@ struct tcb *create_thread(struct tcb *p) /** * Copy process. * - * @param p Parent process. * @param n New process. + * @param p Parent process. * @return \ref OK. */ -static stat_t __copy_proc(struct tcb *p, struct tcb *n) +static stat_t __copy_proc(struct tcb *n, struct tcb *p) { - /** \todo Copy memory regions as well as copy */ - return OK; + /* execution continuation? */ + return clone_mem_regions(n, p); } struct tcb *create_proc(struct tcb *p) diff --git a/common/uapi/proc.c b/common/uapi/proc.c index 0039195..5dbd90c 100644 --- a/common/uapi/proc.c +++ b/common/uapi/proc.c @@ -63,9 +63,9 @@ SYSCALL_DEFINE0(fork)(){ return SYS_RET1(ERR_OOMEM); /* prepare args for when we eventually swap to the new proc */ - set_args(t, SYS_RET2(OK, t->pid)); + set_args(t, SYS_RET2(OK, 0)); - return SYS_RET2(OK, 0); + return SYS_RET2(OK, t->pid); } /** diff --git a/common/vmem.c b/common/vmem.c index 73bc672..42b4adf 100644 --- a/common/vmem.c +++ b/common/vmem.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,20 @@ stat_t init_uvmem(struct tcb *t, vm_t base, vm_t top) return init_region(&t->sp_r, base, top); } +static stat_t __clone_mapped_region(struct tcb *d, struct tcb *s, struct mem_region *m) +{ + size_t size = 0; + vm_t va = alloc_fixed_region(&d->sp_r, m->start, m->end - m->start, + &size, m->flags); + + catastrophic_assert(va == m->start); + + if (copy_allocd_region(d->proc.vmem, va, size, m->flags, s)) + return ERR_MISC; + + return OK; +} + /** * Convenience function for freeing mapped regions. * @@ -70,6 +85,21 @@ stat_t destroy_uvmem(struct tcb *t) return destroy_region(&t->sp_r); } +stat_t clone_mem_regions(struct tcb *d, struct tcb *s) +{ + /** @todo implement some way to only iterate used regions, this loops + * through all regions which is likely a slight bit slower. */ + struct mem_region *m = find_first_region(&s->sp_r); + while (m) { + if (is_region_used(m)) + __clone_mapped_region(d, s, m); + + m = m->next; + } + + return OK; +} + vm_t alloc_uvmem(struct tcb *t, size_t size, vmflags_t flags) { /* t exists and is the process tcb of the current process */ @@ -189,6 +219,34 @@ stat_t alloc_shared_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, return (ret == INFO_SEFF) ? OK : ret; } +stat_t copy_allocd_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, + vmflags_t flags, enum mm_order order, void *data) +{ + struct vmem *s = (struct vmem *)data; + + pm_t paddr = 0; + enum mm_order v_order = 0; + stat_vpage(s, vaddr, &paddr, &v_order, 0); + /** @todo what if we could combine multiple pages into one in the new + * process? */ + if (order > v_order) + return INFO_TRGN; + + pm_t new_page = alloc_page(order); + if (!new_page) + return INFO_TRGN; + + map_vpage(b, new_page, vaddr, flags, order); + memcpy((void *)new_page, (void *)(paddr + *offset), order_size(order)); + + if (v_order > order) + *offset += order_size(order); + else + *offset = 0; + + return OK; +} + stat_t free_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data) { diff --git a/include/apos/vmem.h b/include/apos/vmem.h index eb901a8..862af44 100644 --- a/include/apos/vmem.h +++ b/include/apos/vmem.h @@ -114,6 +114,8 @@ stat_t init_uvmem(struct tcb *r, vm_t base, vm_t top); */ stat_t destroy_uvmem(struct tcb *r); +stat_t clone_mem_regions(struct tcb *d, struct tcb *s); + /** * User virtual memory worker callback for \ref map_fill_region(). * -- cgit v1.3