Nucleus
Barry System call interface 05ba3b0 (3 years, 2 months ago)
diff --git a/kernel/idt.c b/kernel/idt.c
index 3303aa8..0a93c55 100644
--- a/kernel/idt.c
+++ b/kernel/idt.c
@@ -7,9 +7,10 @@
#include <stdint.h>
#include <string.h>
-#include <nucleus/panic.h>
-#include <nucleus/memory.h>
#include <nucleus/cpu.h>
+#include <nucleus/memory.h>
+#include <nucleus/panic.h>
+#include <nucleus/task.h>
#include <io.h>
#include "desc.h"
@@ -212,7 +213,16 @@ __attribute__((interrupt))
static void
exc128(struct InterruptFrame *frame)
{
- exc_handler(128, frame, 0);
+ uintptr_t esi, *eax;
+ asm volatile(
+ "mov %%esi, %0;"
+ "lea -12(%%ebp), %1;"
+ : "=r" (esi), "=r" (eax));
+ *eax = syscall_handler(*eax, esi);
+
+ /* Send APIC EOI */
+ if (apic)
+ LAPIC(0xB0) = 0;
}
/* Interrupts */
diff --git a/task/syscall.c b/task/syscall.c
new file mode 100644
index 0000000..40754e3
--- /dev/null
+++ b/task/syscall.c
@@ -0,0 +1,114 @@
+/*
+ * This file implements the system call handler. It is called by the exc128
+ * handler function and just switches the syscall number into the syscall list
+ * and runs the relevant function.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/syscall.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <nucleus/cpu.h>
+#include <nucleus/memory.h>
+#include <nucleus/panic.h>
+#include <nucleus/task.h>
+#include <nucleus/vfs.h>
+
+/* Structure for a System Call Entry */
+struct SyscallEntry {
+ int argc;
+ void *function;
+};
+
+/* List of syscalls */
+struct SyscallEntry syscalls[] = {
+ /* Task */
+ [SYSCALL_DBGPRINTF] = { 1, dbgprintf },
+ [SYSCALL_CLONE] = { 1, clone },
+ [SYSCALL_EXIT] = { 1, exit },
+ [SYSCALL_GETPID] = { 0, getpid },
+ [SYSCALL_GETUID] = { 0, getuid },
+ [SYSCALL_SETUID] = { 1, setuid },
+ [SYSCALL_GETEUID] = { 0, geteuid },
+ [SYSCALL_SETEUID] = { 1, seteuid },
+ [SYSCALL_GETGID] = { 0, getgid },
+ [SYSCALL_SETGID] = { 1, setgid },
+ [SYSCALL_GETEGID] = { 0, getegid },
+ [SYSCALL_SETEGID] = { 1, setegid },
+ [SYSCALL_EXECVE] = { 3, execve },
+ [SYSCALL_WAITPID] = { 3, waitpid },
+// [SYSCALL_TIME] = { 1, time },
+// [SYSCALL_TIMES] = { 1, times },
+// [SYSCALL_SLEEP] = { 1, sleep },
+
+ /* Files */
+ [SYSCALL_OPEN] = { 3, open },
+ [SYSCALL_CLOSE] = { 1, close },
+ [SYSCALL_READ] = { 3, read },
+ [SYSCALL_WRITE] = { 3, write },
+ [SYSCALL_IOCTL] = { 3, ioctl },
+ [SYSCALL_LSEEK] = { 3, lseek },
+// [SYSCALL_STAT] = { 2, stat },
+// [SYSCALL_FSTAT] = { 2, fstat },
+// [SYSCALL_GETDENTS] = { 3, getdents },
+// [SYSCALL_MKDIR] = { 2, mkdir },
+// [SYSCALL_RMDIR] = { 1, rmdir },
+// [SYSCALL_MKNOD] = { 3, mknod },
+// [SYSCALL_RENAME] = { 2, rename },
+// [SYSCALL_DUP] = { 1, dup },
+// [SYSCALL_DUP2] = { 2, dup2 },
+// [SYSCALL_ISATTY] = { 1, isatty },
+// [SYSCALL_PIPE] = { 1, pipe },
+
+ /* File System */
+ [SYSCALL_MOUNT] = { 5, mount },
+ [SYSCALL_CHDIR] = { 1, chdir },
+ [SYSCALL_CHROOT] = { 1, chroot },
+ [SYSCALL_GETCWD] = { 2, getcwd },
+
+ /* Memory */
+ [SYSCALL_MMAP] = { 6, mmap },
+
+ /* Signals */
+ [SYSCALL_TGKILL] = { 3, tgkill },
+ [SYSCALL_KILL] = { 2, kill },
+ [SYSCALL_SIGNAL] = { 2, signal },
+ [SYSCALL_SIGPROCMASK] = { 3, sigprocmask },
+};
+
+/* Handle a syscall */
+int
+syscall_handler(int num, uintptr_t args)
+{
+ int ret = -EINVAL;
+ current->inSyscall = 1;
+
+ /* Find syscall entry */
+ if (num >= sizeof(syscalls) / sizeof(syscalls[0]))
+ goto end;
+ struct SyscallEntry *syscall = &syscalls[num];
+ if (!syscall->function)
+ goto end;
+
+ /* Copy arguments onto stack */
+ if (syscall->argc) {
+ int *val = (int *) args;
+ int argc = syscall->argc;
+ if (!verify_access(val, argc * sizeof(int), PROT_READ))
+ goto end;
+ while (argc--)
+ asm volatile("pushl %0" :: "r" (val[argc]));
+ }
+
+ /* Call function */
+ asm volatile("call *%1" : "=a" (ret) : "r" (syscall->function));
+
+end:
+ current->inSyscall = 0;
+ return ret;
+}