diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index 8d49e4d6..fd69a690 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -10,6 +10,7 @@ extern syscall_write extern syscall_getpid extern syscall_fstat extern syscall_fstatat +extern syscall_fork syscalltab: dq syscall_print dq syscall_mmap @@ -22,7 +23,8 @@ dq syscall_write dq syscall_getpid dq syscall_fstat dq syscall_fstatat -syscallcount equ 11 +dq syscall_fork +syscallcount equ 12 section .text global arch_syscall_entry ; on entry: @@ -49,7 +51,7 @@ arch_syscall_entry: ; push context push qword 0x1b ; user SS - push qword rcx + push qword rcx ; user RSP add qword [rsp], 8 ; correct the old stack pointer to before the return address push push r11 ; rflags is stored in r11 push qword 0x23 ; user CS @@ -89,6 +91,7 @@ arch_syscall_entry: mov rdx, rsi mov rsi, rdi mov rdi, rsp + add rdi, 8 ; context pointer is after r9 argument sti cmp rax, syscallcount diff --git a/kernel-src/sys/syscalls/fork.c b/kernel-src/sys/syscalls/fork.c new file mode 100644 index 00000000..90539b4d --- /dev/null +++ b/kernel-src/sys/syscalls/fork.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +#include +syscallret_t syscall_fork(context_t *ctx) { + syscallret_t ret = { + .ret = -1, + .errno = 0 + }; + + proc_t *proc = _cpu()->thread->proc; + proc_t *nproc = sched_newproc(); + if (nproc == NULL) { + ret.errno = ENOMEM; + goto cleanup; + } + + thread_t *nthread = sched_newthread((void *)CTX_IP(ctx), 16 * PAGE_SIZE, 1, nproc, (void *)CTX_SP(ctx)); + if (nthread == NULL) { + ret.errno = ENOMEM; + goto cleanup; + } + + nthread->vmmctx = vmm_fork(_cpu()->thread->vmmctx); + + if (nthread->vmmctx == NULL) { + ret.errno = ENOMEM; + goto cleanup; + } + + ret.errno = fd_clone(nproc); + if (ret.errno) + goto cleanup; + + bool intstate = interrupt_set(false); + spinlock_acquire(&proc->lock); + + nproc->parent = proc; + nproc->sibling = proc->child; + proc->child = nproc; + + spinlock_release(&proc->lock); + interrupt_set(intstate); + + nproc->umask = _cpu()->thread->proc->umask; + nproc->root = sched_getroot(); + nproc->cwd = sched_getcwd(); + + ARCH_CONTEXT_THREADSAVE(nthread, ctx); + + CTX_RET(&nthread->context) = 0; + CTX_ERRNO(&nthread->context) = 0; + + ret.ret = nproc->pid; + + sched_queue(nthread); + + cleanup: + return ret; +} diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index aaa37933..d9b6a1e2 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -133,10 +133,10 @@ index 0000000..e5b087a + diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp new file mode 100644 -index 0000000..dc6bd0e +index 0000000..3961e7f --- /dev/null +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -0,0 +1,178 @@ +@@ -0,0 +1,185 @@ +#include +#include +#include @@ -200,6 +200,13 @@ index 0000000..dc6bd0e + return 0; + } + ++ int sys_fork(pid_t *pid) { ++ long ret = 0; ++ long error = syscall(SYSCALL_FORK, &ret); ++ *pid = ret; ++ return error; ++ } ++ + int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat *statbuf) { + long ret; + switch (fsfdt) { @@ -334,10 +341,10 @@ index 0000000..990eca0 +#endif diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h new file mode 100644 -index 0000000..fde482a +index 0000000..16c462d --- /dev/null +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -0,0 +1,34 @@ +@@ -0,0 +1,35 @@ +#ifndef _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE + @@ -352,6 +359,7 @@ index 0000000..fde482a +#define SYSCALL_GETPID 8 +#define SYSCALL_FSTAT 9 +#define SYSCALL_FSTATAT 10 ++#define SYSCALL_FORK 11 + +#include +#include