syscall.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. use crate::kernel::task::Thread;
  2. use eonix_sync::LazyLock;
  3. pub mod file_rw;
  4. pub mod mm;
  5. pub mod net;
  6. pub mod procops;
  7. pub mod sysinfo;
  8. const MAX_SYSCALL_NO: usize = 512;
  9. #[derive(Debug, Clone, Copy)]
  10. pub struct SyscallNoReturn;
  11. #[repr(C)]
  12. pub(self) struct RawSyscallHandler {
  13. no: usize,
  14. handler: fn(&Thread, [usize; 6]) -> Option<usize>,
  15. name: &'static str,
  16. }
  17. pub struct SyscallHandler {
  18. pub handler: fn(&Thread, [usize; 6]) -> Option<usize>,
  19. pub name: &'static str,
  20. }
  21. pub trait FromSyscallArg: core::fmt::Debug {
  22. fn from_arg(value: usize) -> Self;
  23. }
  24. pub trait SyscallRetVal: core::fmt::Debug {
  25. fn into_retval(self) -> Option<usize>;
  26. }
  27. impl<T> SyscallRetVal for Result<T, u32>
  28. where
  29. T: SyscallRetVal,
  30. {
  31. fn into_retval(self) -> Option<usize> {
  32. match self {
  33. Ok(v) => v.into_retval(),
  34. Err(e) => Some((-(e as isize)) as usize),
  35. }
  36. }
  37. }
  38. impl SyscallRetVal for () {
  39. fn into_retval(self) -> Option<usize> {
  40. Some(0)
  41. }
  42. }
  43. impl SyscallRetVal for u32 {
  44. fn into_retval(self) -> Option<usize> {
  45. Some(self as usize)
  46. }
  47. }
  48. impl SyscallRetVal for usize {
  49. fn into_retval(self) -> Option<usize> {
  50. Some(self)
  51. }
  52. }
  53. impl SyscallRetVal for SyscallNoReturn {
  54. fn into_retval(self) -> Option<usize> {
  55. None
  56. }
  57. }
  58. impl FromSyscallArg for u64 {
  59. fn from_arg(value: usize) -> u64 {
  60. value as u64
  61. }
  62. }
  63. impl FromSyscallArg for u32 {
  64. fn from_arg(value: usize) -> u32 {
  65. value as u32
  66. }
  67. }
  68. impl FromSyscallArg for i32 {
  69. fn from_arg(value: usize) -> i32 {
  70. value as i32
  71. }
  72. }
  73. impl FromSyscallArg for usize {
  74. fn from_arg(value: usize) -> usize {
  75. value
  76. }
  77. }
  78. impl<T> FromSyscallArg for *const T {
  79. fn from_arg(value: usize) -> *const T {
  80. value as *const T
  81. }
  82. }
  83. impl<T> FromSyscallArg for *mut T {
  84. fn from_arg(value: usize) -> *mut T {
  85. value as *mut T
  86. }
  87. }
  88. static SYSCALL_HANDLERS: LazyLock<[Option<SyscallHandler>; MAX_SYSCALL_NO]> = LazyLock::new(|| {
  89. extern "C" {
  90. // SAFETY: `SYSCALL_HANDLERS` is defined in linker script.
  91. fn RAW_SYSCALL_HANDLERS();
  92. fn RAW_SYSCALL_HANDLERS_SIZE();
  93. }
  94. // DO NOT TOUCH THESE FUNCTIONS!!!
  95. // THEY ARE USED FOR KEEPING THE OBJECTS NOT STRIPPED BY THE LINKER!!!
  96. file_rw::keep_alive();
  97. mm::keep_alive();
  98. net::keep_alive();
  99. procops::keep_alive();
  100. sysinfo::keep_alive();
  101. let raw_handlers_addr = RAW_SYSCALL_HANDLERS as *const ();
  102. let raw_handlers_size_byte = RAW_SYSCALL_HANDLERS_SIZE as usize;
  103. assert!(raw_handlers_size_byte % size_of::<RawSyscallHandler>() == 0);
  104. let raw_handlers_count = raw_handlers_size_byte / size_of::<RawSyscallHandler>();
  105. let raw_handlers = unsafe {
  106. core::slice::from_raw_parts(
  107. raw_handlers_addr as *const RawSyscallHandler,
  108. raw_handlers_count,
  109. )
  110. };
  111. let mut handlers = [const { None }; MAX_SYSCALL_NO];
  112. for &RawSyscallHandler { no, handler, name } in raw_handlers.iter() {
  113. handlers[no] = Some(SyscallHandler { handler, name })
  114. }
  115. handlers
  116. });
  117. pub fn syscall_handlers() -> &'static [Option<SyscallHandler>] {
  118. SYSCALL_HANDLERS.as_ref()
  119. }