Kernel: Improve syscall handling

Syscalls are now called from a list of function pointers
This commit is contained in:
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;
}