100 lines
3.6 KiB
C++
100 lines
3.6 KiB
C++
#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<int>(p1), reinterpret_cast<const void*>(p2), p3, reinterpret_cast<void*>(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(v, user);
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
return static_cast<size_t>(-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
|