#include "syscall/handler.h" #include "../arch/core.h" #include "../arch/core_interrupt.h" #include "../arch/gdt.h" #include "../arch/idt.h" #include "../debug/kernelpanic.h" #include "../debug/output.h" #include "../interrupt/guard.h" #include "../syscall/skeleton.h" #include "../syscall/stub.h" #include "types.h" /*! \brief Interrupt based system call entry function * * Low-level function written in assembly (located in `syscall/handler.asm`), * calls \ref syscall_handler */ extern "C" [[gnu::interrupt]] void syscall_entry(InterruptContext *context); namespace Syscall { /*! \brief High level system call handler * called by both low level handler in `syscall/handler.asm`. * * Processes the request by delegating it to the appropriate function identified * by the system call number -- allowing up to five parameters for the system * call. * * \param p1 first parameter * \param p2 second parameter * \param p3 third parameter * \param p4 fourth parameter * \param p5 fifth parameter * \param sysnum identifier for the system call * \param user pointer to the interrupt \ref context (for example to determine * instruction pointer) * \return system call return value */ extern "C" size_t syscall_handler(size_t sysnum, size_t p1, size_t p2, size_t p3, size_t p4, size_t p5, InterruptContext *user) { switch ((Syscall::ID)sysnum) { case Syscall::ID::TEST: return Syscall::Skeleton::test(Guard::enter().vault(), p1, p2, p3, p4, p5); case Syscall::ID::WRITE: return Syscall::Skeleton::write(Guard::enter().vault(), p1, (char*)p2, p3, (int)p4, (int)p5); case Syscall::ID::READ: return Syscall::Skeleton::read(Guard::enter().vault(), 0, (void*) p2, p3); case Syscall::ID::SLEEP: Syscall::Skeleton::sleep(Guard::enter().vault(), p1); return 0; case Syscall::ID::SEM_INIT: Syscall::Skeleton::sem_init(Guard::enter().vault(), p1, p2); break; case Syscall::ID::SEM_DESTROY: Syscall::Skeleton::sem_destroy(Guard::enter().vault(), p1); break; case Syscall::ID::SEM_WAIT: Syscall::Skeleton::sem_wait(Guard::enter().vault(), p1); break; case Syscall::ID::SEM_SIGNAL: Syscall::Skeleton::sem_signal(Guard::enter().vault(), p1); break; case Syscall::ID::SYS_GETPID: return Syscall::Skeleton::getpid(Guard::enter().vault()); case Syscall::ID::SYS_EXIT: Syscall::Skeleton::exit(Guard::enter().vault()); return 0; } return static_cast(-1); } void init() { // Set interrupt based syscall handler IDT::set(Core::Interrupt::Vector::SYSCALL, IDT::InterruptDescriptor::Returning(syscall_entry, 0, IDT::DPL_USER)); IDT::load(); } } // namespace Syscall