| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use paste::paste; |
| use zerocopy::{AsBytes, FromBytes}; |
| |
| use crate::fs::socket::syscalls::*; |
| use crate::fs::syscalls::*; |
| use crate::fs::FdNumber; |
| use crate::mm::syscalls::*; |
| use crate::signals::syscalls::*; |
| use crate::syscalls::system::*; |
| use crate::syscalls::{CurrentTask, SyscallResult}; |
| use crate::task::syscalls::*; |
| use crate::types::*; |
| |
| macro_rules! syscall_match { |
| { |
| $current_task:ident; $syscall_number:ident; $args:ident; |
| $($call:ident [$num_args:tt],)* |
| } => { |
| paste! { |
| match $syscall_number as u32 { |
| $( |
| crate::types::[<__NR_ $call>] => { |
| match syscall_match!(@call $current_task; $args; [<sys_ $call>][$num_args]) { |
| Ok(x) => Ok(SyscallResult::from(x)), |
| Err(err) => Err(err), |
| } |
| }, |
| )* |
| _ => sys_unknown($current_task, $syscall_number), |
| } |
| } |
| }; |
| |
| (@call $current_task:ident; $args:ident; $func:ident [0]) => ($func($current_task)); |
| (@call $current_task:ident; $args:ident; $func:ident [1]) => ($func($current_task, $args.0.into_arg())); |
| (@call $current_task:ident; $args:ident; $func:ident [2]) => ($func($current_task, $args.0.into_arg(), $args.1.into_arg())); |
| (@call $current_task:ident; $args:ident; $func:ident [3]) => ($func($current_task, $args.0.into_arg(), $args.1.into_arg(), $args.2.into_arg())); |
| (@call $current_task:ident; $args:ident; $func:ident [4]) => ($func($current_task, $args.0.into_arg(), $args.1.into_arg(), $args.2.into_arg(), $args.3.into_arg())); |
| (@call $current_task:ident; $args:ident; $func:ident [5]) => ($func($current_task, $args.0.into_arg(), $args.1.into_arg(), $args.2.into_arg(), $args.3.into_arg(), $args.4.into_arg())); |
| (@call $current_task:ident; $args:ident; $func:ident [6]) => ($func($current_task, $args.0.into_arg(), $args.1.into_arg(), $args.2.into_arg(), $args.3.into_arg(), $args.4.into_arg(), $args.5.into_arg())); |
| } |
| |
| pub fn dispatch_syscall( |
| current_task: &mut CurrentTask, |
| syscall_number: u64, |
| args: (u64, u64, u64, u64, u64, u64), |
| ) -> Result<SyscallResult, Errno> { |
| syscall_match! { |
| current_task; syscall_number; args; |
| accept4[4], |
| accept[3], |
| access[2], |
| arch_prctl[2], |
| bind[3], |
| brk[1], |
| capget[2], |
| chdir[1], |
| chmod[2], |
| chroot[1], |
| clock_getres[2], |
| clock_gettime[2], |
| clone[5], |
| close[1], |
| connect[3], |
| dup2[2], |
| dup3[3], |
| dup[1], |
| epoll_create1[1], |
| epoll_create[1], |
| epoll_ctl[4], |
| epoll_pwait[5], |
| epoll_wait[4], |
| eventfd2[2], |
| eventfd[1], |
| execve[3], |
| exit[1], |
| exit_group[1], |
| faccessat[3], |
| fchdir[1], |
| fchmod[2], |
| fchmodat[3], |
| fchown[3], |
| fchownat[5], |
| fcntl[3], |
| fdatasync[1], |
| fgetxattr[4], |
| flistxattr[3], |
| flock[2], |
| fremovexattr[2], |
| fsetxattr[5], |
| fstat[2], |
| fstatfs[2], |
| fsync[1], |
| ftruncate[2], |
| futex[6], |
| getcwd[2], |
| getdents64[3], |
| getdents[3], |
| getegid[0], |
| geteuid[0], |
| getgid[0], |
| getgroups[2], |
| getitimer[2], |
| getpeername[3], |
| getpgid[1], |
| getpgrp[0], |
| getpid[0], |
| getppid[0], |
| getpriority[2], |
| getrandom[3], |
| getresgid[3], |
| getresuid[3], |
| getrlimit[2], |
| getrusage[2], |
| getsid[1], |
| getsockname[3], |
| getsockopt[5], |
| gettid[0], |
| gettimeofday[2], |
| getuid[0], |
| getxattr[4], |
| ioctl[3], |
| kill[2], |
| lgetxattr[4], |
| linkat[5], |
| listen[2], |
| listxattr[3], |
| llistxattr[3], |
| lremovexattr[2], |
| lseek[3], |
| lsetxattr[5], |
| lstat[2], |
| madvise[3], |
| membarrier[3], |
| memfd_create[2], |
| mkdir[2], |
| mkdirat[3], |
| mknodat[4], |
| mmap[6], |
| mount[5], |
| mprotect[3], |
| mremap[5], |
| msync[3], |
| munmap[2], |
| nanosleep[2], |
| newfstatat[4], |
| open[3], |
| openat[4], |
| pipe2[2], |
| pipe[1], |
| poll[3], |
| ppoll[4], |
| prctl[5], |
| pread64[4], |
| process_vm_readv[6], |
| pselect6[6], |
| prlimit64[4], |
| pwrite64[4], |
| read[3], |
| readlink[3], |
| readlinkat[4], |
| readv[3], |
| reboot[4], |
| recvfrom[6], |
| recvmmsg[5], |
| recvmsg[3], |
| removexattr[2], |
| rename[2], |
| renameat[4], |
| rmdir[1], |
| rt_sigaction[4], |
| rt_sigprocmask[4], |
| rt_sigreturn[0], |
| rt_sigsuspend[2], |
| rt_sigtimedwait[4], |
| rt_tgsigqueueinfo[4], |
| sched_getaffinity[3], |
| sched_getparam[2], |
| sched_getscheduler[1], |
| sched_setaffinity[3], |
| sendmmsg[4], |
| sendmsg[3], |
| sendto[6], |
| setgid[1], |
| setgroups[2], |
| setitimer[3], |
| setpgid[2], |
| setpriority[3], |
| setresgid[3], |
| setresuid[3], |
| setrlimit[2], |
| setsid[0], |
| setsockopt[5], |
| set_tid_address[1], |
| setuid[1], |
| setxattr[5], |
| shutdown[2], |
| sigaltstack[2], |
| signalfd4[4], |
| socket[3], |
| socketpair[4], |
| stat[2], |
| statfs[2], |
| symlinkat[3], |
| tgkill[3], |
| time[1], |
| timerfd_create[2], |
| timerfd_gettime[2], |
| timerfd_settime[4], |
| tkill[2], |
| truncate[2], |
| umask[1], |
| uname[1], |
| unlink[1], |
| unlinkat[3], |
| unshare[1], |
| vfork[0], |
| wait4[4], |
| waitid[4], |
| write[3], |
| writev[3], |
| } |
| } |
| |
| trait FromSyscallArg { |
| fn from_arg(arg: u64) -> Self; |
| } |
| impl FromSyscallArg for i32 { |
| fn from_arg(arg: u64) -> i32 { |
| arg as i32 |
| } |
| } |
| impl FromSyscallArg for u32 { |
| fn from_arg(arg: u64) -> u32 { |
| arg as u32 |
| } |
| } |
| impl FromSyscallArg for usize { |
| fn from_arg(arg: u64) -> usize { |
| arg as usize |
| } |
| } |
| impl FromSyscallArg for i64 { |
| fn from_arg(arg: u64) -> i64 { |
| arg as i64 |
| } |
| } |
| impl FromSyscallArg for u64 { |
| fn from_arg(arg: u64) -> u64 { |
| arg |
| } |
| } |
| impl FromSyscallArg for UserAddress { |
| fn from_arg(arg: u64) -> UserAddress { |
| UserAddress::from(arg) |
| } |
| } |
| |
| impl<T: AsBytes + FromBytes> FromSyscallArg for UserRef<T> { |
| fn from_arg(arg: u64) -> UserRef<T> { |
| UserRef::<T>::new(UserAddress::from(arg)) |
| } |
| } |
| |
| impl FromSyscallArg for UserCString { |
| fn from_arg(arg: u64) -> UserCString { |
| UserCString::new(UserAddress::from(arg)) |
| } |
| } |
| |
| impl FromSyscallArg for FdNumber { |
| fn from_arg(arg: u64) -> FdNumber { |
| FdNumber::from_raw(arg as i32) |
| } |
| } |
| |
| impl FromSyscallArg for FileMode { |
| fn from_arg(arg: u64) -> FileMode { |
| FileMode::from_bits(arg as u32) |
| } |
| } |
| |
| impl FromSyscallArg for DeviceType { |
| fn from_arg(arg: u64) -> DeviceType { |
| DeviceType::from_bits(arg) |
| } |
| } |
| |
| impl FromSyscallArg for UncheckedSignal { |
| fn from_arg(arg: u64) -> UncheckedSignal { |
| UncheckedSignal::new(arg) |
| } |
| } |
| trait IntoSyscallArg<T> { |
| fn into_arg(self) -> T; |
| } |
| impl<T> IntoSyscallArg<T> for u64 |
| where |
| T: FromSyscallArg, |
| { |
| fn into_arg(self) -> T { |
| T::from_arg(self) |
| } |
| } |