Kernel: Improve syscall handling

Syscalls are now called from a list of function pointers
This commit is contained in:
Bananymous 2024-02-12 21:47:40 +02:00
parent 78ef7e804f
commit 9314528b9b
7 changed files with 97 additions and 287 deletions

View File

@ -1,7 +1,5 @@
.section .userspace, "aw" .section .userspace, "aw"
#include <sys/syscall.h>
// stack contains // stack contains
// return address // return address
// signal number // signal number

View File

@ -96,6 +96,8 @@ namespace Kernel
BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); } BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); }
BAN::ErrorOr<long> sys_getpgid(pid_t); BAN::ErrorOr<long> sys_getpgid(pid_t);
BAN::ErrorOr<long> sys_getpid() const { return pid(); }
BAN::ErrorOr<long> open_inode(BAN::RefPtr<Inode>, int flags); BAN::ErrorOr<long> open_inode(BAN::RefPtr<Inode>, int flags);
BAN::ErrorOr<void> create_file_or_dir(BAN::StringView name, mode_t mode); BAN::ErrorOr<void> create_file_or_dir(BAN::StringView name, mode_t mode);
@ -148,7 +150,7 @@ namespace Kernel
BAN::ErrorOr<void> mount(BAN::StringView source, BAN::StringView target); BAN::ErrorOr<void> mount(BAN::StringView source, BAN::StringView target);
BAN::ErrorOr<long> sys_read_dir_entries(int fd, DirectoryEntryList* buffer, size_t buffer_size); BAN::ErrorOr<long> sys_readdir(int fd, DirectoryEntryList* buffer, size_t buffer_size);
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*); BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len); BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
@ -157,7 +159,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags); BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
BAN::ErrorOr<long> sys_signal(int, void (*)(int)); BAN::ErrorOr<long> sys_signal(int, void (*)(int));
static BAN::ErrorOr<long> sys_kill(pid_t pid, int signal); BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid); BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid);

View File

@ -1218,7 +1218,7 @@ namespace Kernel
return BAN::Error::from_errno(EUNKNOWN); return BAN::Error::from_errno(EUNKNOWN);
} }
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size) BAN::ErrorOr<long> Process::sys_readdir(int fd, DirectoryEntryList* list, size_t list_size)
{ {
LockGuard _(m_lock); LockGuard _(m_lock);
TRY(validate_pointer_access(list, list_size)); TRY(validate_pointer_access(list, list_size));

View File

@ -1,3 +1,4 @@
#include <BAN/Bitcast.h>
#include <kernel/Debug.h> #include <kernel/Debug.h>
#include <kernel/InterruptStack.h> #include <kernel/InterruptStack.h>
#include <kernel/Process.h> #include <kernel/Process.h>
@ -19,6 +20,14 @@ namespace Kernel
extern "C" long sys_fork_trampoline(); extern "C" long sys_fork_trampoline();
using SyscallHandler = BAN::ErrorOr<long> (Process::*)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
static const SyscallHandler s_syscall_handlers[] = {
#define O(enum, name) BAN::bit_cast<SyscallHandler>(&Process::sys_ ## name),
__SYSCALL_LIST(O)
#undef O
};
extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack& interrupt_stack) extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack& interrupt_stack)
{ {
ASSERT((interrupt_stack.cs & 0b11) == 0b11); ASSERT((interrupt_stack.cs & 0b11) == 0b11);
@ -28,222 +37,14 @@ namespace Kernel
asm volatile("sti"); asm volatile("sti");
(void)arg1;
(void)arg2;
(void)arg3;
(void)arg4;
(void)arg5;
(void)interrupt_stack;
BAN::ErrorOr<long> ret = BAN::Error::from_errno(ENOSYS); BAN::ErrorOr<long> ret = BAN::Error::from_errno(ENOSYS);
switch (syscall) if (syscall < 0 || syscall >= __SYSCALL_COUNT)
{ dwarnln("No syscall {}", syscall);
case SYS_EXIT: else if (syscall == SYS_FORK)
ret = Process::current().sys_exit((int)arg1);
break;
case SYS_READ:
ret = Process::current().sys_read((int)arg1, (void*)arg2, (size_t)arg3);
break;
case SYS_WRITE:
ret = Process::current().sys_write((int)arg1, (const void*)arg2, (size_t)arg3);
break;
case SYS_TERMID:
ret = Process::current().sys_termid((char*)arg1);
break;
case SYS_CLOSE:
ret = Process::current().sys_close((int)arg1);
break;
case SYS_OPEN:
ret = Process::current().sys_open((const char*)arg1, (int)arg2, (mode_t)arg3);
break;
case SYS_OPENAT:
ret = Process::current().sys_openat((int)arg1, (const char*)arg2, (int)arg3, (mode_t)arg4);
break;
case SYS_SEEK:
ret = Process::current().sys_seek((int)arg1, (long)arg2, (int)arg3);
break;
case SYS_TELL:
ret = Process::current().sys_tell((int)arg1);
break;
case SYS_GET_TERMIOS:
ret = Process::current().sys_gettermios((::termios*)arg1);
break;
case SYS_SET_TERMIOS:
ret = Process::current().sys_settermios((const ::termios*)arg1);
break;
case SYS_FORK:
ret = sys_fork_trampoline(); ret = sys_fork_trampoline();
break; else
case SYS_EXEC: ret = (Process::current().*s_syscall_handlers[syscall])(arg1, arg2, arg3, arg4, arg5);
ret = Process::current().sys_exec((const char*)arg1, (const char* const*)arg2, (const char* const*)arg3);
break;
case SYS_SLEEP:
ret = Process::current().sys_sleep((unsigned int)arg1);
break;
case SYS_WAIT:
ret = Process::current().sys_wait((pid_t)arg1, (int*)arg2, (int)arg3);
break;
case SYS_FSTAT:
ret = Process::current().sys_fstat((int)arg1, (struct stat*)arg2);
break;
case SYS_READ_DIR_ENTRIES:
ret = Process::current().sys_read_dir_entries((int)arg1, (API::DirectoryEntryList*)arg2, (size_t)arg3);
break;
case SYS_SET_UID:
ret = Process::current().sys_setuid((uid_t)arg1);
break;
case SYS_SET_GID:
ret = Process::current().sys_setgid((gid_t)arg1);
break;
case SYS_SET_EUID:
ret = Process::current().sys_seteuid((uid_t)arg1);
break;
case SYS_SET_EGID:
ret = Process::current().sys_setegid((gid_t)arg1);
break;
case SYS_SET_REUID:
ret = Process::current().sys_setreuid((uid_t)arg1, (uid_t)arg2);
break;
case SYS_SET_REGID:
ret = Process::current().sys_setregid((gid_t)arg1, (gid_t)arg2);
break;
case SYS_GET_UID:
ret = Process::current().sys_getuid();
break;
case SYS_GET_GID:
ret = Process::current().sys_getgid();
break;
case SYS_GET_EUID:
ret = Process::current().sys_geteuid();
break;
case SYS_GET_EGID:
ret = Process::current().sys_getegid();
break;
case SYS_GET_PWD:
ret = Process::current().sys_getpwd((char*)arg1, (size_t)arg2);
break;
case SYS_SET_PWD:
ret = Process::current().sys_setpwd((const char*)arg1);
break;
case SYS_CLOCK_GETTIME:
ret = Process::current().sys_clock_gettime((clockid_t)arg1, (timespec*)arg2);
break;
case SYS_PIPE:
ret = Process::current().sys_pipe((int*)arg1);
break;
case SYS_DUP:
ret = Process::current().sys_dup((int)arg1);
break;
case SYS_DUP2:
ret = Process::current().sys_dup2((int)arg1, (int)arg2);
break;
case SYS_KILL:
ret = Process::current().sys_kill((pid_t)arg1, (int)arg2);
break;
case SYS_SIGNAL:
ret = Process::current().sys_signal((int)arg1, (void (*)(int))arg2);
break;
case SYS_TCSETPGRP:
ret = Process::current().sys_tcsetpgrp((int)arg1, (pid_t)arg2);
break;
case SYS_GET_PID:
ret = Process::current().pid();
break;
case SYS_GET_PGID:
ret = Process::current().sys_getpgid((pid_t)arg1);
break;
case SYS_SET_PGID:
ret = Process::current().sys_setpgid((pid_t)arg1, (pid_t)arg2);
break;
case SYS_FCNTL:
ret = Process::current().sys_fcntl((int)arg1, (int)arg2, (int)arg3);
break;
case SYS_NANOSLEEP:
ret = Process::current().sys_nanosleep((const timespec*)arg1, (timespec*)arg2);
break;
case SYS_FSTATAT:
ret = Process::current().sys_fstatat((int)arg1, (const char*)arg2, (struct stat*)arg3, (int)arg4);
break;
case SYS_STAT:
ret = Process::current().sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3);
break;
case SYS_SYNC:
ret = Process::current().sys_sync((bool)arg1);
break;
case SYS_MMAP:
ret = Process::current().sys_mmap((const sys_mmap_t*)arg1);
break;
case SYS_MUNMAP:
ret = Process::current().sys_munmap((void*)arg1, (size_t)arg2);
break;
case SYS_TTY_CTRL:
ret = Process::current().sys_tty_ctrl((int)arg1, (int)arg2, (int)arg3);
break;
case SYS_POWEROFF:
ret = Process::current().sys_poweroff((int)arg1);
break;
case SYS_CHMOD:
ret = Process::current().sys_chmod((const char*)arg1, (mode_t)arg2);
break;
case SYS_CREATE:
ret = Process::current().sys_create((const char*)arg1, (mode_t)arg2);
break;
case SYS_CREATE_DIR:
ret = Process::current().sys_create_dir((const char*)arg1, (mode_t)arg2);
break;
case SYS_UNLINK:
ret = Process::current().sys_unlink((const char*)arg1);
break;
case SYS_READLINK:
ret = Process::current().sys_readlink((const char*)arg1, (char*)arg2, (size_t)arg3);
break;
case SYS_READLINKAT:
ret = Process::current().sys_readlinkat((int)arg1, (const char*)arg2, (char*)arg3, (size_t)arg4);
break;
case SYS_MSYNC:
ret = Process::current().sys_msync((void*)arg1, (size_t)arg2, (int)arg3);
break;
case SYS_PREAD:
ret = Process::current().sys_pread((int)arg1, (void*)arg2, (size_t)arg3, (off_t)arg4);
break;
case SYS_CHOWN:
ret = Process::current().sys_chown((const char*)arg1, (uid_t)arg2, (gid_t)arg3);
break;
case SYS_LOAD_KEYMAP:
ret = Process::current().sys_load_keymap((const char*)arg1);
break;
case SYS_SOCKET:
ret = Process::current().sys_socket((int)arg1, (int)arg2, (int)arg3);
break;
case SYS_BIND:
ret = Process::current().sys_bind((int)arg1, (const sockaddr*)arg2, (socklen_t)arg3);
break;
case SYS_SENDTO:
ret = Process::current().sys_sendto((const sys_sendto_t*)arg1);
break;
case SYS_RECVFROM:
ret = Process::current().sys_recvfrom((sys_recvfrom_t*)arg1);
break;
case SYS_IOCTL:
ret = Process::current().sys_ioctl((int)arg1, (int)arg2, (void*)arg3);
break;
case SYS_ACCEPT:
ret = Process::current().sys_accept((int)arg1, (sockaddr*)arg2, (socklen_t*)arg3);
break;
case SYS_CONNECT:
ret = Process::current().sys_connect((int)arg1, (const sockaddr*)arg2, (socklen_t)arg3);
break;
case SYS_LISTEN:
ret = Process::current().sys_listen((int)arg1, (int)arg2);
break;
case SYS_PSELECT:
ret = Process::current().sys_pselect((sys_pselect_t*)arg1);
break;
default:
dwarnln("Unknown syscall {}", syscall);
break;
}
asm volatile("cli"); asm volatile("cli");

View File

@ -210,7 +210,7 @@ namespace Kernel
// ^C // ^C
if (ch == '\x03') if (ch == '\x03')
{ {
if (auto ret = Process::sys_kill(-m_foreground_pgrp, SIGINT); ret.is_error()) if (auto ret = Process::current().sys_kill(-m_foreground_pgrp, SIGINT); ret.is_error())
dwarnln("TTY: {}", ret.error()); dwarnln("TTY: {}", ret.error());
return; return;
} }

View File

@ -79,7 +79,7 @@ struct dirent* readdir(DIR* dirp)
return &dirp->current->dirent; return &dirp->current->dirent;
} }
if (syscall(SYS_READ_DIR_ENTRIES, dirp->fd, dirp->buffer, dirp->buffer_size) == -1) if (syscall(SYS_READ_DIR, dirp->fd, dirp->buffer, dirp->buffer_size) == -1)
return nullptr; return nullptr;
if (dirp->buffer->entry_count == 0) if (dirp->buffer->entry_count == 0)

View File

@ -5,73 +5,82 @@
__BEGIN_DECLS __BEGIN_DECLS
#define SYS_EXIT 1 #define __SYSCALL_LIST(O) \
#define SYS_READ 2 O(SYS_EXIT, exit) \
#define SYS_WRITE 3 O(SYS_READ, read) \
#define SYS_TERMID 4 O(SYS_WRITE, write) \
#define SYS_CLOSE 5 O(SYS_TERMID, termid) \
#define SYS_OPEN 6 O(SYS_CLOSE, close) \
#define SYS_OPENAT 7 O(SYS_OPEN, open) \
#define SYS_SEEK 11 O(SYS_OPENAT, openat) \
#define SYS_TELL 12 O(SYS_SEEK, seek) \
#define SYS_GET_TERMIOS 13 O(SYS_TELL, tell) \
#define SYS_SET_TERMIOS 14 O(SYS_GET_TERMIOS, gettermios) \
#define SYS_FORK 15 O(SYS_SET_TERMIOS, settermios) \
#define SYS_EXEC 16 O(SYS_FORK, fork) \
#define SYS_SLEEP 17 O(SYS_EXEC, exec) \
#define SYS_WAIT 18 O(SYS_SLEEP, sleep) \
#define SYS_FSTAT 19 O(SYS_WAIT, wait) \
#define SYS_READ_DIR_ENTRIES 21 O(SYS_FSTAT, fstat) \
#define SYS_SET_UID 22 O(SYS_READ_DIR, readdir) \
#define SYS_SET_GID 23 O(SYS_SET_UID, setuid) \
#define SYS_SET_EUID 24 O(SYS_SET_GID, setgid) \
#define SYS_SET_EGID 25 O(SYS_SET_EUID, seteuid) \
#define SYS_SET_REUID 26 O(SYS_SET_EGID, setegid) \
#define SYS_SET_REGID 27 O(SYS_SET_REUID, setreuid) \
#define SYS_GET_UID 28 O(SYS_SET_REGID, setregid) \
#define SYS_GET_GID 29 O(SYS_GET_UID, getuid) \
#define SYS_GET_EUID 30 O(SYS_GET_GID, getgid) \
#define SYS_GET_EGID 31 O(SYS_GET_EUID, geteuid) \
#define SYS_GET_PWD 32 O(SYS_GET_EGID, getegid) \
#define SYS_SET_PWD 33 O(SYS_GET_PWD, getpwd) \
#define SYS_CLOCK_GETTIME 34 O(SYS_SET_PWD, setpwd) \
#define SYS_PIPE 35 O(SYS_CLOCK_GETTIME, clock_gettime) \
#define SYS_DUP 36 O(SYS_PIPE, pipe) \
#define SYS_DUP2 37 O(SYS_DUP, dup) \
#define SYS_KILL 39 O(SYS_DUP2, dup2) \
#define SYS_SIGNAL 40 O(SYS_KILL, kill) \
#define SYS_TCSETPGRP 42 O(SYS_SIGNAL, signal) \
#define SYS_GET_PID 43 O(SYS_TCSETPGRP, tcsetpgrp) \
#define SYS_GET_PGID 44 O(SYS_GET_PID, getpid) \
#define SYS_SET_PGID 45 O(SYS_GET_PGID, getpgid) \
#define SYS_FCNTL 46 O(SYS_SET_PGID, setpgid) \
#define SYS_NANOSLEEP 47 O(SYS_FCNTL, fcntl) \
#define SYS_FSTATAT 48 O(SYS_NANOSLEEP, nanosleep) \
#define SYS_STAT 49 // stat/lstat O(SYS_FSTATAT, fstatat) \
#define SYS_SYNC 50 O(SYS_STAT, stat) \
#define SYS_MMAP 51 O(SYS_SYNC, sync) \
#define SYS_MUNMAP 52 O(SYS_MMAP, mmap) \
#define SYS_TTY_CTRL 53 O(SYS_MUNMAP, munmap) \
#define SYS_POWEROFF 54 O(SYS_TTY_CTRL, tty_ctrl) \
#define SYS_CHMOD 55 O(SYS_POWEROFF, poweroff) \
#define SYS_CREATE 56 // creat, mkfifo O(SYS_CHMOD, chmod) \
#define SYS_CREATE_DIR 57 // mkdir O(SYS_CREATE, create) \
#define SYS_UNLINK 58 O(SYS_CREATE_DIR, create_dir) \
#define SYS_READLINK 59 O(SYS_UNLINK, unlink) \
#define SYS_READLINKAT 60 O(SYS_READLINK, readlink) \
#define SYS_MSYNC 61 O(SYS_READLINKAT, readlinkat) \
#define SYS_PREAD 62 O(SYS_MSYNC, msync) \
#define SYS_CHOWN 63 O(SYS_PREAD, pread) \
#define SYS_LOAD_KEYMAP 64 O(SYS_CHOWN, chown) \
#define SYS_SOCKET 65 O(SYS_LOAD_KEYMAP, load_keymap) \
#define SYS_BIND 66 O(SYS_SOCKET, socket) \
#define SYS_SENDTO 67 O(SYS_BIND, bind) \
#define SYS_RECVFROM 68 O(SYS_SENDTO, sendto) \
#define SYS_IOCTL 69 O(SYS_RECVFROM, recvfrom) \
#define SYS_ACCEPT 70 O(SYS_IOCTL, ioctl) \
#define SYS_CONNECT 71 O(SYS_ACCEPT, accept) \
#define SYS_LISTEN 72 O(SYS_CONNECT, connect) \
#define SYS_PSELECT 73 O(SYS_LISTEN, listen) \
O(SYS_PSELECT, pselect) \
enum Syscall
{
#define O(enum, name) enum,
__SYSCALL_LIST(O)
#undef O
__SYSCALL_COUNT
};
__END_DECLS __END_DECLS