//! System call use alloc::{string::String, sync::Arc, vec::Vec}; use core::{slice, str, fmt}; use bitflags::bitflags; use rcore_memory::VMError; use rcore_fs::vfs::{FileType, FsError, INode, Metadata}; use crate::arch::interrupt::TrapFrame; use crate::sync::Condvar; use crate::process::*; use crate::thread; use crate::util; use crate::arch::cpu; use crate::arch::syscall; use self::fs::*; use self::mem::*; use self::proc::*; use self::time::*; use self::net::*; use self::misc::*; use self::custom::*; mod fs; mod mem; mod proc; mod time; mod net; mod misc; mod custom; /// System call dispatcher pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { let x86_64_id = syscall::translate(id); let cid = cpu::id(); let pid = { process().pid.clone() }; let tid = processor().tid(); if !pid.is_init() { // we trust pid 0 process debug!("{}:{}:{} syscall id {}->{} begin", cid, pid, tid, id, x86_64_id); } // use syscall numbers in Linux x86_64 // See https://filippo.io/linux-syscall-table/ // And https://fedora.juszkiewicz.com.pl/syscalls.html. let ret = match x86_64_id { // file 000 => sys_read(args[0], args[1] as *mut u8, args[2]), 001 => sys_write(args[0], args[1] as *const u8, args[2]), 002 => sys_open(args[0] as *const u8, args[1], args[2]), 003 => sys_close(args[0]), 004 => sys_stat(args[0] as *const u8, args[1] as *mut Stat), 005 => sys_fstat(args[0], args[1] as *mut Stat), 006 => sys_lstat(args[0] as *const u8, args[1] as *mut Stat), 007 => sys_poll(args[0] as *mut PollFd, args[1], args[2]), 008 => sys_lseek(args[0], args[1] as i64, args[2] as u8), 009 => sys_mmap(args[0], args[1], args[2], args[3], args[4] as i32, args[5]), 010 => sys_mprotect(args[0], args[1], args[2]), 011 => sys_munmap(args[0], args[1]), 017 => sys_pread(args[0], args[1] as *mut u8, args[2], args[3]), 018 => sys_pwrite(args[0], args[1] as *const u8, args[2], args[3]), 019 => sys_readv(args[0], args[1] as *const IoVec, args[2]), 020 => sys_writev(args[0], args[1] as *const IoVec, args[2]), 021 => sys_access(args[0] as *const u8, args[1]), 022 => sys_pipe(args[0] as *mut u32), 023 => sys_select(args[0], args[1] as *mut u32, args[2] as *mut u32, args[3] as *mut u32, args[4] as *const TimeVal), 024 => sys_yield(), 033 => sys_dup2(args[0], args[1]), // 034 => sys_pause(), 035 => sys_nanosleep(args[0] as *const TimeSpec), 039 => sys_getpid(), 041 => sys_socket(args[0], args[1], args[2]), 042 => sys_connect(args[0], args[1] as *const SockAddr, args[2]), 043 => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), 044 => sys_sendto(args[0], args[1] as *const u8, args[2], args[3], args[4] as *const SockAddr, args[5]), 045 => sys_recvfrom(args[0], args[1] as *mut u8, args[2], args[3], args[4] as *mut SockAddr, args[5] as *mut u32), // 046 => sys_sendmsg(), // 047 => sys_recvmsg(), 048 => sys_shutdown(args[0], args[1]), 049 => sys_bind(args[0], args[1] as *const SockAddr, args[2]), 050 => sys_listen(args[0], args[1]), 051 => sys_getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), 052 => sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), 054 => sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]), 055 => sys_getsockopt(args[0], args[1], args[2], args[3] as *mut u8, args[4] as *mut u32), 056 => sys_clone(args[0], args[1], args[2] as *mut u32, args[3] as *mut u32, args[4], tf), 057 => sys_fork(tf), // use fork for vfork 058 => sys_fork(tf), 059 => sys_exec(args[0] as *const u8, args[1] as *const *const u8, args[2] as *const *const u8, tf), 060 => sys_exit(args[0] as usize), 061 => sys_wait4(args[0] as isize, args[1] as *mut i32), // TODO: wait4 062 => sys_kill(args[0], args[1]), 063 => sys_uname(args[0] as *mut u8), // 072 => sys_fcntl(), 074 => sys_fsync(args[0]), 075 => sys_fdatasync(args[0]), 076 => sys_truncate(args[0] as *const u8, args[1]), 077 => sys_ftruncate(args[0], args[1]), 079 => sys_getcwd(args[0] as *mut u8, args[1]), 080 => sys_chdir(args[0] as *const u8), 082 => sys_rename(args[0] as *const u8, args[1] as *const u8), 083 => sys_mkdir(args[0] as *const u8, args[1]), 086 => sys_link(args[0] as *const u8, args[1] as *const u8), 087 => sys_unlink(args[0] as *const u8), 096 => sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8), // 097 => sys_getrlimit(), 098 => sys_getrusage(args[0], args[1] as *mut RUsage), 099 => sys_sysinfo(args[0] as *mut SysInfo), 110 => sys_getppid(), // 133 => sys_mknod(), 141 => sys_set_priority(args[0]), 158 => sys_arch_prctl(args[0] as i32, args[1], tf), // 160 => sys_setrlimit(), // 162 => sys_sync(), 169 => sys_reboot(args[0] as u32, args[1] as u32, args[2] as u32, args[3] as *const u8), 186 => sys_gettid(), 201 => sys_time(args[0] as *mut u64), 202 => sys_futex(args[0], args[1] as u32, args[2] as i32, args[3] as *const TimeSpec), 204 => sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32), 217 => sys_getdents64(args[0], args[1] as *mut LinuxDirent64, args[2]), 228 => sys_clock_gettime(args[0], args[1] as *mut TimeSpec), 231 => sys_exit_group(args[0]), 288 => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), // use accept for accept4 // custom temporary syscall 999 => sys_map_pci_device(args[0], args[1]), // 293 => sys_pipe(), // for musl: empty impl 012 => { warn!("sys_brk is unimplemented"); Ok(0) } 013 => { warn!("sys_sigaction is unimplemented"); Ok(0) } 014 => { warn!("sys_sigprocmask is unimplemented"); Ok(0) } 016 => { warn!("sys_ioctl is unimplemented"); Ok(0) } 028 => { warn!("sys_madvise is unimplemented"); Ok(0) } 037 => { warn!("sys_alarm is unimplemented"); Ok(0) } 038 => { warn!("sys_setitimer is unimplemented"); Ok(0) } 072 => { warn!("sys_fcntl is unimplemented"); Ok(0) } 089 => { warn!("sys_readlink is unimplemented"); Err(SysError::ENOENT) } 092 => { warn!("sys_chown is unimplemented"); Ok(0) } 095 => { warn!("sys_umask is unimplemented"); Ok(0o777) } 102 => { warn!("sys_getuid is unimplemented"); Ok(0) } 104 => { warn!("sys_getgid is unimplemented"); Ok(0) } 105 => { warn!("sys_setuid is unimplemented"); Ok(0) } 107 => { warn!("sys_geteuid is unimplemented"); Ok(0) } 108 => { warn!("sys_getegid is unimplemented"); Ok(0) } 112 => { warn!("sys_setsid is unimplemented"); Ok(0) } 131 => { warn!("sys_sigaltstack is unimplemented"); Ok(0) } 162 => { warn!("sys_sync is unimplemented"); Ok(0) } 213 => { warn!("sys_epoll_create is unimplemented"); Err(SysError::ENOSYS) } 218 => { warn!("sys_set_tid_address is unimplemented"); Ok(thread::current().id()) } 280 => { warn!("sys_utimensat is unimplemented"); Ok(0) } 291 => { warn!("sys_epoll_create1 is unimplemented"); Err(SysError::ENOSYS) } 302 => { warn!("sys_prlimit64 is unimplemented"); Ok(0) } _ => { error!("unknown syscall id: {}->{}, args: {:x?}", id, x86_64_id, args); crate::trap::error(tf); } }; if !pid.is_init() { // we trust pid 0 process debug!("{}:{}:{} syscall id {}->{} ret with {:x?}", cid, pid, tid, id, x86_64_id, ret); } match ret { Ok(code) => code as isize, Err(err) => -(err as isize), } } pub type SysResult = Result; #[allow(dead_code)] #[repr(isize)] #[derive(Debug)] pub enum SysError { EUNDEF = 0, EPERM = 1, ENOENT = 2, ESRCH = 3, EINTR = 4, EIO = 5, ENXIO = 6, E2BIG = 7, ENOEXEC = 8, EBADF = 9, ECHILD = 10, EAGAIN = 11, ENOMEM = 12, EACCES = 13, EFAULT = 14, ENOTBLK = 15, EBUSY = 16, EEXIST = 17, EXDEV = 18, ENODEV = 19, ENOTDIR = 20, EISDIR = 21, EINVAL = 22, ENFILE = 23, EMFILE = 24, ENOTTY = 25, ETXTBSY = 26, EFBIG = 27, ENOSPC = 28, ESPIPE = 29, EROFS = 30, EMLINK = 31, EPIPE = 32, EDOM = 33, ERANGE = 34, EDEADLK = 35, ENAMETOOLONG = 36, ENOLCK = 37, ENOSYS = 38, ENOTEMPTY = 39, ENOTSOCK = 80, ENOPROTOOPT = 92, EPFNOSUPPORT = 96, EAFNOSUPPORT = 97, ENOBUFS = 105, EISCONN = 106, ENOTCONN = 107, ECONNREFUSED = 111, } #[allow(non_snake_case)] impl fmt::Display for SysError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", match self { EPERM => "Operation not permitted", ENOENT => "No such file or directory", ESRCH => "No such process", EINTR => "Interrupted system call", EIO => "I/O error", ENXIO => "No such device or address", E2BIG => "Argument list too long", ENOEXEC => "Exec format error", EBADF => "Bad file number", ECHILD => "No child processes", EAGAIN => "Try again", ENOMEM => "Out of memory", EACCES => "Permission denied", EFAULT => "Bad address", ENOTBLK => "Block device required", EBUSY => "Device or resource busy", EEXIST => "File exists", EXDEV => "Cross-device link", ENODEV => "No such device", ENOTDIR => "Not a directory", EISDIR => "Is a directory", EINVAL => "Invalid argument", ENFILE => "File table overflow", EMFILE => "Too many open files", ENOTTY => "Not a typewriter", ETXTBSY => "Text file busy", EFBIG => "File too large", ENOSPC => "No space left on device", ESPIPE => "Illegal seek", EROFS => "Read-only file system", EMLINK => "Too many links", EPIPE => "Broken pipe", EDOM => "Math argument out of domain of func", ERANGE => "Math result not representable", EDEADLK => "Resource deadlock would occur", ENAMETOOLONG => "File name too long", ENOLCK => "No record locks available", ENOSYS => "Function not implemented", ENOTEMPTY => "Directory not empty", ENOTSOCK => "Socket operation on non-socket", ENOPROTOOPT => "Protocol not available", EPFNOSUPPORT => "Protocol family not supported", EAFNOSUPPORT => "Address family not supported by protocol", ENOBUFS => "No buffer space available", EISCONN => "Transport endpoint is already connected", ENOTCONN => "Transport endpoint is not connected", ECONNREFUSED => "Connection refused", _ => "Unknown error", }, ) } } impl From for SysError { fn from(_: VMError) -> Self { SysError::EFAULT } } const SPIN_WAIT_TIMES: usize = 100; pub fn spin_and_wait(condvars: &[&Condvar], mut action: impl FnMut() -> Option) -> SysResult { for i in 0..SPIN_WAIT_TIMES { if let Some(result) = action() { return result; } } loop { if let Some(result) = action() { return result; } Condvar::wait_any(&condvars); } }