mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-18 03:56:42 +00:00
368 lines
8.7 KiB
Rust
368 lines
8.7 KiB
Rust
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
//! Read the Cpu ctx content then dispatch syscall to corresponding handler
|
|
//! The each sub module contains functions that handle real syscall logic.
|
|
pub use clock_gettime::ClockId;
|
|
use ostd::cpu::UserContext;
|
|
|
|
use crate::{context::Context, cpu::LinuxAbi, prelude::*};
|
|
|
|
mod accept;
|
|
mod access;
|
|
mod alarm;
|
|
mod arch;
|
|
mod arch_prctl;
|
|
mod bind;
|
|
mod brk;
|
|
mod capget;
|
|
mod capset;
|
|
mod chdir;
|
|
mod chmod;
|
|
mod chown;
|
|
mod chroot;
|
|
mod clock_gettime;
|
|
mod clone;
|
|
mod close;
|
|
mod connect;
|
|
mod constants;
|
|
mod dup;
|
|
mod epoll;
|
|
mod eventfd;
|
|
mod execve;
|
|
mod exit;
|
|
mod exit_group;
|
|
mod fallocate;
|
|
mod fcntl;
|
|
mod flock;
|
|
mod fork;
|
|
mod fsync;
|
|
mod futex;
|
|
mod getcwd;
|
|
mod getdents64;
|
|
mod getegid;
|
|
mod geteuid;
|
|
mod getgid;
|
|
mod getgroups;
|
|
mod getpeername;
|
|
mod getpgid;
|
|
mod getpgrp;
|
|
mod getpid;
|
|
mod getppid;
|
|
mod getrandom;
|
|
mod getresgid;
|
|
mod getresuid;
|
|
mod getrusage;
|
|
mod getsid;
|
|
mod getsockname;
|
|
mod getsockopt;
|
|
mod gettid;
|
|
mod gettimeofday;
|
|
mod getuid;
|
|
mod ioctl;
|
|
mod kill;
|
|
mod link;
|
|
mod listen;
|
|
mod lseek;
|
|
mod madvise;
|
|
mod mkdir;
|
|
mod mknod;
|
|
mod mmap;
|
|
mod mount;
|
|
mod mprotect;
|
|
mod msync;
|
|
mod munmap;
|
|
mod nanosleep;
|
|
mod open;
|
|
mod pause;
|
|
mod pipe;
|
|
mod poll;
|
|
mod prctl;
|
|
mod pread64;
|
|
mod preadv;
|
|
mod prlimit64;
|
|
mod pselect6;
|
|
mod pwrite64;
|
|
mod pwritev;
|
|
mod read;
|
|
mod readlink;
|
|
mod recvfrom;
|
|
mod recvmsg;
|
|
mod rename;
|
|
mod rmdir;
|
|
mod rt_sigaction;
|
|
mod rt_sigpending;
|
|
mod rt_sigprocmask;
|
|
mod rt_sigreturn;
|
|
mod rt_sigsuspend;
|
|
mod sched_affinity;
|
|
mod sched_yield;
|
|
mod select;
|
|
mod semctl;
|
|
mod semget;
|
|
mod semop;
|
|
mod sendfile;
|
|
mod sendmsg;
|
|
mod sendto;
|
|
mod set_get_priority;
|
|
mod set_robust_list;
|
|
mod set_tid_address;
|
|
mod setfsgid;
|
|
mod setfsuid;
|
|
mod setgid;
|
|
mod setgroups;
|
|
mod setitimer;
|
|
mod setpgid;
|
|
mod setregid;
|
|
mod setresgid;
|
|
mod setresuid;
|
|
mod setreuid;
|
|
mod setsid;
|
|
mod setsockopt;
|
|
mod setuid;
|
|
mod shutdown;
|
|
mod sigaltstack;
|
|
mod socket;
|
|
mod socketpair;
|
|
mod stat;
|
|
mod statfs;
|
|
mod symlink;
|
|
mod sync;
|
|
mod sysinfo;
|
|
mod tgkill;
|
|
mod time;
|
|
mod timer_create;
|
|
mod timer_settime;
|
|
mod truncate;
|
|
mod umask;
|
|
mod umount;
|
|
mod uname;
|
|
mod unlink;
|
|
mod utimens;
|
|
mod wait4;
|
|
mod waitid;
|
|
mod write;
|
|
|
|
/// This macro is used to define syscall handler.
|
|
/// The first param is the number of parameters,
|
|
/// The second param is the function name of syscall handler,
|
|
/// The third is optional, means the args(if parameter number > 0),
|
|
/// The fourth is optional, means if cpu ctx is required.
|
|
macro_rules! syscall_handler {
|
|
(0, $fn_name: ident, $args: ident, $ctx: expr) => {
|
|
$fn_name($ctx)
|
|
};
|
|
(0, $fn_name: ident, $args: ident, $ctx: expr, $user_ctx: expr) => {
|
|
$fn_name($ctx, $user_ctx)
|
|
};
|
|
|
|
(1, $fn_name: ident, $args: ident, $ctx: expr) => {
|
|
$fn_name($args[0] as _, $ctx)
|
|
};
|
|
(1, $fn_name: ident, $args: ident, $ctx: expr, $user_ctx: expr) => {
|
|
$fn_name($args[0] as _, $ctx, $user_ctx)
|
|
};
|
|
|
|
(2, $fn_name: ident, $args: ident, $ctx: expr) => {
|
|
$fn_name($args[0] as _, $args[1] as _, $ctx)
|
|
};
|
|
(2, $fn_name: ident, $args: ident, $ctx: expr, $user_ctx: expr) => {
|
|
$fn_name($args[0] as _, $args[1] as _, $ctx, $user_ctx)
|
|
};
|
|
|
|
(3, $fn_name: ident, $args: ident, $ctx: expr) => {
|
|
$fn_name($args[0] as _, $args[1] as _, $args[2] as _, $ctx)
|
|
};
|
|
(3, $fn_name: ident, $args: ident, $ctx: expr, $user_ctx: expr) => {
|
|
$fn_name($args[0] as _, $args[1] as _, $args[2] as _, $ctx, $user_ctx)
|
|
};
|
|
|
|
(4, $fn_name: ident, $args: ident, $ctx: expr) => {
|
|
$fn_name(
|
|
$args[0] as _,
|
|
$args[1] as _,
|
|
$args[2] as _,
|
|
$args[3] as _,
|
|
$ctx,
|
|
)
|
|
};
|
|
(4, $fn_name: ident, $args: ident, $ctx: expr, $user_ctx: expr) => {
|
|
$fn_name(
|
|
$args[0] as _,
|
|
$args[1] as _,
|
|
$args[2] as _,
|
|
$args[3] as _,
|
|
$ctx,
|
|
$user_ctx,
|
|
)
|
|
};
|
|
|
|
(5, $fn_name: ident, $args: ident, $ctx: expr) => {
|
|
$fn_name(
|
|
$args[0] as _,
|
|
$args[1] as _,
|
|
$args[2] as _,
|
|
$args[3] as _,
|
|
$args[4] as _,
|
|
$ctx,
|
|
)
|
|
};
|
|
(5, $fn_name: ident, $args: ident, $ctx: expr, $user_ctx: expr) => {
|
|
$fn_name(
|
|
$args[0] as _,
|
|
$args[1] as _,
|
|
$args[2] as _,
|
|
$args[3] as _,
|
|
$args[4] as _,
|
|
$ctx,
|
|
$user_ctx,
|
|
)
|
|
};
|
|
|
|
(6, $fn_name: ident, $args: ident, $ctx: expr) => {
|
|
$fn_name(
|
|
$args[0] as _,
|
|
$args[1] as _,
|
|
$args[2] as _,
|
|
$args[3] as _,
|
|
$args[4] as _,
|
|
$args[5] as _,
|
|
$ctx,
|
|
)
|
|
};
|
|
(6, $fn_name: ident, $args: ident, $ctx: expr, $user_ctx: expr) => {
|
|
$fn_name(
|
|
$args[0] as _,
|
|
$args[1] as _,
|
|
$args[2] as _,
|
|
$args[3] as _,
|
|
$args[4] as _,
|
|
$args[5] as _,
|
|
$ctx,
|
|
$user_ctx,
|
|
)
|
|
};
|
|
}
|
|
|
|
macro_rules! dispatch_fn_inner {
|
|
( $args: ident, $ctx: ident, $user_ctx: ident, $handler: ident ( args[ .. $cnt: tt ] ) ) => {
|
|
$crate::syscall::syscall_handler!($cnt, $handler, $args, $ctx)
|
|
};
|
|
( $args: ident, $ctx: ident, $user_ctx: ident, $handler: ident ( args[ .. $cnt: tt ] , &user_ctx ) ) => {
|
|
$crate::syscall::syscall_handler!($cnt, $handler, $args, $ctx, &$user_ctx)
|
|
};
|
|
( $args: ident, $ctx: ident, $user_ctx: ident, $handler: ident ( args[ .. $cnt: tt ] , &mut user_ctx ) ) => {
|
|
// `$user_ctx` is already of type `&mut ostd::cpu::UserContext`,
|
|
// so no need to take `&mut` again
|
|
$crate::syscall::syscall_handler!($cnt, $handler, $args, $ctx, $user_ctx)
|
|
};
|
|
}
|
|
|
|
macro_rules! impl_syscall_nums_and_dispatch_fn {
|
|
// $args, $user_ctx, and $dispatcher_name are needed since Rust macro is hygienic
|
|
( $( $name: ident = $num: literal => $handler: ident $args: tt );* $(;)? ) => {
|
|
// First, define the syscall numbers
|
|
$(
|
|
pub const $name: u64 = $num;
|
|
)*
|
|
|
|
// Then, define the dispatcher function
|
|
pub fn syscall_dispatch(
|
|
syscall_number: u64,
|
|
args: [u64; 6],
|
|
ctx: &crate::context::Context,
|
|
user_ctx: &mut ostd::cpu::UserContext,
|
|
) -> $crate::prelude::Result<$crate::syscall::SyscallReturn> {
|
|
match syscall_number {
|
|
$(
|
|
$num => {
|
|
$crate::log_syscall_entry!($name);
|
|
$crate::syscall::dispatch_fn_inner!(args, ctx, user_ctx, $handler $args)
|
|
}
|
|
)*
|
|
_ => {
|
|
log::warn!("Unimplemented syscall number: {}", syscall_number);
|
|
$crate::return_errno_with_message!($crate::error::Errno::ENOSYS, "Syscall was unimplemented");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Export macros to sub-modules
|
|
use dispatch_fn_inner;
|
|
use impl_syscall_nums_and_dispatch_fn;
|
|
use syscall_handler;
|
|
|
|
pub struct SyscallArgument {
|
|
syscall_number: u64,
|
|
args: [u64; 6],
|
|
}
|
|
|
|
/// Syscall return
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub enum SyscallReturn {
|
|
/// return isize, this value will be used to set rax
|
|
Return(isize),
|
|
/// does not need to set rax
|
|
NoReturn,
|
|
}
|
|
|
|
impl SyscallArgument {
|
|
fn new_from_context(user_ctx: &UserContext) -> Self {
|
|
let syscall_number = user_ctx.syscall_num() as u64;
|
|
let args = user_ctx.syscall_args().map(|x| x as u64);
|
|
Self {
|
|
syscall_number,
|
|
args,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn handle_syscall(ctx: &Context, user_ctx: &mut UserContext) {
|
|
let syscall_frame = SyscallArgument::new_from_context(user_ctx);
|
|
let syscall_return = arch::syscall_dispatch(
|
|
syscall_frame.syscall_number,
|
|
syscall_frame.args,
|
|
ctx,
|
|
user_ctx,
|
|
);
|
|
|
|
match syscall_return {
|
|
Ok(return_value) => {
|
|
if let SyscallReturn::Return(return_value) = return_value {
|
|
user_ctx.set_syscall_ret(return_value as usize);
|
|
}
|
|
}
|
|
Err(err) => {
|
|
debug!("syscall return error: {:?}", err);
|
|
let errno = err.error() as i32;
|
|
user_ctx.set_syscall_ret((-errno) as usize)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! log_syscall_entry {
|
|
($syscall_name: tt) => {
|
|
if log::log_enabled!(log::Level::Info) {
|
|
let syscall_name_str = stringify!($syscall_name);
|
|
let pid = $crate::current!().pid();
|
|
let tid = {
|
|
use $crate::process::posix_thread::AsPosixThread;
|
|
$crate::current_thread!().as_posix_thread().unwrap().tid()
|
|
};
|
|
log::info!(
|
|
"[pid={}][tid={}][id={}][{}]",
|
|
pid,
|
|
tid,
|
|
$syscall_name,
|
|
syscall_name_str
|
|
);
|
|
}
|
|
};
|
|
}
|
|
|
|
pub(super) fn init() {
|
|
uname::init();
|
|
}
|