Syscall.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include <Kernel/Arch/i386/CPU.h>
  2. #include <Kernel/Process.h>
  3. #include <Kernel/ProcessTracer.h>
  4. #include <Kernel/Syscall.h>
  5. extern "C" void syscall_trap_entry(RegisterDump);
  6. extern "C" void syscall_trap_handler();
  7. asm(
  8. ".globl syscall_trap_handler \n"
  9. "syscall_trap_handler:\n"
  10. " pushl $0x0\n"
  11. " pusha\n"
  12. " pushw %ds\n"
  13. " pushw %es\n"
  14. " pushw %fs\n"
  15. " pushw %gs\n"
  16. " pushw %ss\n"
  17. " pushw %ss\n"
  18. " pushw %ss\n"
  19. " pushw %ss\n"
  20. " pushw %ss\n"
  21. " popw %ds\n"
  22. " popw %es\n"
  23. " popw %fs\n"
  24. " popw %gs\n"
  25. " call syscall_trap_entry\n"
  26. " popw %gs\n"
  27. " popw %gs\n"
  28. " popw %fs\n"
  29. " popw %es\n"
  30. " popw %ds\n"
  31. " popa\n"
  32. " add $0x4, %esp\n"
  33. " iret\n");
  34. namespace Syscall {
  35. static int handle(RegisterDump&, u32 function, u32 arg1, u32 arg2, u32 arg3);
  36. void initialize()
  37. {
  38. register_user_callable_interrupt_handler(0x82, syscall_trap_handler);
  39. kprintf("Syscall: int 0x82 handler installed\n");
  40. }
  41. #pragma GCC diagnostic ignored "-Wcast-function-type"
  42. typedef int (Process::*Handler)(u32, u32, u32);
  43. #define __ENUMERATE_SYSCALL(x) reinterpret_cast<Handler>(&Process::sys$##x),
  44. static Handler s_syscall_table[] = {
  45. ENUMERATE_SYSCALLS
  46. };
  47. #undef __ENUMERATE_SYSCALL
  48. int handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
  49. {
  50. ASSERT_INTERRUPTS_ENABLED();
  51. auto& process = current->process();
  52. process.did_syscall();
  53. if (function == SC_exit || function == SC_exit_thread) {
  54. // These syscalls need special handling since they never return to the caller.
  55. cli();
  56. if (auto* tracer = process.tracer())
  57. tracer->did_syscall(function, arg1, arg2, arg3, 0);
  58. if (function == SC_exit)
  59. process.sys$exit((int)arg1);
  60. else
  61. process.sys$exit_thread((int)arg1);
  62. ASSERT_NOT_REACHED();
  63. return 0;
  64. }
  65. if (function == SC_fork)
  66. return process.sys$fork(regs);
  67. if (function == SC_sigreturn)
  68. return process.sys$sigreturn(regs);
  69. if (function >= Function::__Count) {
  70. dbg() << process << ": Unknown syscall %u requested (" << arg1 << ", " << arg2 << ", " << arg3 << ")";
  71. return -ENOSYS;
  72. }
  73. return (process.*(s_syscall_table[function]))(arg1, arg2, arg3);
  74. }
  75. }
  76. void syscall_trap_entry(RegisterDump regs)
  77. {
  78. auto& process = current->process();
  79. process.big_lock().lock();
  80. u32 function = regs.eax;
  81. u32 arg1 = regs.edx;
  82. u32 arg2 = regs.ecx;
  83. u32 arg3 = regs.ebx;
  84. regs.eax = (u32)Syscall::handle(regs, function, arg1, arg2, arg3);
  85. if (auto* tracer = process.tracer())
  86. tracer->did_syscall(function, arg1, arg2, arg3, regs.eax);
  87. process.big_lock().unlock();
  88. }