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"
#include <sys/syscall.h>
// stack contains
// return address
// signal number

View File

@ -96,6 +96,8 @@ namespace Kernel
BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); }
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<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<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_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_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);

View File

@ -1218,7 +1218,7 @@ namespace Kernel
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);
TRY(validate_pointer_access(list, list_size));

View File

@ -1,3 +1,4 @@
#include <BAN/Bitcast.h>
#include <kernel/Debug.h>
#include <kernel/InterruptStack.h>
#include <kernel/Process.h>
@ -19,6 +20,14 @@ namespace Kernel
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)
{
ASSERT((interrupt_stack.cs & 0b11) == 0b11);
@ -28,222 +37,14 @@ namespace Kernel
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);
switch (syscall)
{
case SYS_EXIT:
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:
if (syscall < 0 || syscall >= __SYSCALL_COUNT)
dwarnln("No syscall {}", syscall);
else if (syscall == SYS_FORK)
ret = sys_fork_trampoline();
break;
case SYS_EXEC:
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;
}
else
ret = (Process::current().*s_syscall_handlers[syscall])(arg1, arg2, arg3, arg4, arg5);
asm volatile("cli");

View File

@ -210,7 +210,7 @@ namespace Kernel
// ^C
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());
return;
}

View File

@ -79,7 +79,7 @@ struct dirent* readdir(DIR* dirp)
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;
if (dirp->buffer->entry_count == 0)

View File

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