Browse Source

feat: syscall entry stub

greatbridf 2 years ago
parent
commit
8fbf10ff42
3 changed files with 56 additions and 81 deletions
  1. 1 1
      include/kernel/syscall.hpp
  2. 1 4
      src/asm/interrupt.s
  3. 54 76
      src/kernel/syscall.cpp

+ 1 - 1
include/kernel/syscall.hpp

@@ -4,6 +4,6 @@
 #include <types/types.h>
 
 // return value is stored in %eax and %edx
-typedef void (*syscall_handler)(interrupt_stack* data);
+typedef int (*syscall_handler)(interrupt_stack* data);
 
 void init_syscall(void);

+ 1 - 4
src/asm/interrupt.s

@@ -189,16 +189,13 @@ syscall_stub:
     jge syscall_stub_end
     pushal
 
-    # syscall function no. is in %eax
-    # store it in %ebx
-    movl %eax, %ebx
     # stack alignment and push *data
     movl %esp, %eax
     subl $0x4, %esp
     andl $0xfffffff0, %esp
     movl %eax, (%esp)
 
-    call *syscall_handlers(,%ebx,4)
+    call syscall_entry
 
     # restore stack
     popl %esp

+ 54 - 76
src/kernel/syscall.cpp

@@ -17,26 +17,11 @@
 #include <types/elf.hpp>
 #include <types/status.h>
 
-#define SYSCALL_SET_RETURN_VAL_EAX(_eax) \
-    data->s_regs.eax = ((decltype(data->s_regs.eax))(_eax))
-
-#define SYSCALL_SET_RETURN_VAL_EDX(_edx) \
-    data->s_regs.edx = ((decltype(data->s_regs.edx))(_edx))
-
-#define SYSCALL_SET_RETURN_VAL(_eax, _edx) \
-    SYSCALL_SET_RETURN_VAL_EAX(_eax);      \
-    SYSCALL_SET_RETURN_VAL_EDX(_edx)
-
 #define SYSCALL_HANDLERS_SIZE (16)
 syscall_handler syscall_handlers[SYSCALL_HANDLERS_SIZE];
 
-void _syscall_not_impl(interrupt_stack* data)
-{
-    SYSCALL_SET_RETURN_VAL(0xffffffff, 0xffffffff);
-}
-
 extern "C" void _syscall_stub_fork_return(void);
-void _syscall_fork(interrupt_stack* data)
+int _syscall_fork(interrupt_stack* data)
 {
     auto* newproc = &procs->emplace(*current_process)->value;
     auto* newthd = &newproc->thds.Emplace(*current_thread, newproc);
@@ -74,80 +59,73 @@ void _syscall_fork(interrupt_stack* data)
     // eflags
     push_stack(&newthd->esp, 0);
 
-    SYSCALL_SET_RETURN_VAL(newproc->pid, 0);
+    return newproc->pid;
 }
 
-void _syscall_write(interrupt_stack* data)
+int _syscall_write(interrupt_stack* data)
 {
     int fd = data->s_regs.edi;
     const char* buf = reinterpret_cast<const char*>(data->s_regs.esi);
     size_t n = data->s_regs.edx;
 
     auto* file = current_process->files[fd];
-    if (file->type == fs::file::types::directory) {
-        SYSCALL_SET_RETURN_VAL(GB_FAILED, EINVAL);
-        return;
-    }
+    if (file->type == fs::file::types::directory)
+        return GB_FAILED;
 
     int n_wrote = fs::vfs_write(file->ind, buf, file->cursor, n);
     file->cursor += n_wrote;
-    SYSCALL_SET_RETURN_VAL(n_wrote, 0);
+    return n_wrote;
 }
 
-void _syscall_read(interrupt_stack* data)
+int _syscall_read(interrupt_stack* data)
 {
     int fd = data->s_regs.edi;
     char* buf = reinterpret_cast<char*>(data->s_regs.esi);
     size_t n = data->s_regs.edx;
 
     auto* file = current_process->files[fd];
-    if (file->type == fs::file::types::directory) {
-        SYSCALL_SET_RETURN_VAL(GB_FAILED, EINVAL);
-        return;
-    }
+    if (file->type == fs::file::types::directory)
+        return GB_FAILED;
 
     // TODO: copy to user function !IMPORTANT
     int n_wrote = fs::vfs_read(file->ind, buf, n, file->cursor, n);
     file->cursor += n_wrote;
-    SYSCALL_SET_RETURN_VAL(n_wrote, 0);
+    return n_wrote;
 }
 
-void _syscall_sleep(interrupt_stack* data)
+int _syscall_sleep(interrupt_stack* data)
 {
     current_thread->attr.ready = 0;
     current_thread->attr.wait = 1;
 
-    SYSCALL_SET_RETURN_VAL(0, 0);
-
     schedule();
+    return 0;
 }
 
-void _syscall_chdir(interrupt_stack* data)
+int _syscall_chdir(interrupt_stack* data)
 {
     const char* path = reinterpret_cast<const char*>(data->s_regs.edi);
     auto* dir = fs::vfs_open(path);
     if (!dir) {
         // set errno ENOTFOUND
-        SYSCALL_SET_RETURN_VAL_EAX(-1);
-        return;
+        return -1;
     }
 
     if (!dir->ind->flags.in.directory) {
         // set errno ENOTDIR
-        SYSCALL_SET_RETURN_VAL_EAX(-1);
-        return;
+        return -1;
     }
 
     current_process->pwd = path;
 
-    SYSCALL_SET_RETURN_VAL_EAX(0);
+    return 0;
 }
 
 // syscall_exec(const char* exec, const char** argv)
 // @param exec: the path of program to execute
 // @param argv: arguments end with nullptr
 // @param envp: environment variables end with nullptr
-void _syscall_exec(interrupt_stack* data)
+int _syscall_exec(interrupt_stack* data)
 {
     const char* exec = reinterpret_cast<const char*>(data->s_regs.edi);
     char* const* argv = reinterpret_cast<char* const*>(data->s_regs.esi);
@@ -160,17 +138,17 @@ void _syscall_exec(interrupt_stack* data)
     d.system = false;
 
     int ret = types::elf::elf32_load(&d);
-    if (ret != GB_OK) {
-        data->s_regs.eax = d.errcode;
-        return;
-    }
+    if (ret != GB_OK)
+        return d.errcode;
 
     data->v_eip = d.eip;
     data->esp = (uint32_t)d.sp;
+
+    return 0;
 }
 
 // @param exit_code
-void _syscall_exit(interrupt_stack* data)
+int _syscall_exit(interrupt_stack* data)
 {
     uint32_t exit_code = data->s_regs.edi;
 
@@ -187,25 +165,22 @@ void _syscall_exit(interrupt_stack* data)
 
     // we should not return to here
     assert(false);
+    return -1;
 }
 
 // @param address of exit code: int*
 // @return pid of the exited process
-void _syscall_wait(interrupt_stack* data)
+int _syscall_wait(interrupt_stack* data)
 {
     auto* arg1 = reinterpret_cast<int*>(data->s_regs.edi);
 
     // TODO: check valid address
-    if (arg1 < (int*)0x40000000) {
-        SYSCALL_SET_RETURN_VAL(-1, EINVAL);
-        return;
-    }
+    if (arg1 < (int*)0x40000000)
+        return -1;
 
     auto& waitlst = current_process->wait_lst;
-    if (waitlst.empty() && !procs->has_child(current_process->pid)) {
-        SYSCALL_SET_RETURN_VAL(-1, ECHILD);
-        return;
-    }
+    if (waitlst.empty() && !procs->has_child(current_process->pid))
+        return -1;
 
     while (waitlst.empty()) {
         current_thread->attr.ready = 0;
@@ -227,20 +202,18 @@ void _syscall_wait(interrupt_stack* data)
     *arg1 = (int)evt.data2;
 
     procs->remove(pid);
-    SYSCALL_SET_RETURN_VAL(pid, 0);
+    return pid;
 }
 
-void _syscall_getdents(interrupt_stack* data)
+int _syscall_getdents(interrupt_stack* data)
 {
     int fd = data->s_regs.edi;
     auto* buf = (char*)(data->s_regs.esi);
     size_t cnt = data->s_regs.edx;
 
     auto* dir = current_process->files[fd];
-    if (dir->type != fs::file::types::directory) {
-        data->s_regs.eax = -1;
-        return;
-    }
+    if (dir->type != fs::file::types::directory)
+        return -1;
 
     size_t orig_cnt = cnt;
     int nread = dir->ind->fs->inode_readdir(dir->ind, dir->cursor,
@@ -270,17 +243,17 @@ void _syscall_getdents(interrupt_stack* data)
     if (nread > 0)
         dir->cursor += nread;
 
-    data->s_regs.eax = orig_cnt - cnt;
+    return orig_cnt - cnt;
 }
 
-void _syscall_open(interrupt_stack* data)
+int _syscall_open(interrupt_stack* data)
 {
     auto* path = (const char*)data->s_regs.edi;
     uint32_t flags = data->s_regs.esi;
-    data->s_regs.eax = current_process->files.open(path, flags);
+    return current_process->files.open(path, flags);
 }
 
-void _syscall_getcwd(interrupt_stack* data)
+int _syscall_getcwd(interrupt_stack* data)
 {
     char* buf = reinterpret_cast<char*>(data->s_regs.edi);
     size_t bufsize = reinterpret_cast<size_t>(data->s_regs.esi);
@@ -289,15 +262,13 @@ void _syscall_getcwd(interrupt_stack* data)
     strncpy(buf, current_process->pwd.c_str(), bufsize);
     buf[bufsize - 1] = 0;
 
-    SYSCALL_SET_RETURN_VAL_EAX(buf);
+    return (uint32_t)buf;
 }
 
-void _syscall_setsid(interrupt_stack* data)
+int _syscall_setsid(interrupt_stack* data)
 {
-    if (current_process->pid == current_process->pgid) {
-        SYSCALL_SET_RETURN_VAL_EAX(-1);
-        return;
-    }
+    if (current_process->pid == current_process->pgid)
+        return -1;
 
     current_process->sid = current_process->pid;
     current_process->pgid = current_process->pid;
@@ -305,20 +276,27 @@ void _syscall_setsid(interrupt_stack* data)
     // TODO: get tty* from fd or block device id
     procs->set_ctrl_tty(current_process->pid, console);
 
-    SYSCALL_SET_RETURN_VAL_EAX(current_process->pid);
+    return current_process->pid;
 }
 
-void _syscall_getsid(interrupt_stack* data)
+int _syscall_getsid(interrupt_stack* data)
 {
     pid_t pid = data->s_regs.edi;
 
     auto* proc = procs->find(pid);
-    if (!proc || proc->sid != current_process->sid) {
-        SYSCALL_SET_RETURN_VAL_EAX(-1);
-        return;
-    }
+    if (!proc || proc->sid != current_process->sid)
+        return -1;
+
+    return proc->sid;
+}
+
+extern "C" void syscall_entry(interrupt_stack* data)
+{
+    int ret = syscall_handlers[data->s_regs.eax](data);
+
+    data->s_regs.eax = ret;
 
-    SYSCALL_SET_RETURN_VAL_EAX(proc->sid);
+    // TODO: check signal
 }
 
 SECTION(".text.kinit")