|
|
@ -11,7 +11,7 @@ use crate::arch::cpu;
|
|
|
|
use crate::arch::interrupt::TrapFrame;
|
|
|
|
use crate::arch::interrupt::TrapFrame;
|
|
|
|
use crate::arch::syscall::*;
|
|
|
|
use crate::arch::syscall::*;
|
|
|
|
use crate::process::*;
|
|
|
|
use crate::process::*;
|
|
|
|
use crate::sync::Condvar;
|
|
|
|
use crate::sync::{Condvar, SpinNoIrq, MutexGuard};
|
|
|
|
use crate::thread;
|
|
|
|
use crate::thread;
|
|
|
|
use crate::util;
|
|
|
|
use crate::util;
|
|
|
|
|
|
|
|
|
|
|
@ -40,330 +40,348 @@ lazy_static! {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// System call dispatcher
|
|
|
|
/// System call dispatcher
|
|
|
|
// This #[deny(unreachable_patterns)] checks if each match arm is defined
|
|
|
|
|
|
|
|
// See discussion in https://github.com/oscourse-tsinghua/rcore_plus/commit/17e644e54e494835f1a49b34b80c2c4f15ed0dbe.
|
|
|
|
|
|
|
|
#[deny(unreachable_patterns)]
|
|
|
|
|
|
|
|
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
|
|
|
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
|
|
|
#[cfg(feature = "profile")]
|
|
|
|
let thread = unsafe { current_thread() };
|
|
|
|
let begin_time = unsafe { core::arch::x86_64::_rdtsc() };
|
|
|
|
let mut syscall = Syscall { thread, tf };
|
|
|
|
let cid = cpu::id();
|
|
|
|
syscall.syscall(id, args)
|
|
|
|
let pid = process().pid.clone();
|
|
|
|
}
|
|
|
|
let tid = processor().tid();
|
|
|
|
|
|
|
|
if !pid.is_init() {
|
|
|
|
/// All context needed for syscall
|
|
|
|
// we trust pid 0 process
|
|
|
|
struct Syscall<'a> {
|
|
|
|
debug!("{}:{}:{} syscall id {} begin", cid, pid, tid, id);
|
|
|
|
thread: &'a mut Thread,
|
|
|
|
|
|
|
|
tf: &'a mut TrapFrame,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Syscall<'_> {
|
|
|
|
|
|
|
|
/// Get current process
|
|
|
|
|
|
|
|
pub fn process(&self) -> MutexGuard<'_, Process, SpinNoIrq> {
|
|
|
|
|
|
|
|
self.thread.proc.lock()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// use platform-specific syscal numbers
|
|
|
|
/// System call dispatcher
|
|
|
|
// See https://filippo.io/linux-syscall-table/
|
|
|
|
// This #[deny(unreachable_patterns)] checks if each match arm is defined
|
|
|
|
// And https://fedora.juszkiewicz.com.pl/syscalls.html.
|
|
|
|
// See discussion in https://github.com/oscourse-tsinghua/rcore_plus/commit/17e644e54e494835f1a49b34b80c2c4f15ed0dbe.
|
|
|
|
let ret = match id {
|
|
|
|
#[deny(unreachable_patterns)]
|
|
|
|
// file
|
|
|
|
fn syscall(&mut self, id: usize, args: [usize; 6]) -> isize {
|
|
|
|
SYS_READ => sys_read(args[0], args[1] as *mut u8, args[2]),
|
|
|
|
#[cfg(feature = "profile")]
|
|
|
|
SYS_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
|
|
|
|
let begin_time = unsafe { core::arch::x86_64::_rdtsc() };
|
|
|
|
SYS_OPENAT => sys_openat(args[0], args[1] as *const u8, args[2], args[3]),
|
|
|
|
let cid = cpu::id();
|
|
|
|
SYS_CLOSE => sys_close(args[0]),
|
|
|
|
let pid = self.process().pid.clone();
|
|
|
|
SYS_FSTAT => sys_fstat(args[0], args[1] as *mut Stat),
|
|
|
|
let tid = processor().tid();
|
|
|
|
SYS_NEWFSTATAT => sys_fstatat(args[0], args[1] as *const u8, args[2] as *mut Stat, args[3]),
|
|
|
|
if !pid.is_init() {
|
|
|
|
SYS_LSEEK => sys_lseek(args[0], args[1] as i64, args[2] as u8),
|
|
|
|
// we trust pid 0 process
|
|
|
|
SYS_IOCTL => sys_ioctl(args[0], args[1], args[2], args[3], args[4]),
|
|
|
|
debug!("{}:{}:{} syscall id {} begin", cid, pid, tid, id);
|
|
|
|
SYS_PREAD64 => sys_pread(args[0], args[1] as *mut u8, args[2], args[3]),
|
|
|
|
|
|
|
|
SYS_PWRITE64 => sys_pwrite(args[0], args[1] as *const u8, args[2], args[3]),
|
|
|
|
|
|
|
|
SYS_READV => sys_readv(args[0], args[1] as *const IoVec, args[2]),
|
|
|
|
|
|
|
|
SYS_WRITEV => sys_writev(args[0], args[1] as *const IoVec, args[2]),
|
|
|
|
|
|
|
|
SYS_SENDFILE => sys_sendfile(args[0], args[1], args[2] as *mut usize, args[3]),
|
|
|
|
|
|
|
|
SYS_FCNTL => unimplemented("fcntl", Ok(0)),
|
|
|
|
|
|
|
|
SYS_FLOCK => unimplemented("flock", Ok(0)),
|
|
|
|
|
|
|
|
SYS_FSYNC => sys_fsync(args[0]),
|
|
|
|
|
|
|
|
SYS_FDATASYNC => sys_fdatasync(args[0]),
|
|
|
|
|
|
|
|
SYS_TRUNCATE => sys_truncate(args[0] as *const u8, args[1]),
|
|
|
|
|
|
|
|
SYS_FTRUNCATE => sys_ftruncate(args[0], args[1]),
|
|
|
|
|
|
|
|
SYS_GETDENTS64 => sys_getdents64(args[0], args[1] as *mut LinuxDirent64, args[2]),
|
|
|
|
|
|
|
|
SYS_GETCWD => sys_getcwd(args[0] as *mut u8, args[1]),
|
|
|
|
|
|
|
|
SYS_CHDIR => sys_chdir(args[0] as *const u8),
|
|
|
|
|
|
|
|
SYS_RENAMEAT => sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8),
|
|
|
|
|
|
|
|
SYS_MKDIRAT => sys_mkdirat(args[0], args[1] as *const u8, args[2]),
|
|
|
|
|
|
|
|
SYS_LINKAT => sys_linkat(
|
|
|
|
|
|
|
|
args[0],
|
|
|
|
|
|
|
|
args[1] as *const u8,
|
|
|
|
|
|
|
|
args[2],
|
|
|
|
|
|
|
|
args[3] as *const u8,
|
|
|
|
|
|
|
|
args[4],
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
SYS_UNLINKAT => sys_unlinkat(args[0], args[1] as *const u8, args[2]),
|
|
|
|
|
|
|
|
SYS_SYMLINKAT => unimplemented("symlinkat", Err(SysError::EACCES)),
|
|
|
|
|
|
|
|
SYS_READLINKAT => {
|
|
|
|
|
|
|
|
sys_readlinkat(args[0], args[1] as *const u8, args[2] as *mut u8, args[3])
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SYS_FCHMOD => unimplemented("fchmod", Ok(0)),
|
|
|
|
|
|
|
|
SYS_FCHMODAT => unimplemented("fchmodat", Ok(0)),
|
|
|
|
// use platform-specific syscal numbers
|
|
|
|
SYS_FCHOWN => unimplemented("fchown", Ok(0)),
|
|
|
|
// See https://filippo.io/linux-syscall-table/
|
|
|
|
SYS_FCHOWNAT => unimplemented("fchownat", Ok(0)),
|
|
|
|
// And https://fedora.juszkiewicz.com.pl/syscalls.html.
|
|
|
|
SYS_FACCESSAT => sys_faccessat(args[0], args[1] as *const u8, args[2], args[3]),
|
|
|
|
let ret = match id {
|
|
|
|
SYS_DUP3 => sys_dup2(args[0], args[1]), // TODO: handle `flags`
|
|
|
|
// file
|
|
|
|
SYS_PIPE2 => sys_pipe(args[0] as *mut u32), // TODO: handle `flags`
|
|
|
|
SYS_READ => self.sys_read(args[0], args[1] as *mut u8, args[2]),
|
|
|
|
SYS_UTIMENSAT => unimplemented("utimensat", Ok(0)),
|
|
|
|
SYS_WRITE => self.sys_write(args[0], args[1] as *const u8, args[2]),
|
|
|
|
|
|
|
|
SYS_OPENAT => self.sys_openat(args[0], args[1] as *const u8, args[2], args[3]),
|
|
|
|
// io multiplexing
|
|
|
|
SYS_CLOSE => self.sys_close(args[0]),
|
|
|
|
SYS_PPOLL => sys_ppoll(args[0] as *mut PollFd, args[1], args[2] as *const TimeSpec), // ignore sigmask
|
|
|
|
SYS_FSTAT => self.sys_fstat(args[0], args[1] as *mut Stat),
|
|
|
|
SYS_EPOLL_CREATE1 => unimplemented("epoll_create1", Err(SysError::ENOSYS)),
|
|
|
|
SYS_NEWFSTATAT => self.sys_fstatat(args[0], args[1] as *const u8, args[2] as *mut Stat, args[3]),
|
|
|
|
|
|
|
|
SYS_LSEEK => self.sys_lseek(args[0], args[1] as i64, args[2] as u8),
|
|
|
|
// file system
|
|
|
|
SYS_IOCTL => self.sys_ioctl(args[0], args[1], args[2], args[3], args[4]),
|
|
|
|
SYS_STATFS => unimplemented("statfs", Err(SysError::EACCES)),
|
|
|
|
SYS_PREAD64 => self.sys_pread(args[0], args[1] as *mut u8, args[2], args[3]),
|
|
|
|
SYS_FSTATFS => unimplemented("fstatfs", Err(SysError::EACCES)),
|
|
|
|
SYS_PWRITE64 => self.sys_pwrite(args[0], args[1] as *const u8, args[2], args[3]),
|
|
|
|
SYS_SYNC => sys_sync(),
|
|
|
|
SYS_READV => self.sys_readv(args[0], args[1] as *const IoVec, args[2]),
|
|
|
|
SYS_MOUNT => unimplemented("mount", Err(SysError::EACCES)),
|
|
|
|
SYS_WRITEV => self.sys_writev(args[0], args[1] as *const IoVec, args[2]),
|
|
|
|
SYS_UMOUNT2 => unimplemented("umount2", Err(SysError::EACCES)),
|
|
|
|
SYS_SENDFILE => self.sys_sendfile(args[0], args[1], args[2] as *mut usize, args[3]),
|
|
|
|
|
|
|
|
SYS_FCNTL => self.unimplemented("fcntl", Ok(0)),
|
|
|
|
// memory
|
|
|
|
SYS_FLOCK => self.unimplemented("flock", Ok(0)),
|
|
|
|
SYS_BRK => unimplemented("brk", Err(SysError::ENOMEM)),
|
|
|
|
SYS_FSYNC => self.sys_fsync(args[0]),
|
|
|
|
SYS_MMAP => sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5]),
|
|
|
|
SYS_FDATASYNC => self.sys_fdatasync(args[0]),
|
|
|
|
SYS_MPROTECT => sys_mprotect(args[0], args[1], args[2]),
|
|
|
|
SYS_TRUNCATE => self.sys_truncate(args[0] as *const u8, args[1]),
|
|
|
|
SYS_MUNMAP => sys_munmap(args[0], args[1]),
|
|
|
|
SYS_FTRUNCATE => self.sys_ftruncate(args[0], args[1]),
|
|
|
|
SYS_MADVISE => unimplemented("madvise", Ok(0)),
|
|
|
|
SYS_GETDENTS64 => self.sys_getdents64(args[0], args[1] as *mut LinuxDirent64, args[2]),
|
|
|
|
|
|
|
|
SYS_GETCWD => self.sys_getcwd(args[0] as *mut u8, args[1]),
|
|
|
|
// signal
|
|
|
|
SYS_CHDIR => self.sys_chdir(args[0] as *const u8),
|
|
|
|
SYS_RT_SIGACTION => unimplemented("sigaction", Ok(0)),
|
|
|
|
SYS_RENAMEAT => self.sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8),
|
|
|
|
SYS_RT_SIGPROCMASK => unimplemented("sigprocmask", Ok(0)),
|
|
|
|
SYS_MKDIRAT => self.sys_mkdirat(args[0], args[1] as *const u8, args[2]),
|
|
|
|
SYS_SIGALTSTACK => unimplemented("sigaltstack", Ok(0)),
|
|
|
|
SYS_LINKAT => self.sys_linkat(
|
|
|
|
SYS_KILL => sys_kill(args[0], args[1]),
|
|
|
|
args[0],
|
|
|
|
|
|
|
|
args[1] as *const u8,
|
|
|
|
// schedule
|
|
|
|
args[2],
|
|
|
|
SYS_SCHED_YIELD => sys_yield(),
|
|
|
|
args[3] as *const u8,
|
|
|
|
SYS_SCHED_GETAFFINITY => sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32),
|
|
|
|
args[4],
|
|
|
|
|
|
|
|
),
|
|
|
|
// socket
|
|
|
|
SYS_UNLINKAT => self.sys_unlinkat(args[0], args[1] as *const u8, args[2]),
|
|
|
|
SYS_SOCKET => sys_socket(args[0], args[1], args[2]),
|
|
|
|
SYS_SYMLINKAT => self.unimplemented("symlinkat", Err(SysError::EACCES)),
|
|
|
|
SYS_CONNECT => sys_connect(args[0], args[1] as *const SockAddr, args[2]),
|
|
|
|
SYS_READLINKAT => {
|
|
|
|
SYS_ACCEPT => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
|
|
|
|
self.sys_readlinkat(args[0], args[1] as *const u8, args[2] as *mut u8, args[3])
|
|
|
|
SYS_ACCEPT4 => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), // use accept for accept4
|
|
|
|
}
|
|
|
|
SYS_SENDTO => sys_sendto(
|
|
|
|
SYS_FCHMOD => self.unimplemented("fchmod", Ok(0)),
|
|
|
|
args[0],
|
|
|
|
SYS_FCHMODAT => self.unimplemented("fchmodat", Ok(0)),
|
|
|
|
args[1] as *const u8,
|
|
|
|
SYS_FCHOWN => self.unimplemented("fchown", Ok(0)),
|
|
|
|
args[2],
|
|
|
|
SYS_FCHOWNAT => self.unimplemented("fchownat", Ok(0)),
|
|
|
|
args[3],
|
|
|
|
SYS_FACCESSAT => self.sys_faccessat(args[0], args[1] as *const u8, args[2], args[3]),
|
|
|
|
args[4] as *const SockAddr,
|
|
|
|
SYS_DUP3 => self.sys_dup2(args[0], args[1]), // TODO: handle `flags`
|
|
|
|
args[5],
|
|
|
|
SYS_PIPE2 => self.sys_pipe(args[0] as *mut u32), // TODO: handle `flags`
|
|
|
|
),
|
|
|
|
SYS_UTIMENSAT => self.unimplemented("utimensat", Ok(0)),
|
|
|
|
SYS_RECVFROM => sys_recvfrom(
|
|
|
|
|
|
|
|
args[0],
|
|
|
|
// io multiplexing
|
|
|
|
args[1] as *mut u8,
|
|
|
|
SYS_PPOLL => self.sys_ppoll(args[0] as *mut PollFd, args[1], args[2] as *const TimeSpec), // ignore sigmask
|
|
|
|
args[2],
|
|
|
|
SYS_EPOLL_CREATE1 => self.unimplemented("epoll_create1", Err(SysError::ENOSYS)),
|
|
|
|
args[3],
|
|
|
|
|
|
|
|
args[4] as *mut SockAddr,
|
|
|
|
// file system
|
|
|
|
args[5] as *mut u32,
|
|
|
|
SYS_STATFS => self.unimplemented("statfs", Err(SysError::EACCES)),
|
|
|
|
),
|
|
|
|
SYS_FSTATFS => self.unimplemented("fstatfs", Err(SysError::EACCES)),
|
|
|
|
// SYS_SENDMSG => sys_sendmsg(),
|
|
|
|
SYS_SYNC => self.sys_sync(),
|
|
|
|
SYS_RECVMSG => sys_recvmsg(args[0], args[1] as *mut MsgHdr, args[2]),
|
|
|
|
SYS_MOUNT => self.unimplemented("mount", Err(SysError::EACCES)),
|
|
|
|
SYS_SHUTDOWN => sys_shutdown(args[0], args[1]),
|
|
|
|
SYS_UMOUNT2 => self.unimplemented("umount2", Err(SysError::EACCES)),
|
|
|
|
SYS_BIND => sys_bind(args[0], args[1] as *const SockAddr, args[2]),
|
|
|
|
|
|
|
|
SYS_LISTEN => sys_listen(args[0], args[1]),
|
|
|
|
// memory
|
|
|
|
SYS_GETSOCKNAME => sys_getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
|
|
|
|
SYS_BRK => self.unimplemented("brk", Err(SysError::ENOMEM)),
|
|
|
|
SYS_GETPEERNAME => sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
|
|
|
|
SYS_MMAP => self.sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5]),
|
|
|
|
SYS_SETSOCKOPT => sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]),
|
|
|
|
SYS_MPROTECT => self.sys_mprotect(args[0], args[1], args[2]),
|
|
|
|
SYS_GETSOCKOPT => sys_getsockopt(
|
|
|
|
SYS_MUNMAP => self.sys_munmap(args[0], args[1]),
|
|
|
|
args[0],
|
|
|
|
SYS_MADVISE => self.unimplemented("madvise", Ok(0)),
|
|
|
|
args[1],
|
|
|
|
|
|
|
|
args[2],
|
|
|
|
// signal
|
|
|
|
args[3] as *mut u8,
|
|
|
|
SYS_RT_SIGACTION => self.unimplemented("sigaction", Ok(0)),
|
|
|
|
args[4] as *mut u32,
|
|
|
|
SYS_RT_SIGPROCMASK => self.unimplemented("sigprocmask", Ok(0)),
|
|
|
|
),
|
|
|
|
SYS_SIGALTSTACK => self.unimplemented("sigaltstack", Ok(0)),
|
|
|
|
|
|
|
|
SYS_KILL => self.sys_kill(args[0], args[1]),
|
|
|
|
// process
|
|
|
|
|
|
|
|
SYS_CLONE => sys_clone(
|
|
|
|
// schedule
|
|
|
|
args[0],
|
|
|
|
SYS_SCHED_YIELD => self.sys_yield(),
|
|
|
|
args[1],
|
|
|
|
SYS_SCHED_GETAFFINITY => self.sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32),
|
|
|
|
args[2] as *mut u32,
|
|
|
|
|
|
|
|
args[3] as *mut u32,
|
|
|
|
// socket
|
|
|
|
args[4],
|
|
|
|
SYS_SOCKET => self.sys_socket(args[0], args[1], args[2]),
|
|
|
|
tf,
|
|
|
|
SYS_CONNECT => self.sys_connect(args[0], args[1] as *const SockAddr, args[2]),
|
|
|
|
),
|
|
|
|
SYS_ACCEPT => self.sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
|
|
|
|
SYS_EXECVE => sys_exec(
|
|
|
|
SYS_ACCEPT4 => self.sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), // use accept for accept4
|
|
|
|
args[0] as *const u8,
|
|
|
|
SYS_SENDTO => self.sys_sendto(
|
|
|
|
args[1] as *const *const u8,
|
|
|
|
args[0],
|
|
|
|
args[2] as *const *const u8,
|
|
|
|
args[1] as *const u8,
|
|
|
|
tf,
|
|
|
|
args[2],
|
|
|
|
),
|
|
|
|
args[3],
|
|
|
|
SYS_EXIT => sys_exit(args[0] as usize),
|
|
|
|
args[4] as *const SockAddr,
|
|
|
|
SYS_EXIT_GROUP => sys_exit_group(args[0]),
|
|
|
|
args[5],
|
|
|
|
SYS_WAIT4 => sys_wait4(args[0] as isize, args[1] as *mut i32), // TODO: wait4
|
|
|
|
),
|
|
|
|
SYS_SET_TID_ADDRESS => sys_set_tid_address(args[0] as *mut u32),
|
|
|
|
SYS_RECVFROM => self.sys_recvfrom(
|
|
|
|
SYS_FUTEX => sys_futex(
|
|
|
|
args[0],
|
|
|
|
args[0],
|
|
|
|
args[1] as *mut u8,
|
|
|
|
args[1] as u32,
|
|
|
|
args[2],
|
|
|
|
args[2] as i32,
|
|
|
|
args[3],
|
|
|
|
args[3] as *const TimeSpec,
|
|
|
|
args[4] as *mut SockAddr,
|
|
|
|
),
|
|
|
|
args[5] as *mut u32,
|
|
|
|
|
|
|
|
),
|
|
|
|
// time
|
|
|
|
// SYS_SENDMSG => self.sys_sendmsg(),
|
|
|
|
SYS_NANOSLEEP => sys_nanosleep(args[0] as *const TimeSpec),
|
|
|
|
SYS_RECVMSG => self.sys_recvmsg(args[0], args[1] as *mut MsgHdr, args[2]),
|
|
|
|
SYS_SETITIMER => unimplemented("setitimer", Ok(0)),
|
|
|
|
SYS_SHUTDOWN => self.sys_shutdown(args[0], args[1]),
|
|
|
|
SYS_GETTIMEOFDAY => sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8),
|
|
|
|
SYS_BIND => self.sys_bind(args[0], args[1] as *const SockAddr, args[2]),
|
|
|
|
SYS_CLOCK_GETTIME => sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
|
|
|
|
SYS_LISTEN => self.sys_listen(args[0], args[1]),
|
|
|
|
|
|
|
|
SYS_GETSOCKNAME => self.sys_getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
|
|
|
|
// system
|
|
|
|
SYS_GETPEERNAME => self.sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
|
|
|
|
SYS_GETPID => sys_getpid(),
|
|
|
|
SYS_SETSOCKOPT => self.sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]),
|
|
|
|
SYS_GETTID => sys_gettid(),
|
|
|
|
SYS_GETSOCKOPT => self.sys_getsockopt(
|
|
|
|
SYS_UNAME => sys_uname(args[0] as *mut u8),
|
|
|
|
args[0],
|
|
|
|
SYS_UMASK => unimplemented("umask", Ok(0o777)),
|
|
|
|
args[1],
|
|
|
|
// SYS_GETRLIMIT => sys_getrlimit(),
|
|
|
|
args[2],
|
|
|
|
// SYS_SETRLIMIT => sys_setrlimit(),
|
|
|
|
args[3] as *mut u8,
|
|
|
|
SYS_GETRUSAGE => sys_getrusage(args[0], args[1] as *mut RUsage),
|
|
|
|
args[4] as *mut u32,
|
|
|
|
SYS_SYSINFO => sys_sysinfo(args[0] as *mut SysInfo),
|
|
|
|
),
|
|
|
|
SYS_TIMES => sys_times(args[0] as *mut Tms),
|
|
|
|
|
|
|
|
SYS_GETUID => unimplemented("getuid", Ok(0)),
|
|
|
|
// process
|
|
|
|
SYS_GETGID => unimplemented("getgid", Ok(0)),
|
|
|
|
SYS_CLONE => self.sys_clone(
|
|
|
|
SYS_SETUID => unimplemented("setuid", Ok(0)),
|
|
|
|
args[0],
|
|
|
|
SYS_GETEUID => unimplemented("geteuid", Ok(0)),
|
|
|
|
args[1],
|
|
|
|
SYS_GETEGID => unimplemented("getegid", Ok(0)),
|
|
|
|
args[2] as *mut u32,
|
|
|
|
SYS_SETPGID => unimplemented("setpgid", Ok(0)),
|
|
|
|
args[3] as *mut u32,
|
|
|
|
SYS_GETPPID => sys_getppid(),
|
|
|
|
args[4],
|
|
|
|
SYS_SETSID => unimplemented("setsid", Ok(0)),
|
|
|
|
),
|
|
|
|
SYS_GETPGID => unimplemented("getpgid", Ok(0)),
|
|
|
|
SYS_EXECVE => self.sys_exec(
|
|
|
|
SYS_GETGROUPS => unimplemented("getgroups", Ok(0)),
|
|
|
|
args[0] as *const u8,
|
|
|
|
SYS_SETGROUPS => unimplemented("setgroups", Ok(0)),
|
|
|
|
args[1] as *const *const u8,
|
|
|
|
SYS_SETPRIORITY => sys_set_priority(args[0]),
|
|
|
|
args[2] as *const *const u8,
|
|
|
|
SYS_PRCTL => unimplemented("prctl", Ok(0)),
|
|
|
|
),
|
|
|
|
SYS_PRLIMIT64 => sys_prlimit64(
|
|
|
|
SYS_EXIT => self.sys_exit(args[0] as usize),
|
|
|
|
args[0],
|
|
|
|
SYS_EXIT_GROUP => self.sys_exit_group(args[0]),
|
|
|
|
args[1],
|
|
|
|
SYS_WAIT4 => self.sys_wait4(args[0] as isize, args[1] as *mut i32), // TODO: wait4
|
|
|
|
args[2] as *const RLimit,
|
|
|
|
SYS_SET_TID_ADDRESS => self.sys_set_tid_address(args[0] as *mut u32),
|
|
|
|
args[3] as *mut RLimit,
|
|
|
|
SYS_FUTEX => self.sys_futex(
|
|
|
|
),
|
|
|
|
args[0],
|
|
|
|
SYS_REBOOT => sys_reboot(
|
|
|
|
args[1] as u32,
|
|
|
|
args[0] as u32,
|
|
|
|
args[2] as i32,
|
|
|
|
args[1] as u32,
|
|
|
|
args[3] as *const TimeSpec,
|
|
|
|
args[2] as u32,
|
|
|
|
),
|
|
|
|
args[3] as *const u8,
|
|
|
|
|
|
|
|
),
|
|
|
|
// time
|
|
|
|
|
|
|
|
SYS_NANOSLEEP => self.sys_nanosleep(args[0] as *const TimeSpec),
|
|
|
|
// custom
|
|
|
|
SYS_SETITIMER => self.unimplemented("setitimer", Ok(0)),
|
|
|
|
SYS_MAP_PCI_DEVICE => sys_map_pci_device(args[0], args[1]),
|
|
|
|
SYS_GETTIMEOFDAY => self.sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8),
|
|
|
|
SYS_GET_PADDR => sys_get_paddr(args[0] as *const u64, args[1] as *mut u64, args[2]),
|
|
|
|
SYS_CLOCK_GETTIME => self.sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
|
|
|
|
//SYS_GETRANDOM => unimplemented("getrandom", Err(SysError::EINVAL)),
|
|
|
|
|
|
|
|
SYS_GETRANDOM => sys_getrandom(args[0] as *mut u8, args[1] as usize, args[2] as u32),
|
|
|
|
// system
|
|
|
|
SYS_TKILL => unimplemented("tkill", Ok(0)),
|
|
|
|
SYS_GETPID => self.sys_getpid(),
|
|
|
|
_ => {
|
|
|
|
SYS_GETTID => self.sys_gettid(),
|
|
|
|
let ret = match () {
|
|
|
|
SYS_UNAME => self.sys_uname(args[0] as *mut u8),
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
SYS_UMASK => self.unimplemented("umask", Ok(0o777)),
|
|
|
|
() => x86_64_syscall(id, args, tf),
|
|
|
|
// SYS_GETRLIMIT => self.sys_getrlimit(),
|
|
|
|
#[cfg(target_arch = "mips")]
|
|
|
|
// SYS_SETRLIMIT => self.sys_setrlimit(),
|
|
|
|
() => mips_syscall(id, args, tf),
|
|
|
|
SYS_GETRUSAGE => self.sys_getrusage(args[0], args[1] as *mut RUsage),
|
|
|
|
#[cfg(all(not(target_arch = "x86_64"), not(target_arch = "mips")))]
|
|
|
|
SYS_SYSINFO => self.sys_sysinfo(args[0] as *mut SysInfo),
|
|
|
|
() => None,
|
|
|
|
SYS_TIMES => self.sys_times(args[0] as *mut Tms),
|
|
|
|
};
|
|
|
|
SYS_GETUID => self.unimplemented("getuid", Ok(0)),
|
|
|
|
if let Some(ret) = ret {
|
|
|
|
SYS_GETGID => self.unimplemented("getgid", Ok(0)),
|
|
|
|
ret
|
|
|
|
SYS_SETUID => self.unimplemented("setuid", Ok(0)),
|
|
|
|
} else {
|
|
|
|
SYS_GETEUID => self.unimplemented("geteuid", Ok(0)),
|
|
|
|
error!("unknown syscall id: {}, args: {:x?}", id, args);
|
|
|
|
SYS_GETEGID => self.unimplemented("getegid", Ok(0)),
|
|
|
|
crate::trap::error(tf);
|
|
|
|
SYS_SETPGID => self.unimplemented("setpgid", Ok(0)),
|
|
|
|
|
|
|
|
SYS_GETPPID => self.sys_getppid(),
|
|
|
|
|
|
|
|
SYS_SETSID => self.unimplemented("setsid", Ok(0)),
|
|
|
|
|
|
|
|
SYS_GETPGID => self.unimplemented("getpgid", Ok(0)),
|
|
|
|
|
|
|
|
SYS_GETGROUPS => self.unimplemented("getgroups", Ok(0)),
|
|
|
|
|
|
|
|
SYS_SETGROUPS => self.unimplemented("setgroups", Ok(0)),
|
|
|
|
|
|
|
|
SYS_SETPRIORITY => self.sys_set_priority(args[0]),
|
|
|
|
|
|
|
|
SYS_PRCTL => self.unimplemented("prctl", Ok(0)),
|
|
|
|
|
|
|
|
SYS_PRLIMIT64 => self.sys_prlimit64(
|
|
|
|
|
|
|
|
args[0],
|
|
|
|
|
|
|
|
args[1],
|
|
|
|
|
|
|
|
args[2] as *const RLimit,
|
|
|
|
|
|
|
|
args[3] as *mut RLimit,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
SYS_REBOOT => self.sys_reboot(
|
|
|
|
|
|
|
|
args[0] as u32,
|
|
|
|
|
|
|
|
args[1] as u32,
|
|
|
|
|
|
|
|
args[2] as u32,
|
|
|
|
|
|
|
|
args[3] as *const u8,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// custom
|
|
|
|
|
|
|
|
SYS_MAP_PCI_DEVICE => self.sys_map_pci_device(args[0], args[1]),
|
|
|
|
|
|
|
|
SYS_GET_PADDR => self.sys_get_paddr(args[0] as *const u64, args[1] as *mut u64, args[2]),
|
|
|
|
|
|
|
|
//SYS_GETRANDOM => self.unimplemented("getrandom", Err(SysError::EINVAL)),
|
|
|
|
|
|
|
|
SYS_GETRANDOM => self.sys_getrandom(args[0] as *mut u8, args[1] as usize, args[2] as u32),
|
|
|
|
|
|
|
|
SYS_TKILL => self.unimplemented("tkill", Ok(0)),
|
|
|
|
|
|
|
|
_ => {
|
|
|
|
|
|
|
|
let ret = match () {
|
|
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
|
|
|
|
() => self.x86_64_syscall(id, args),
|
|
|
|
|
|
|
|
#[cfg(target_arch = "mips")]
|
|
|
|
|
|
|
|
() => self.mips_syscall(id, args),
|
|
|
|
|
|
|
|
#[cfg(all(not(target_arch = "x86_64"), not(target_arch = "mips")))]
|
|
|
|
|
|
|
|
() => None,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(ret) = ret {
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
error!("unknown syscall id: {}, args: {:x?}", id, args);
|
|
|
|
|
|
|
|
crate::trap::error(self.tf);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
if !pid.is_init() {
|
|
|
|
|
|
|
|
// we trust pid 0 process
|
|
|
|
|
|
|
|
info!("=> {:x?}", ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#[cfg(feature = "profile")]
|
|
|
|
if !pid.is_init() {
|
|
|
|
{
|
|
|
|
// we trust pid 0 process
|
|
|
|
let end_time = unsafe { core::arch::x86_64::_rdtsc() };
|
|
|
|
info!("=> {:x?}", ret);
|
|
|
|
*SYSCALL_TIMING.lock().entry(id).or_insert(0) += end_time - begin_time;
|
|
|
|
}
|
|
|
|
if end_time % 1000 == 0 {
|
|
|
|
#[cfg(feature = "profile")]
|
|
|
|
let timing = SYSCALL_TIMING.lock();
|
|
|
|
{
|
|
|
|
let mut count_vec: Vec<(&usize, &i64)> = timing.iter().collect();
|
|
|
|
let end_time = unsafe { core::arch::x86_64::_rdtsc() };
|
|
|
|
count_vec.sort_by(|a, b| b.1.cmp(a.1));
|
|
|
|
*SYSCALL_TIMING.lock().entry(id).or_insert(0) += end_time - begin_time;
|
|
|
|
for (id, time) in count_vec.iter().take(5) {
|
|
|
|
if end_time % 1000 == 0 {
|
|
|
|
warn!("timing {:03} time {:012}", id, time);
|
|
|
|
let timing = SYSCALL_TIMING.lock();
|
|
|
|
}
|
|
|
|
let mut count_vec: Vec<(&usize, &i64)> = timing.iter().collect();
|
|
|
|
|
|
|
|
count_vec.sort_by(|a, b| b.1.cmp(a.1));
|
|
|
|
|
|
|
|
for (id, time) in count_vec.iter().take(5) {
|
|
|
|
|
|
|
|
warn!("timing {:03} time {:012}", id, time);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match ret {
|
|
|
|
|
|
|
|
Ok(code) => code as isize,
|
|
|
|
|
|
|
|
Err(err) => -(err as isize),
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match ret {
|
|
|
|
|
|
|
|
Ok(code) => code as isize,
|
|
|
|
|
|
|
|
Err(err) => -(err as isize),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn unimplemented(name: &str, ret: SysResult) -> SysResult {
|
|
|
|
fn unimplemented(&self, name: &str, ret: SysResult) -> SysResult {
|
|
|
|
warn!("{} is unimplemented", name);
|
|
|
|
warn!("{} is unimplemented", name);
|
|
|
|
ret
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(target_arch = "mips")]
|
|
|
|
#[cfg(target_arch = "mips")]
|
|
|
|
fn mips_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
|
|
|
|
fn mips_syscall(&mut self, id: usize, args: [usize; 6],) -> Option<SysResult> {
|
|
|
|
let ret = match id {
|
|
|
|
let ret = match id {
|
|
|
|
SYS_OPEN => sys_open(args[0] as *const u8, args[1], args[2]),
|
|
|
|
SYS_OPEN => self.sys_open(args[0] as *const u8, args[1], args[2]),
|
|
|
|
SYS_POLL => sys_poll(args[0] as *mut PollFd, args[1], args[2]),
|
|
|
|
SYS_POLL => self.sys_poll(args[0] as *mut PollFd, args[1], args[2]),
|
|
|
|
SYS_DUP2 => sys_dup2(args[0], args[1]),
|
|
|
|
SYS_DUP2 => self.sys_dup2(args[0], args[1]),
|
|
|
|
SYS_FORK => sys_fork(tf),
|
|
|
|
SYS_FORK => self.sys_fork(),
|
|
|
|
SYS_MMAP2 => sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5] * 4096),
|
|
|
|
SYS_MMAP2 => self.sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5] * 4096),
|
|
|
|
SYS_FSTAT64 => sys_fstat(args[0], args[1] as *mut Stat),
|
|
|
|
SYS_FSTAT64 => self.sys_fstat(args[0], args[1] as *mut Stat),
|
|
|
|
SYS_LSTAT64 => sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
|
|
|
|
SYS_LSTAT64 => self.sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
|
|
|
|
SYS_STAT64 => sys_stat(args[0] as *const u8, args[1] as *mut Stat),
|
|
|
|
SYS_STAT64 => self.sys_stat(args[0] as *const u8, args[1] as *mut Stat),
|
|
|
|
SYS_PIPE => {
|
|
|
|
SYS_PIPE => {
|
|
|
|
let fd_ptr = args[0] as *mut u32;
|
|
|
|
let fd_ptr = args[0] as *mut u32;
|
|
|
|
match sys_pipe(fd_ptr) {
|
|
|
|
match self.sys_pipe(fd_ptr) {
|
|
|
|
Ok(code) => {
|
|
|
|
Ok(code) => {
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
tf.v0 = *fd_ptr as usize;
|
|
|
|
tf.v0 = *fd_ptr as usize;
|
|
|
|
tf.v1 = *(fd_ptr.add(1)) as usize;
|
|
|
|
tf.v1 = *(fd_ptr.add(1)) as usize;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(tf.v0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(tf.v0)
|
|
|
|
Err(err) => Err(err),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(err) => Err(err),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SYS_FCNTL64 => unimplemented("fcntl64", Ok(0)),
|
|
|
|
|
|
|
|
SYS_SET_THREAD_AREA => {
|
|
|
|
|
|
|
|
info!("set_thread_area: tls: 0x{:x}", args[0]);
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
fn _cur_tls();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SYS_FCNTL64 => self.unimplemented("fcntl64", Ok(0)),
|
|
|
|
|
|
|
|
SYS_SET_THREAD_AREA => {
|
|
|
|
|
|
|
|
info!("set_thread_area: tls: 0x{:x}", args[0]);
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
fn _cur_tls();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
asm!("mtc0 $0, $$4, 2": :"r"(args[0]));
|
|
|
|
asm!("mtc0 $0, $$4, 2": :"r"(args[0]));
|
|
|
|
*(_cur_tls as *mut usize) = args[0];
|
|
|
|
*(_cur_tls as *mut usize) = args[0];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(0)
|
|
|
|
_ => return None,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
_ => return None,
|
|
|
|
Some(ret)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
Some(ret)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
|
|
|
|
fn x86_64_syscall(&mut self, id: usize, args: [usize; 6]) -> Option<SysResult> {
|
|
|
|
let ret = match id {
|
|
|
|
let ret = match id {
|
|
|
|
SYS_OPEN => sys_open(args[0] as *const u8, args[1], args[2]),
|
|
|
|
SYS_OPEN => self.sys_open(args[0] as *const u8, args[1], args[2]),
|
|
|
|
SYS_STAT => sys_stat(args[0] as *const u8, args[1] as *mut Stat),
|
|
|
|
SYS_STAT => self.sys_stat(args[0] as *const u8, args[1] as *mut Stat),
|
|
|
|
SYS_LSTAT => sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
|
|
|
|
SYS_LSTAT => self.sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
|
|
|
|
SYS_POLL => sys_poll(args[0] as *mut PollFd, args[1], args[2]),
|
|
|
|
SYS_POLL => self.sys_poll(args[0] as *mut PollFd, args[1], args[2]),
|
|
|
|
SYS_ACCESS => sys_access(args[0] as *const u8, args[1]),
|
|
|
|
SYS_ACCESS => self.sys_access(args[0] as *const u8, args[1]),
|
|
|
|
SYS_PIPE => sys_pipe(args[0] as *mut u32),
|
|
|
|
SYS_PIPE => self.sys_pipe(args[0] as *mut u32),
|
|
|
|
SYS_SELECT => sys_select(
|
|
|
|
SYS_SELECT => self.sys_select(
|
|
|
|
args[0],
|
|
|
|
args[0],
|
|
|
|
args[1] as *mut u32,
|
|
|
|
args[1] as *mut u32,
|
|
|
|
args[2] as *mut u32,
|
|
|
|
args[2] as *mut u32,
|
|
|
|
args[3] as *mut u32,
|
|
|
|
args[3] as *mut u32,
|
|
|
|
args[4] as *const TimeVal,
|
|
|
|
args[4] as *const TimeVal,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
SYS_DUP2 => sys_dup2(args[0], args[1]),
|
|
|
|
SYS_DUP2 => self.sys_dup2(args[0], args[1]),
|
|
|
|
SYS_ALARM => unimplemented("alarm", Ok(0)),
|
|
|
|
SYS_ALARM => self.unimplemented("alarm", Ok(0)),
|
|
|
|
SYS_FORK => sys_fork(tf),
|
|
|
|
SYS_FORK => self.sys_fork(),
|
|
|
|
SYS_VFORK => sys_vfork(tf),
|
|
|
|
SYS_VFORK => self.sys_vfork(),
|
|
|
|
SYS_RENAME => sys_rename(args[0] as *const u8, args[1] as *const u8),
|
|
|
|
SYS_RENAME => self.sys_rename(args[0] as *const u8, args[1] as *const u8),
|
|
|
|
SYS_MKDIR => sys_mkdir(args[0] as *const u8, args[1]),
|
|
|
|
SYS_MKDIR => self.sys_mkdir(args[0] as *const u8, args[1]),
|
|
|
|
SYS_RMDIR => sys_rmdir(args[0] as *const u8),
|
|
|
|
SYS_RMDIR => self.sys_rmdir(args[0] as *const u8),
|
|
|
|
SYS_LINK => sys_link(args[0] as *const u8, args[1] as *const u8),
|
|
|
|
SYS_LINK => self.sys_link(args[0] as *const u8, args[1] as *const u8),
|
|
|
|
SYS_UNLINK => sys_unlink(args[0] as *const u8),
|
|
|
|
SYS_UNLINK => self.sys_unlink(args[0] as *const u8),
|
|
|
|
SYS_READLINK => sys_readlink(args[0] as *const u8, args[1] as *mut u8, args[2]),
|
|
|
|
SYS_READLINK => self.sys_readlink(args[0] as *const u8, args[1] as *mut u8, args[2]),
|
|
|
|
SYS_CHMOD => unimplemented("chmod", Ok(0)),
|
|
|
|
SYS_CHMOD => self.unimplemented("chmod", Ok(0)),
|
|
|
|
SYS_CHOWN => unimplemented("chown", Ok(0)),
|
|
|
|
SYS_CHOWN => self.unimplemented("chown", Ok(0)),
|
|
|
|
SYS_ARCH_PRCTL => sys_arch_prctl(args[0] as i32, args[1], tf),
|
|
|
|
SYS_ARCH_PRCTL => self.sys_arch_prctl(args[0] as i32, args[1]),
|
|
|
|
SYS_TIME => sys_time(args[0] as *mut u64),
|
|
|
|
SYS_TIME => self.sys_time(args[0] as *mut u64),
|
|
|
|
SYS_EPOLL_CREATE => unimplemented("epoll_create", Err(SysError::ENOSYS)),
|
|
|
|
SYS_EPOLL_CREATE => self.unimplemented("epoll_create", Err(SysError::ENOSYS)),
|
|
|
|
_ => return None,
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
Some(ret)
|
|
|
|
Some(ret)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub type SysResult = Result<usize, SysError>;
|
|
|
|
pub type SysResult = Result<usize, SysError>;
|
|
|
|