syscall.rs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. use crate::{
  2. kernel::task::{ProcessList, Signal},
  3. println_warn,
  4. };
  5. use arch::{ExtendedContext, InterruptContext};
  6. extern crate arch;
  7. mod file_rw;
  8. mod mm;
  9. mod net;
  10. mod procops;
  11. mod sysinfo;
  12. pub(self) struct MapArgumentImpl;
  13. pub(self) trait MapArgument<'a, T: 'a> {
  14. fn map_arg(value: u64) -> T;
  15. }
  16. pub(self) trait MapReturnValue {
  17. fn map_ret(self) -> usize;
  18. }
  19. impl MapReturnValue for () {
  20. fn map_ret(self) -> usize {
  21. 0
  22. }
  23. }
  24. impl MapReturnValue for u32 {
  25. fn map_ret(self) -> usize {
  26. self as usize
  27. }
  28. }
  29. impl MapReturnValue for usize {
  30. fn map_ret(self) -> usize {
  31. self
  32. }
  33. }
  34. impl MapArgument<'_, u64> for MapArgumentImpl {
  35. fn map_arg(value: u64) -> u64 {
  36. value as u64
  37. }
  38. }
  39. impl MapArgument<'_, u32> for MapArgumentImpl {
  40. fn map_arg(value: u64) -> u32 {
  41. value as u32
  42. }
  43. }
  44. impl MapArgument<'_, i32> for MapArgumentImpl {
  45. fn map_arg(value: u64) -> i32 {
  46. value as i32
  47. }
  48. }
  49. impl MapArgument<'_, usize> for MapArgumentImpl {
  50. fn map_arg(value: u64) -> usize {
  51. value as usize
  52. }
  53. }
  54. impl<'a, T: 'a> MapArgument<'a, *const T> for MapArgumentImpl {
  55. fn map_arg(value: u64) -> *const T {
  56. value as *const _
  57. }
  58. }
  59. impl<'a, T: 'a> MapArgument<'a, *mut T> for MapArgumentImpl {
  60. fn map_arg(value: u64) -> *mut T {
  61. value as *mut _
  62. }
  63. }
  64. macro_rules! arg_register {
  65. (0, $is:ident) => {
  66. $is.rbx
  67. };
  68. (1, $is:ident) => {
  69. $is.rcx
  70. };
  71. (2, $is:ident) => {
  72. $is.rdx
  73. };
  74. (3, $is:ident) => {
  75. $is.rsi
  76. };
  77. (4, $is:ident) => {
  78. $is.rdi
  79. };
  80. (5, $is:ident) => {
  81. $is.rbp
  82. };
  83. }
  84. #[allow(unused_macros)]
  85. macro_rules! format_expand {
  86. ($name:ident, $arg:tt) => {
  87. format_args!("{}: {:x?}", stringify!($name), $arg)
  88. };
  89. ($name1:ident, $arg1:tt, $($name:ident, $arg:tt),*) => {
  90. format_args!("{}: {:x?}, {}", stringify!($name1), $arg1, format_expand!($($name, $arg),*))
  91. }
  92. }
  93. macro_rules! syscall32_call {
  94. ($is:ident, $handler:ident, $($arg:ident: $type:ty),*) => {{
  95. use $crate::kernel::syscall::{MapArgument, MapArgumentImpl, arg_register};
  96. #[allow(unused_imports)]
  97. use $crate::kernel::syscall::{MapReturnValue, format_expand};
  98. #[allow(unused_imports)]
  99. use $crate::{kernel::task::Thread, println_trace};
  100. $(
  101. let $arg: $type =
  102. MapArgumentImpl::map_arg(arg_register!(${index()}, $is));
  103. )*
  104. println_trace!(
  105. "trace_syscall",
  106. "tid{}: {}({}) => {{",
  107. Thread::current().tid,
  108. stringify!($handler),
  109. format_expand!($($arg, $arg),*),
  110. );
  111. let result = $handler($($arg),*);
  112. println_trace!(
  113. "trace_syscall",
  114. "tid{}: {}({}) => }} = {:x?}",
  115. Thread::current().tid,
  116. stringify!($handler),
  117. format_expand!($($arg, $arg),*),
  118. result
  119. );
  120. match result {
  121. Ok(val) => MapReturnValue::map_ret(val),
  122. Err(err) => (-(err as i32)) as usize,
  123. }
  124. }};
  125. }
  126. macro_rules! define_syscall32 {
  127. ($name:ident, $handler:ident) => {
  128. fn $name(_int_stack: &mut $crate::kernel::syscall::arch::InterruptContext,
  129. _: &mut ::arch::ExtendedContext) -> usize {
  130. use $crate::kernel::syscall::MapReturnValue;
  131. match $handler() {
  132. Ok(val) => MapReturnValue::map_ret(val),
  133. Err(err) => (-(err as i32)) as usize,
  134. }
  135. }
  136. };
  137. ($name:ident, $handler:ident, $($arg:ident: $argt:ty),*) => {
  138. fn $name(
  139. int_stack: &mut $crate::kernel::syscall::arch::InterruptContext,
  140. _: &mut ::arch::ExtendedContext) -> usize {
  141. use $crate::kernel::syscall::syscall32_call;
  142. syscall32_call!(int_stack, $handler, $($arg: $argt),*)
  143. }
  144. };
  145. }
  146. macro_rules! register_syscall {
  147. ($no:expr, $name:ident) => {
  148. $crate::kernel::syscall::register_syscall_handler(
  149. $no,
  150. concat_idents!(sys_, $name),
  151. stringify!($name),
  152. );
  153. };
  154. }
  155. use super::task::Thread;
  156. pub(self) use {arg_register, define_syscall32, format_expand, register_syscall, syscall32_call};
  157. #[allow(dead_code)]
  158. pub(self) struct SyscallHandler {
  159. handler: fn(&mut InterruptContext, &mut ExtendedContext) -> usize,
  160. name: &'static str,
  161. }
  162. pub(self) fn register_syscall_handler(
  163. no: usize,
  164. handler: fn(&mut InterruptContext, &mut ExtendedContext) -> usize,
  165. name: &'static str,
  166. ) {
  167. // SAFETY: `SYSCALL_HANDLERS` is never modified after initialization.
  168. #[allow(static_mut_refs)]
  169. let syscall = unsafe { SYSCALL_HANDLERS.get_mut(no) }.unwrap();
  170. assert!(
  171. syscall.replace(SyscallHandler { handler, name }).is_none(),
  172. "Syscall {} is already registered",
  173. no
  174. );
  175. }
  176. pub fn register_syscalls() {
  177. file_rw::register();
  178. procops::register();
  179. mm::register();
  180. net::register();
  181. sysinfo::register();
  182. }
  183. const SYSCALL_HANDLERS_SIZE: usize = 404;
  184. static mut SYSCALL_HANDLERS: [Option<SyscallHandler>; SYSCALL_HANDLERS_SIZE] =
  185. [const { None }; SYSCALL_HANDLERS_SIZE];
  186. pub fn handle_syscall32(
  187. no: usize,
  188. int_stack: &mut InterruptContext,
  189. ext_ctx: &mut ExtendedContext,
  190. ) {
  191. // SAFETY: `SYSCALL_HANDLERS` are never modified after initialization.
  192. #[allow(static_mut_refs)]
  193. let syscall = unsafe { SYSCALL_HANDLERS.get(no) }.and_then(Option::as_ref);
  194. match syscall {
  195. None => {
  196. println_warn!("Syscall {no}({no:#x}) isn't implemented.");
  197. ProcessList::kill_current(Signal::SIGSYS);
  198. }
  199. Some(handler) => {
  200. arch::enable_irqs();
  201. let retval = (handler.handler)(int_stack, ext_ctx);
  202. // SAFETY: `int_stack` is always valid.
  203. int_stack.rax = retval as u64;
  204. int_stack.r8 = 0;
  205. int_stack.r9 = 0;
  206. int_stack.r10 = 0;
  207. int_stack.r11 = 0;
  208. int_stack.r12 = 0;
  209. int_stack.r13 = 0;
  210. int_stack.r14 = 0;
  211. int_stack.r15 = 0;
  212. }
  213. }
  214. if Thread::current().signal_list.has_pending_signal() {
  215. Thread::current().signal_list.handle(int_stack, ext_ctx);
  216. }
  217. }