#include "syscall/handler.h" #include "arch/core_interrupt.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 sysnum identifier 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 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) { (void) 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; case Syscall::ID::SYS_KILL: Syscall::Skeleton::kill(Guard::enter().vault(),p1); return 0; case Syscall::ID::MAP: return (size_t) Skeleton::map(&(Guard::enter().vault()), p1); case Syscall::ID::UNMAP: return (int) Skeleton::unmap(Guard::enter().vault(), (void*) (p1), p2); case Syscall::ID::SEND: return Skeleton::send(Guard::enter().vault(), static_cast(p1), reinterpret_cast(p2), p3, reinterpret_cast(p4), p5); case Syscall::ID::RECEIVE: return Skeleton::receive(Guard::enter().vault(), (void*)(p1), p2); case Syscall::ID::REPLY: return Skeleton::reply(Guard::enter().vault(), (void*)(p1), p2); case Syscall::ID::FORK: return Skeleton::fork(Guard::enter().vault(), user); break; } 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