use axhal::uspace::UserContext;
#[cfg(not(target_arch = "x86_64"))]
mod nums {
pub const SYS_IOCTL: usize = 29;
pub const SYS_WRITEV: usize = 66;
pub const SYS_EXIT: usize = 93;
pub const SYS_EXIT_GROUP: usize = 94;
pub const SYS_SET_TID_ADDRESS: usize = 96;
}
#[cfg(target_arch = "x86_64")]
mod nums {
pub const SYS_IOCTL: usize = 16;
pub const SYS_WRITEV: usize = 20;
pub const SYS_EXIT: usize = 60;
pub const SYS_EXIT_GROUP: usize = 231;
pub const SYS_SET_TID_ADDRESS: usize = 218;
pub const SYS_ARCH_PRCTL: usize = 158;
pub const ARCH_SET_FS: usize = 0x1002;
}
use nums::*;
#[repr(C)]
struct IoVec {
iov_base: usize,
iov_len: usize,
}
#[cfg(any(
target_arch = "riscv64",
target_arch = "riscv32",
target_arch = "loongarch64"
))]
fn get_syscall_num(uctx: &UserContext) -> usize {
uctx.regs.a7
}
#[cfg(target_arch = "aarch64")]
fn get_syscall_num(uctx: &UserContext) -> usize {
uctx.x[8] as usize
}
#[cfg(target_arch = "x86_64")]
fn get_syscall_num(uctx: &UserContext) -> usize {
uctx.rax as usize
}
fn set_syscall_ret(uctx: &mut UserContext, ret: usize) {
#[cfg(target_arch = "x86_64")]
{
uctx.rax = ret as u64;
}
#[cfg(not(target_arch = "x86_64"))]
{
uctx.set_arg0(ret);
}
}
pub fn handle_syscall(uctx: &mut UserContext) -> Option<i32> {
let syscall_num = get_syscall_num(uctx);
let args = [uctx.arg0(), uctx.arg1(), uctx.arg2()];
ax_println!("handle_syscall [{}] ...", syscall_num);
let ret: isize = match syscall_num {
SYS_IOCTL => {
ax_println!("Unimplemented syscall: SYS_IOCTL");
0
}
SYS_SET_TID_ADDRESS => {
axtask::current().id().as_u64() as isize
}
SYS_WRITEV => sys_writev(args[0] as i32, args[1] as *const IoVec, args[2] as i32),
SYS_EXIT_GROUP => {
ax_println!("[SYS_EXIT_GROUP]: system is exiting ..");
return Some(args[0] as i32);
}
SYS_EXIT => {
ax_println!("[SYS_EXIT]: system is exiting ..");
return Some(args[0] as i32);
}
#[cfg(target_arch = "x86_64")]
SYS_ARCH_PRCTL => sys_arch_prctl(uctx, args[0], args[1]),
_ => {
ax_println!("Unimplemented syscall: {}", syscall_num);
-(axerrno::LinuxError::ENOSYS.code() as isize)
}
};
set_syscall_ret(uctx, ret as usize);
None
}
fn sys_writev(fd: i32, iov: *const IoVec, iovcnt: i32) -> isize {
if fd != 1 && fd != 2 {
return -(axerrno::LinuxError::EBADF.code() as isize);
}
let mut total: isize = 0;
for i in 0..iovcnt as usize {
let entry = unsafe { &*iov.add(i) };
if entry.iov_len == 0 || entry.iov_base == 0 {
continue;
}
let slice =
unsafe { core::slice::from_raw_parts(entry.iov_base as *const u8, entry.iov_len) };
for &b in slice {
ax_print!("{}", b as char);
}
total += entry.iov_len as isize;
}
total
}
#[cfg(target_arch = "x86_64")]
fn sys_arch_prctl(uctx: &mut UserContext, op: usize, addr: usize) -> isize {
match op {
ARCH_SET_FS => {
uctx.fs_base = addr as u64;
0
}
_ => {
ax_println!("Unimplemented arch_prctl op: {:#x}", op);
-(axerrno::LinuxError::EINVAL.code() as isize)
}
}
}