aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-11-10 15:14:10 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2022-11-10 15:14:10 +0200
commit9edd65c48ee75751327c6ee6d42a7009e726d667 (patch)
treeeb46862f518b70c059c6dc36968f7a2ddc373966
parent87a6be8bc3404abea2af788c46cf450dc8bb6204 (diff)
downloadkmi-9edd65c48ee75751327c6ee6d42a7009e726d667.tar.gz
kmi-9edd65c48ee75751327c6ee6d42a7009e726d667.zip
initial implementation of process copying
+ Not actually working (at least fully), need to continue debugging when I have time.
-rwxr-xr-xarch/riscv64/conf/initbin2144 -> 2560 bytes
-rw-r--r--arch/riscv64/conf/init.c32
-rw-r--r--arch/riscv64/conf/initrdbin2560 -> 3072 bytes
-rw-r--r--common/tcb.c8
-rw-r--r--common/uapi/proc.c4
-rw-r--r--common/vmem.c58
-rw-r--r--include/apos/vmem.h2
7 files changed, 98 insertions, 6 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init
index b75076f..47e733f 100755
--- a/arch/riscv64/conf/init
+++ b/arch/riscv64/conf/init
Binary files 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
--- a/arch/riscv64/conf/initrd
+++ b/arch/riscv64/conf/initrd
Binary files 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 <apos/mem_regions.h>
#include <apos/assert.h>
+#include <apos/string.h>
#include <apos/debug.h>
#include <apos/bits.h>
#include <apos/vmem.h>
@@ -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().
*