165 lines
6.5 KiB
C
165 lines
6.5 KiB
C
/// @file syscall.c
|
|
/// @brief System Call management functions.
|
|
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
|
|
/// See LICENSE.md for details.
|
|
|
|
// Include the kernel log levels.
|
|
#include "sys/kernel_levels.h"
|
|
/// Change the header.
|
|
#define __DEBUG_HEADER__ "[SYSCLL]"
|
|
/// Set the log level.
|
|
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE
|
|
|
|
#include "devices/fpu.h"
|
|
#include "mem/kheap.h"
|
|
#include "system/syscall.h"
|
|
#include "descriptor_tables/isr.h"
|
|
#include "sys/errno.h"
|
|
#include "kernel.h"
|
|
#include "process/process.h"
|
|
#include "process/scheduler.h"
|
|
#include "sys/utsname.h"
|
|
#include "fs/ioctl.h"
|
|
#include "hardware/timer.h"
|
|
|
|
#include "ipc/msg.h"
|
|
#include "ipc/sem.h"
|
|
#include "ipc/shm.h"
|
|
|
|
/// The signature of a function call.
|
|
typedef int (*SystemCall)();
|
|
|
|
/// The list of function call.
|
|
SystemCall sys_call_table[SYSCALL_NUMBER];
|
|
|
|
/// Last interupt stack frame
|
|
static pt_regs *current_interrupt_stack_frame;
|
|
|
|
/// @brief A Not Implemented (NI) system-call.
|
|
/// @return Always returns -ENOSYS.
|
|
/// @details
|
|
/// Linux provides a "not implemented" system call, sys_ni_syscall(), which does
|
|
/// nothing except return ENOSYS, the error corresponding to an invalid
|
|
/// system call. This function is used to "plug the hole" in the rare event that
|
|
/// a syscall is removed or otherwise made unavailable.
|
|
static inline int sys_ni_syscall()
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
void syscall_init()
|
|
{
|
|
// Initialize the list of system calls.
|
|
for (uint32_t it = 0; it < SYSCALL_NUMBER; ++it) {
|
|
sys_call_table[it] = sys_ni_syscall;
|
|
}
|
|
|
|
sys_call_table[__NR_exit] = (SystemCall)sys_exit;
|
|
sys_call_table[__NR_read] = (SystemCall)sys_read;
|
|
sys_call_table[__NR_write] = (SystemCall)sys_write;
|
|
sys_call_table[__NR_open] = (SystemCall)sys_open;
|
|
sys_call_table[__NR_close] = (SystemCall)sys_close;
|
|
sys_call_table[__NR_stat] = (SystemCall)sys_stat;
|
|
sys_call_table[__NR_fstat] = (SystemCall)sys_fstat;
|
|
sys_call_table[__NR_mkdir] = (SystemCall)sys_mkdir;
|
|
sys_call_table[__NR_rmdir] = (SystemCall)sys_rmdir;
|
|
sys_call_table[__NR_creat] = (SystemCall)sys_creat;
|
|
sys_call_table[__NR_unlink] = (SystemCall)sys_unlink;
|
|
sys_call_table[__NR_getdents] = (SystemCall)sys_getdents;
|
|
sys_call_table[__NR_lseek] = (SystemCall)sys_lseek;
|
|
sys_call_table[__NR_getpid] = (SystemCall)sys_getpid;
|
|
sys_call_table[__NR_getsid] = (SystemCall)sys_getsid;
|
|
sys_call_table[__NR_setsid] = (SystemCall)sys_setsid;
|
|
sys_call_table[__NR_getpgid] = (SystemCall)sys_getpgid;
|
|
sys_call_table[__NR_setpgid] = (SystemCall)sys_setpgid;
|
|
sys_call_table[__NR_getuid] = (SystemCall)sys_getuid;
|
|
sys_call_table[__NR_setuid] = (SystemCall)sys_setuid;
|
|
sys_call_table[__NR_getgid] = (SystemCall)sys_getgid;
|
|
sys_call_table[__NR_setgid] = (SystemCall)sys_setgid;
|
|
sys_call_table[__NR_getppid] = (SystemCall)sys_getppid;
|
|
sys_call_table[__NR_sigaction] = (SystemCall)sys_sigaction;
|
|
sys_call_table[__NR_fork] = (SystemCall)sys_fork;
|
|
sys_call_table[__NR_execve] = (SystemCall)sys_execve;
|
|
sys_call_table[__NR_nice] = (SystemCall)sys_nice;
|
|
sys_call_table[__NR_kill] = (SystemCall)sys_kill;
|
|
sys_call_table[__NR_reboot] = (SystemCall)sys_reboot;
|
|
sys_call_table[__NR_uname] = (SystemCall)sys_uname;
|
|
sys_call_table[__NR_sigreturn] = (SystemCall)sys_sigreturn;
|
|
sys_call_table[__NR_waitpid] = (SystemCall)sys_waitpid;
|
|
sys_call_table[__NR_chdir] = (SystemCall)sys_chdir;
|
|
sys_call_table[__NR_fchdir] = (SystemCall)sys_fchdir;
|
|
sys_call_table[__NR_time] = (SystemCall)sys_time;
|
|
sys_call_table[__NR_sigprocmask] = (SystemCall)sys_sigprocmask;
|
|
sys_call_table[__NR_brk] = (SystemCall)sys_brk;
|
|
sys_call_table[__NR_signal] = (SystemCall)sys_signal;
|
|
sys_call_table[__NR_ioctl] = (SystemCall)sys_ioctl;
|
|
sys_call_table[__NR_sched_setparam] = (SystemCall)sys_sched_setparam;
|
|
sys_call_table[__NR_sched_getparam] = (SystemCall)sys_sched_getparam;
|
|
sys_call_table[__NR_nanosleep] = (SystemCall)sys_nanosleep;
|
|
sys_call_table[__NR_getcwd] = (SystemCall)sys_getcwd;
|
|
sys_call_table[__NR_waitperiod] = (SystemCall)sys_waitperiod;
|
|
sys_call_table[__NR_msgctl] = (SystemCall)sys_msgctl;
|
|
sys_call_table[__NR_msgget] = (SystemCall)sys_msgget;
|
|
sys_call_table[__NR_msgrcv] = (SystemCall)sys_msgrcv;
|
|
sys_call_table[__NR_msgsnd] = (SystemCall)sys_msgsnd;
|
|
sys_call_table[__NR_semctl] = (SystemCall)sys_semctl;
|
|
sys_call_table[__NR_semget] = (SystemCall)sys_semget;
|
|
sys_call_table[__NR_semop] = (SystemCall)sys_semop;
|
|
sys_call_table[__NR_shmat] = (SystemCall)sys_shmat;
|
|
sys_call_table[__NR_shmctl] = (SystemCall)sys_shmctl;
|
|
sys_call_table[__NR_shmdt] = (SystemCall)sys_shmdt;
|
|
sys_call_table[__NR_shmget] = (SystemCall)sys_shmget;
|
|
sys_call_table[__NR_alarm] = (SystemCall)sys_alarm;
|
|
sys_call_table[__NR_setitimer] = (SystemCall)sys_setitimer;
|
|
sys_call_table[__NR_getitimer] = (SystemCall)sys_getitimer;
|
|
|
|
isr_install_handler(SYSTEM_CALL, &syscall_handler, "syscall_handler");
|
|
}
|
|
|
|
pt_regs *get_current_interrupt_stack_frame()
|
|
{
|
|
return current_interrupt_stack_frame;
|
|
}
|
|
|
|
void syscall_handler(pt_regs *f)
|
|
{
|
|
// Saves current interrupt stack frame
|
|
current_interrupt_stack_frame = f;
|
|
|
|
// dbg_print_regs(f);
|
|
// Save current process fpu state.
|
|
switch_fpu();
|
|
|
|
// The index of the requested system call.
|
|
uint32_t sc_index = f->eax;
|
|
|
|
// The result of the system call.
|
|
int ret;
|
|
if (sc_index >= SYSCALL_NUMBER) {
|
|
ret = ENOSYS;
|
|
} else {
|
|
uintptr_t ptr = (uintptr_t)sys_call_table[sc_index];
|
|
|
|
SystemCall func = (SystemCall)ptr;
|
|
|
|
uint32_t arg0 = f->ebx;
|
|
uint32_t arg1 = f->ecx;
|
|
uint32_t arg2 = f->edx;
|
|
uint32_t arg3 = f->esi;
|
|
uint32_t arg4 = f->edi;
|
|
if ((sc_index == __NR_fork) ||
|
|
(sc_index == __NR_clone) ||
|
|
(sc_index == __NR_execve) ||
|
|
(sc_index == __NR_sigreturn)) {
|
|
arg0 = (uintptr_t)f;
|
|
}
|
|
ret = func(arg0, arg1, arg2, arg3, arg4);
|
|
}
|
|
f->eax = ret;
|
|
|
|
// Schedule next process.
|
|
scheduler_run(f);
|
|
// Restore fpu state.
|
|
unswitch_fpu();
|
|
}
|