| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- use super::task::ThreadAlloc;
- use crate::kernel::task::Thread;
- use alloc::boxed::Box;
- use core::{future::Future, marker::PhantomData, ops::Deref, pin::Pin};
- use eonix_mm::address::{Addr, VAddr};
- use eonix_sync::LazyLock;
- use posix_types::ctypes::PtrT;
- pub mod file_rw;
- pub mod mm;
- pub mod net;
- pub mod procops;
- pub mod sysinfo;
- const MAX_SYSCALL_NO: usize = 512;
- #[derive(Debug, Clone, Copy)]
- pub struct SyscallNoReturn;
- #[derive(Clone, Copy)]
- pub struct User<T>(VAddr, PhantomData<T>);
- #[derive(Clone, Copy)]
- pub struct UserMut<T>(VAddr, PhantomData<T>);
- #[repr(C)]
- pub(self) struct RawSyscallHandler {
- no: usize,
- handler: for<'thd, 'alloc> fn(
- &'thd Thread,
- ThreadAlloc<'alloc>,
- [usize; 6],
- ) -> Pin<
- Box<dyn Future<Output = Option<usize>> + Send + 'thd, ThreadAlloc<'alloc>>,
- >,
- name: &'static str,
- }
- pub struct SyscallHandler {
- pub handler: for<'thd, 'alloc> fn(
- &'thd Thread,
- ThreadAlloc<'alloc>,
- [usize; 6],
- ) -> Pin<
- Box<dyn Future<Output = Option<usize>> + Send + 'thd, ThreadAlloc<'alloc>>,
- >,
- pub name: &'static str,
- }
- pub trait FromSyscallArg: core::fmt::Debug {
- fn from_arg(value: usize) -> Self;
- }
- pub trait SyscallRetVal: core::fmt::Debug {
- fn into_retval(self) -> Option<usize>;
- }
- impl<T> SyscallRetVal for Result<T, u32>
- where
- T: SyscallRetVal,
- {
- fn into_retval(self) -> Option<usize> {
- match self {
- Ok(v) => v.into_retval(),
- Err(e) => Some((-(e as isize)) as usize),
- }
- }
- }
- impl SyscallRetVal for () {
- fn into_retval(self) -> Option<usize> {
- Some(0)
- }
- }
- impl SyscallRetVal for u32 {
- fn into_retval(self) -> Option<usize> {
- Some(self as usize)
- }
- }
- impl SyscallRetVal for usize {
- fn into_retval(self) -> Option<usize> {
- Some(self)
- }
- }
- impl SyscallRetVal for isize {
- fn into_retval(self) -> Option<usize> {
- Some(self as usize)
- }
- }
- impl SyscallRetVal for i32 {
- fn into_retval(self) -> Option<usize> {
- Some(self as usize)
- }
- }
- impl SyscallRetVal for SyscallNoReturn {
- fn into_retval(self) -> Option<usize> {
- None
- }
- }
- impl<T> SyscallRetVal for User<T> {
- fn into_retval(self) -> Option<usize> {
- Some(self.0.addr())
- }
- }
- impl<T> SyscallRetVal for UserMut<T> {
- fn into_retval(self) -> Option<usize> {
- Some(self.0.addr())
- }
- }
- #[cfg(not(target_arch = "x86_64"))]
- impl SyscallRetVal for u64 {
- fn into_retval(self) -> Option<usize> {
- Some(self as usize)
- }
- }
- #[cfg(not(target_arch = "x86_64"))]
- impl FromSyscallArg for u64 {
- fn from_arg(value: usize) -> u64 {
- value as u64
- }
- }
- impl FromSyscallArg for u32 {
- fn from_arg(value: usize) -> u32 {
- value as u32
- }
- }
- impl FromSyscallArg for i32 {
- fn from_arg(value: usize) -> i32 {
- value as i32
- }
- }
- impl FromSyscallArg for usize {
- fn from_arg(value: usize) -> usize {
- value
- }
- }
- impl FromSyscallArg for PtrT {
- fn from_arg(value: usize) -> Self {
- PtrT::new(value).expect("Invalid user pointer value")
- }
- }
- impl<T> FromSyscallArg for User<T> {
- fn from_arg(value: usize) -> User<T> {
- User(VAddr::from(value), PhantomData)
- }
- }
- impl<T> FromSyscallArg for UserMut<T> {
- fn from_arg(value: usize) -> UserMut<T> {
- UserMut(VAddr::from(value), PhantomData)
- }
- }
- impl<T> User<T> {
- pub const fn new(addr: VAddr) -> Self {
- Self(addr, PhantomData)
- }
- pub const fn with_addr(addr: usize) -> Self {
- Self::new(VAddr::from(addr))
- }
- pub const fn null() -> Self {
- Self(VAddr::NULL, PhantomData)
- }
- pub fn is_null(&self) -> bool {
- self.0.addr() == 0
- }
- pub const fn cast<U>(self) -> User<U> {
- User(self.0, PhantomData)
- }
- pub fn offset(self, off: isize) -> Self {
- Self(
- VAddr::from(
- self.0
- .addr()
- .checked_add_signed(off)
- .expect("offset overflow"),
- ),
- PhantomData,
- )
- }
- pub const unsafe fn as_mut(self) -> UserMut<T> {
- UserMut(self.0, PhantomData)
- }
- }
- impl<T> UserMut<T> {
- pub const fn new(addr: VAddr) -> Self {
- Self(addr, PhantomData)
- }
- pub const fn with_addr(addr: usize) -> Self {
- Self::new(VAddr::from(addr))
- }
- pub const fn null() -> Self {
- Self(VAddr::NULL, PhantomData)
- }
- pub fn is_null(&self) -> bool {
- self.0.addr() == 0
- }
- pub const fn cast<U>(self) -> UserMut<U> {
- UserMut(self.0, PhantomData)
- }
- pub fn offset(self, off: isize) -> Self {
- Self(
- VAddr::from(
- self.0
- .addr()
- .checked_add_signed(off)
- .expect("offset overflow"),
- ),
- PhantomData,
- )
- }
- pub const fn as_const(self) -> User<T> {
- User(self.0, PhantomData)
- }
- pub const fn vaddr(&self) -> VAddr {
- self.0
- }
- }
- impl<T> Deref for User<T> {
- type Target = VAddr;
- fn deref(&self) -> &Self::Target {
- &self.0
- }
- }
- impl<T> Deref for UserMut<T> {
- type Target = VAddr;
- fn deref(&self) -> &Self::Target {
- &self.0
- }
- }
- impl<T> core::fmt::Debug for User<T> {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- match self.0 {
- VAddr::NULL => write!(f, "User(NULL)"),
- _ => write!(f, "User({:#018x?})", self.0.addr()),
- }
- }
- }
- impl<T> core::fmt::Debug for UserMut<T> {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- match self.0 {
- VAddr::NULL => write!(f, "UserMut(NULL)"),
- _ => write!(f, "UserMut({:#018x?})", self.0.addr()),
- }
- }
- }
- static SYSCALL_HANDLERS: LazyLock<[Option<SyscallHandler>; MAX_SYSCALL_NO]> = LazyLock::new(|| {
- extern "C" {
- // SAFETY: `SYSCALL_HANDLERS` is defined in linker script.
- fn RAW_SYSCALL_HANDLERS();
- fn RAW_SYSCALL_HANDLERS_SIZE();
- }
- // DO NOT TOUCH THESE FUNCTIONS!!!
- // THEY ARE USED FOR KEEPING THE OBJECTS NOT STRIPPED BY THE LINKER!!!
- file_rw::keep_alive();
- mm::keep_alive();
- net::keep_alive();
- procops::keep_alive();
- sysinfo::keep_alive();
- let raw_handlers_addr = RAW_SYSCALL_HANDLERS as *const ();
- let raw_handlers_size_byte = RAW_SYSCALL_HANDLERS_SIZE as usize;
- assert!(raw_handlers_size_byte % size_of::<RawSyscallHandler>() == 0);
- let raw_handlers_count = raw_handlers_size_byte / size_of::<RawSyscallHandler>();
- let raw_handlers = unsafe {
- core::slice::from_raw_parts(
- raw_handlers_addr as *const RawSyscallHandler,
- raw_handlers_count,
- )
- };
- let mut handlers = [const { None }; MAX_SYSCALL_NO];
- for &RawSyscallHandler { no, handler, name } in raw_handlers.iter() {
- handlers[no] = Some(SyscallHandler { handler, name })
- }
- handlers
- });
- pub fn syscall_handlers() -> &'static [Option<SyscallHandler>] {
- SYSCALL_HANDLERS.as_ref()
- }
|