diff --git a/Cargo.toml b/Cargo.toml index 5e50fb8b..31fa59ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,3 +24,6 @@ axmm = { git = "https://github.com/arceos-org/arceos.git" } axtask = { git = "https://github.com/arceos-org/arceos.git" } axsync = { git = "https://github.com/arceos-org/arceos.git" } axruntime = { git = "https://github.com/arceos-org/arceos.git", features = ["multitask"] } + +[target.'cfg(target_arch = "x86_64")'.dependencies] +x86 = "0.52" diff --git a/src/main.rs b/src/main.rs index ca4151f3..55d253ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ extern crate axstd; mod loader; mod mm; -mod syscall; +mod syscall_imp; mod task; use alloc::sync::Arc; diff --git a/src/mm.rs b/src/mm.rs index 2bcb24b5..5665372a 100644 --- a/src/mm.rs +++ b/src/mm.rs @@ -2,9 +2,12 @@ use alloc::string::ToString; use axerrno::AxResult; use memory_addr::{MemoryAddr, PageIter4K, VirtAddr, PAGE_SIZE_4K}; -use axhal::mem::phys_to_virt; -use axhal::paging::MappingFlags; -use axhal::trap::{register_trap_handler, PAGE_FAULT}; +use axhal::{ + mem::phys_to_virt, + paging::MappingFlags, + trap::{register_trap_handler, PAGE_FAULT}, +}; + use axmm::AddrSpace; use axtask::TaskExtRef; @@ -71,33 +74,37 @@ pub fn load_user_app(app_name: &str) -> AxResult<(VirtAddr, VirtAddr, AddrSpace) // TDOO: flush the I-cache } - let ustack_base = uspace.end(); + // The user stack is divided into two parts: + // `ustack_bottom` -> `ustack top`: It is the stack space that users actually read and write. + // `ustack_top` -> `ustack end`: It is the space that contains the arguments, environment variables and auxv passed to the app. + // When the app starts running, the stack pointer points to `ustack_top`. + let ustack_end = uspace.end(); let ustack_size = crate::USER_STACK_SIZE; - let ustack_top = ustack_base - ustack_size; + let ustack_bottom = ustack_end - ustack_size; debug!( "Mapping user stack: {:#x?} -> {:#x?}", - ustack_top, ustack_base + ustack_bottom, ustack_end ); // FIXME: Add more arguments and environment variables - let (stack_data, ustack_bottom) = elf_parser::get_app_stack_region( + let (stack_data, ustack_top) = elf_parser::get_app_stack_region( &[app_name.to_string()], &[], &elf_info.auxv, - ustack_top, + ustack_bottom, ustack_size, ); uspace.map_alloc( - ustack_top, + ustack_bottom, ustack_size, MappingFlags::READ | MappingFlags::WRITE | MappingFlags::USER, true, )?; { // Copy the stack data to the user stack - let ustack_bottom_align = VirtAddr::from_usize(ustack_bottom).align_down_4k(); - let stack_data_offset = ustack_bottom_align - ustack_top; + let ustack_top_align = VirtAddr::from_usize(ustack_top).align_down_4k(); + let stack_data_offset = ustack_top_align - ustack_bottom; // Only copy data which contains args, envs and auxv. - for (idx, vaddr) in PageIter4K::new(ustack_bottom_align, ustack_base) + for (idx, vaddr) in PageIter4K::new(ustack_top_align, ustack_end) .expect("Failed to create page iterator") .enumerate() { @@ -116,7 +123,7 @@ pub fn load_user_app(app_name: &str) -> AxResult<(VirtAddr, VirtAddr, AddrSpace) } } - Ok((elf_info.entry, VirtAddr::from(ustack_bottom), uspace)) + Ok((elf_info.entry, VirtAddr::from(ustack_top), uspace)) } #[register_trap_handler(PAGE_FAULT)] diff --git a/src/syscall.rs b/src/syscall.rs deleted file mode 100644 index 3ccd5927..00000000 --- a/src/syscall.rs +++ /dev/null @@ -1,225 +0,0 @@ -#![allow(dead_code)] - -use arceos_posix_api as api; -use axerrno::{AxError, LinuxError}; -use axhal::arch::{TrapFrame, UspaceContext}; -use axhal::paging::MappingFlags; -use axhal::trap::{register_trap_handler, SYSCALL}; -use axtask::{current, TaskExtRef}; -use memory_addr::{VirtAddr, VirtAddrRange}; -use num_enum::TryFromPrimitive; - -const SYS_READ: usize = 0; -const SYS_WRITE: usize = 1; -const SYS_MMAP: usize = 9; -const SYS_IOCTL: usize = 16; -const SYS_WRITEV: usize = 20; -const SYS_SCHED_YIELD: usize = 24; -const SYS_NANOSLEEP: usize = 35; -const SYS_GETPID: usize = 39; -const SYS_CLONE: usize = 56; -const SYS_FORK: usize = 57; -const SYS_EXECVE: usize = 59; -const SYS_EXIT: usize = 60; -const SYS_ARCH_PRCTL: usize = 158; -const SYS_SET_TID_ADDRESS: usize = 218; -const SYS_CLOCK_GETTIME: usize = 228; -const SYS_CLOCK_NANOSLEEP: usize = 230; -const SYS_EXITGROUP: usize = 231; - -bitflags::bitflags! { - #[derive(Debug)] - /// permissions for sys_mmap - /// - /// See - pub struct MmapProt: i32 { - /// Page can be read. - const PROT_READ = 1 << 0; - /// Page can be written. - const PROT_WRITE = 1 << 1; - /// Page can be executed. - const PROT_EXEC = 1 << 2; - } -} - -impl From for MappingFlags { - fn from(value: MmapProt) -> Self { - let mut flags = MappingFlags::USER; - if value.contains(MmapProt::PROT_READ) { - flags |= MappingFlags::READ; - } - if value.contains(MmapProt::PROT_WRITE) { - flags |= MappingFlags::WRITE; - } - if value.contains(MmapProt::PROT_EXEC) { - flags |= MappingFlags::EXECUTE; - } - flags - } -} - -bitflags::bitflags! { - #[derive(Debug)] - /// flags for sys_mmap - /// - /// See - pub struct MmapFlags: i32 { - /// Share changes - const MAP_SHARED = 1 << 0; - /// Changes private; copy pages on write. - const MAP_PRIVATE = 1 << 1; - /// Map address must be exactly as requested, no matter whether it is available. - const MAP_FIXED = 1 << 4; - /// Don't use a file. - const MAP_ANONYMOUS = 1 << 5; - /// Don't check for reservations. - const MAP_NORESERVE = 1 << 14; - /// Allocation is for a stack. - const MAP_STACK = 0x20000; - } -} - -#[derive(Debug, Eq, PartialEq, TryFromPrimitive)] -#[repr(i32)] -/// ARCH_PRCTL codes -pub enum ArchPrctlCode { - /// Set the FS segment base - ArchSetFs = 0x1002, - /// Get the FS segment base - ArchGetFs = 0x1003, - /// Set the GS segment base - ArchSetGs = 0x1001, - /// Get the GS segment base - ArchGetGs = 0x1004, -} - -#[cfg(target_arch = "x86_64")] -fn sys_arch_prctl(code: i32, addr: *mut usize) -> isize { - match ArchPrctlCode::try_from(code) { - // TODO: check the legality of the address - Ok(ArchPrctlCode::ArchSetFs) => { - unsafe { - axhal::arch::write_thread_pointer(*addr); - } - 0 - } - Ok(ArchPrctlCode::ArchGetFs) => { - unsafe { - *addr = axhal::arch::read_thread_pointer(); - } - 0 - } - Ok(ArchPrctlCode::ArchSetGs) | Ok(ArchPrctlCode::ArchGetGs) => todo!(), - _ => -LinuxError::EINVAL.code() as isize, - } -} - -/// To set the clear_child_tid field in the task extended data. -/// -/// The set_tid_address() always succeeds -fn sys_set_tid_address(tid_ptd: *const i32) -> isize { - let curr = current(); - curr.task_ext().set_clear_child_tid(tid_ptd as _); - curr.id().as_u64() as isize -} - -fn sys_exit(status: i32) -> ! { - let curr = current(); - let clear_child_tid = curr.task_ext().clear_child_tid() as *mut i32; - if !clear_child_tid.is_null() { - // TODO: check whether the address is valid - unsafe { - // TODO: Encapsulate all operations that access user-mode memory into a unified function - *(clear_child_tid) = 0; - } - // TODO: wake up threads, which are blocked by futex, and waiting for the address pointed by clear_child_tid - } - axtask::exit(status); -} - -fn mmap(addr: *mut usize, length: usize, prot: i32, flags: i32) -> Result { - let curr = current(); - let curr_ext = curr.task_ext(); - let mut aspace = curr_ext.aspace.lock(); - let permiss_flags = MmapProt::from_bits_truncate(prot); - // TODO: check illegal flags for mmap - // An example is the flags contained none of MAP_PRIVATE, MAP_SHARED, or MAP_SHARED_VALIDATE. - let map_flags = MmapFlags::from_bits_truncate(flags); - - let start_addr = if map_flags.contains(MmapFlags::MAP_FIXED) { - VirtAddr::from(addr as usize) - } else { - aspace - .find_free_area( - VirtAddr::from(addr as usize), - length, - VirtAddrRange::new(aspace.base(), aspace.end()), - ) - .or(aspace.find_free_area( - aspace.base(), - length, - VirtAddrRange::new(aspace.base(), aspace.end()), - )) - .ok_or(LinuxError::ENOMEM)? - }; - - aspace - .map_alloc(start_addr, length, permiss_flags.into(), false) - .map_err(>::from)?; - - Ok(start_addr) -} - -fn sys_mmap(addr: *mut usize, length: usize, prot: i32, flags: i32) -> isize { - match mmap(addr, length, prot, flags) { - Ok(addr) => addr.as_usize() as isize, - Err(err) => -(err.code() as isize), - } -} - -fn sys_clone(tf: &TrapFrame, newsp: usize) -> usize { - let aspace = axtask::current().task_ext().aspace.clone(); - let mut uctx = UspaceContext::from(tf); - uctx.set_sp(newsp); - uctx.set_retval(0); - let new_task = crate::task::spawn_user_task(aspace, uctx); - new_task.id().as_u64() as usize -} - -fn sys_ioctl() -> usize { - warn!("Unimplemented syscall: SYS_IOCTL"); - 0 -} - -#[register_trap_handler(SYSCALL)] -fn handle_syscall(tf: &TrapFrame, syscall_num: usize) -> isize { - let ret = match syscall_num { - SYS_READ => api::sys_read(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _), - SYS_WRITE => api::sys_write(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _), - SYS_MMAP => sys_mmap( - tf.arg0() as _, - tf.arg1() as _, - tf.arg2() as _, - tf.arg3() as _, - ), - SYS_IOCTL => sys_ioctl() as _, - SYS_WRITEV => unsafe { api::sys_writev(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _) }, - SYS_SCHED_YIELD => api::sys_sched_yield() as isize, - SYS_NANOSLEEP => unsafe { api::sys_nanosleep(tf.arg0() as _, tf.arg1() as _) as _ }, - SYS_GETPID => api::sys_getpid() as isize, - SYS_EXIT => axtask::exit(tf.arg0() as _), - SYS_ARCH_PRCTL => sys_arch_prctl(tf.arg0() as _, tf.arg1() as _), - SYS_SET_TID_ADDRESS => sys_set_tid_address(tf.arg0() as _), - SYS_CLOCK_GETTIME => unsafe { api::sys_clock_gettime(tf.arg0() as _, tf.arg1() as _) as _ }, - SYS_CLOCK_NANOSLEEP => unsafe { - // TODO: port to the posix api - api::sys_nanosleep(tf.arg2() as _, tf.arg3() as _) as _ - }, - SYS_EXITGROUP => sys_exit(tf.arg0() as _), - _ => { - warn!("Unimplemented syscall: {}", syscall_num); - axtask::exit(LinuxError::ENOSYS as _) - } - }; - ret -} diff --git a/src/syscall_imp/fs/ctl.rs b/src/syscall_imp/fs/ctl.rs new file mode 100644 index 00000000..2aa36dad --- /dev/null +++ b/src/syscall_imp/fs/ctl.rs @@ -0,0 +1,18 @@ +use core::ffi::c_void; + +use crate::syscall_body; + +/// The ioctl() system call manipulates the underlying device parameters +/// of special files. +/// +/// # Arguments +/// * `fd` - The file descriptor +/// * `op` - The request code. It is of type unsigned long in glibc and BSD, +/// and of type int in musl and other UNIX systems. +/// * `argp` - The argument to the request. It is a pointer to a memory location +pub(crate) fn sys_ioctl(_fd: i32, _op: usize, _argp: *mut c_void) -> i32 { + syscall_body!(sys_ioctl, { + warn!("Unimplemented syscall: SYS_IOCTL"); + Ok(0) + }) +} diff --git a/src/syscall_imp/fs/io.rs b/src/syscall_imp/fs/io.rs new file mode 100644 index 00000000..6f5d30a2 --- /dev/null +++ b/src/syscall_imp/fs/io.rs @@ -0,0 +1,14 @@ +use core::ffi::c_void; + +use arceos_posix_api as api; + +pub(crate) fn sys_read(fd: i32, buf: *mut c_void, count: usize) -> isize { + api::sys_read(fd, buf, count) +} +pub(crate) fn sys_write(fd: i32, buf: *const c_void, count: usize) -> isize { + api::sys_write(fd, buf, count) +} + +pub(crate) fn sys_writev(fd: i32, iov: *const api::ctypes::iovec, iocnt: i32) -> isize { + unsafe { api::sys_writev(fd, iov, iocnt) } +} diff --git a/src/syscall_imp/fs/mod.rs b/src/syscall_imp/fs/mod.rs new file mode 100644 index 00000000..81af8c8e --- /dev/null +++ b/src/syscall_imp/fs/mod.rs @@ -0,0 +1,5 @@ +mod ctl; +mod io; + +pub(crate) use ctl::*; +pub(crate) use io::*; diff --git a/src/syscall_imp/mm/mmap.rs b/src/syscall_imp/mm/mmap.rs new file mode 100644 index 00000000..8d7b83f8 --- /dev/null +++ b/src/syscall_imp/mm/mmap.rs @@ -0,0 +1,100 @@ +use axerrno::{AxError, LinuxError}; +use axhal::paging::MappingFlags; +use axtask::{current, TaskExtRef}; +use memory_addr::{VirtAddr, VirtAddrRange}; + +use crate::syscall_body; + +bitflags::bitflags! { + #[derive(Debug)] + /// permissions for sys_mmap + /// + /// See + struct MmapProt: i32 { + /// Page can be read. + const PROT_READ = 1 << 0; + /// Page can be written. + const PROT_WRITE = 1 << 1; + /// Page can be executed. + const PROT_EXEC = 1 << 2; + } +} + +impl From for MappingFlags { + fn from(value: MmapProt) -> Self { + let mut flags = MappingFlags::USER; + if value.contains(MmapProt::PROT_READ) { + flags |= MappingFlags::READ; + } + if value.contains(MmapProt::PROT_WRITE) { + flags |= MappingFlags::WRITE; + } + if value.contains(MmapProt::PROT_EXEC) { + flags |= MappingFlags::EXECUTE; + } + flags + } +} + +bitflags::bitflags! { + #[derive(Debug)] + /// flags for sys_mmap + /// + /// See + struct MmapFlags: i32 { + /// Share changes + const MAP_SHARED = 1 << 0; + /// Changes private; copy pages on write. + const MAP_PRIVATE = 1 << 1; + /// Map address must be exactly as requested, no matter whether it is available. + const MAP_FIXED = 1 << 4; + /// Don't use a file. + const MAP_ANONYMOUS = 1 << 5; + /// Don't check for reservations. + const MAP_NORESERVE = 1 << 14; + /// Allocation is for a stack. + const MAP_STACK = 0x20000; + } +} + +pub(crate) fn sys_mmap( + addr: *mut usize, + length: usize, + prot: i32, + flags: i32, + _fd: i32, + _offset: isize, +) -> usize { + syscall_body!(sys_mmap, { + let curr = current(); + let curr_ext = curr.task_ext(); + let mut aspace = curr_ext.aspace.lock(); + let permiss_flags = MmapProt::from_bits_truncate(prot); + // TODO: check illegal flags for mmap + // An example is the flags contained none of MAP_PRIVATE, MAP_SHARED, or MAP_SHARED_VALIDATE. + let map_flags = MmapFlags::from_bits_truncate(flags); + + let start_addr = if map_flags.contains(MmapFlags::MAP_FIXED) { + VirtAddr::from(addr as usize) + } else { + aspace + .find_free_area( + VirtAddr::from(addr as usize), + length, + VirtAddrRange::new(aspace.base(), aspace.end()), + ) + .or(aspace.find_free_area( + aspace.base(), + length, + VirtAddrRange::new(aspace.base(), aspace.end()), + )) + .ok_or(LinuxError::ENOMEM)? + }; + + aspace + .map_alloc(start_addr, length, permiss_flags.into(), false) + .map_err(>::from)?; + + Ok(start_addr.as_usize()) + }) +} diff --git a/src/syscall_imp/mm/mod.rs b/src/syscall_imp/mm/mod.rs new file mode 100644 index 00000000..ca74032f --- /dev/null +++ b/src/syscall_imp/mm/mod.rs @@ -0,0 +1,3 @@ +mod mmap; + +pub(crate) use mmap::*; diff --git a/src/syscall_imp/mod.rs b/src/syscall_imp/mod.rs new file mode 100644 index 00000000..c15295b5 --- /dev/null +++ b/src/syscall_imp/mod.rs @@ -0,0 +1,83 @@ +mod fs; +mod mm; +mod task; +mod time; +use axerrno::LinuxError; +use axhal::{ + arch::TrapFrame, + trap::{register_trap_handler, SYSCALL}, +}; +use fs::*; +use mm::*; +use task::*; +use time::*; +const SYS_READ: usize = 0; +const SYS_WRITE: usize = 1; +const SYS_MMAP: usize = 9; +const SYS_IOCTL: usize = 16; +const SYS_WRITEV: usize = 20; +const SYS_SCHED_YIELD: usize = 24; +const SYS_NANOSLEEP: usize = 35; +const SYS_GETPID: usize = 39; +const SYS_EXIT: usize = 60; +#[cfg(target_arch = "x86_64")] +const SYS_ARCH_PRCTL: usize = 158; +const SYS_SET_TID_ADDRESS: usize = 218; +const SYS_CLOCK_GETTIME: usize = 228; +const SYS_CLOCK_NANOSLEEP: usize = 230; +const SYS_EXITGROUP: usize = 231; + +/// Macro to generate syscall body +/// +/// It will receive a function which return Result<_, LinuxError> and convert it to +/// the type which is specified by the caller. +#[macro_export] +macro_rules! syscall_body { + ($fn: ident, $($stmt: tt)*) => {{ + #[allow(clippy::redundant_closure_call)] + let res = (|| -> axerrno::LinuxResult<_> { $($stmt)* })(); + match res { + Ok(_) | Err(axerrno::LinuxError::EAGAIN) => debug!(concat!(stringify!($fn), " => {:?}"), res), + Err(_) => info!(concat!(stringify!($fn), " => {:?}"), res), + } + match res { + Ok(v) => v as _, + Err(e) => { + -e.code() as _ + } + } + }}; +} + +#[register_trap_handler(SYSCALL)] +fn handle_syscall(tf: &TrapFrame, syscall_num: usize) -> isize { + let ret = match syscall_num { + SYS_READ => sys_read(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _), + SYS_WRITE => sys_write(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _), + SYS_MMAP => sys_mmap( + tf.arg0() as _, + tf.arg1() as _, + tf.arg2() as _, + tf.arg3() as _, + tf.arg4() as _, + tf.arg5() as _, + ) as _, + SYS_IOCTL => sys_ioctl(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _) as _, + SYS_WRITEV => sys_writev(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _), + SYS_SCHED_YIELD => sys_sched_yield() as isize, + SYS_NANOSLEEP => sys_nanosleep(tf.arg0() as _, tf.arg1() as _) as _, + SYS_GETPID => sys_getpid() as isize, + SYS_EXIT => sys_exit(tf.arg0() as _), + #[cfg(target_arch = "x86_64")] + SYS_ARCH_PRCTL => sys_arch_prctl(tf.arg0() as _, tf.arg1() as _), + SYS_SET_TID_ADDRESS => sys_set_tid_address(tf.arg0() as _), + SYS_CLOCK_GETTIME => sys_clock_gettime(tf.arg0() as _, tf.arg1() as _) as _, + SYS_CLOCK_NANOSLEEP => sys_nanosleep(tf.arg0() as _, tf.arg1() as _) as _, + SYS_EXITGROUP => sys_exit_group(tf.arg0() as _), + _ => { + warn!("Unimplemented syscall: {}", syscall_num); + axtask::exit(LinuxError::ENOSYS as _) + } + }; + ret +} diff --git a/src/syscall_imp/task/mod.rs b/src/syscall_imp/task/mod.rs new file mode 100644 index 00000000..8196ff70 --- /dev/null +++ b/src/syscall_imp/task/mod.rs @@ -0,0 +1,4 @@ +mod schedule; +mod task; +pub(crate) use schedule::*; +pub(crate) use task::*; diff --git a/src/syscall_imp/task/schedule.rs b/src/syscall_imp/task/schedule.rs new file mode 100644 index 00000000..5de19b38 --- /dev/null +++ b/src/syscall_imp/task/schedule.rs @@ -0,0 +1,12 @@ +use arceos_posix_api as api; + +pub(crate) fn sys_sched_yield() -> i32 { + api::sys_sched_yield() +} + +pub(crate) fn sys_nanosleep( + req: *const api::ctypes::timespec, + rem: *mut api::ctypes::timespec, +) -> i32 { + unsafe { api::sys_nanosleep(req, rem) } +} diff --git a/src/syscall_imp/task/task.rs b/src/syscall_imp/task/task.rs new file mode 100644 index 00000000..a6b902cb --- /dev/null +++ b/src/syscall_imp/task/task.rs @@ -0,0 +1,96 @@ +use arceos_posix_api::{self as api}; + +use axtask::{current, TaskExtRef}; +use num_enum::TryFromPrimitive; + +use crate::syscall_body; + +#[derive(Debug, Eq, PartialEq, TryFromPrimitive)] +#[repr(i32)] +/// ARCH_PRCTL codes +/// +/// It is only avaliable on x86_64, and is not convenient +/// to generate automatically via c_to_rust binding. +enum ArchPrctlCode { + /// Set the GS segment base + ArchSetGs = 0x1001, + /// Set the FS segment base + ArchSetFs = 0x1002, + /// Get the FS segment base + ArchGetFs = 0x1003, + /// Get the GS segment base + ArchGetGs = 0x1004, + /// The setting of the flag manipulated by ARCH_SET_CPUID + ArchGetCpuid = 0x1011, + /// Enable (addr != 0) or disable (addr == 0) the cpuid instruction for the calling thread. + ArchSetCpuid = 0x1012, +} + +pub(crate) fn sys_getpid() -> i32 { + api::sys_getpid() +} + +pub(crate) fn sys_exit(status: i32) -> ! { + let curr = current(); + let clear_child_tid = curr.task_ext().clear_child_tid() as *mut i32; + if !clear_child_tid.is_null() { + // TODO: check whether the address is valid + unsafe { + // TODO: Encapsulate all operations that access user-mode memory into a unified function + *(clear_child_tid) = 0; + } + // TODO: wake up threads, which are blocked by futex, and waiting for the address pointed by clear_child_tid + } + axtask::exit(status); +} + +pub(crate) fn sys_exit_group(status: i32) -> ! { + warn!("Temporarily replace sys_exit_group with sys_exit"); + axtask::exit(status); +} + +/// To set the clear_child_tid field in the task extended data. +/// +/// The set_tid_address() always succeeds +pub(crate) fn sys_set_tid_address(tid_ptd: *const i32) -> isize { + syscall_body!(sys_set_tid_address, { + let curr = current(); + curr.task_ext().set_clear_child_tid(tid_ptd as _); + Ok(curr.id().as_u64() as isize) + }) +} + +#[cfg(target_arch = "x86_64")] +pub(crate) fn sys_arch_prctl(code: i32, addr: *mut usize) -> isize { + use axerrno::LinuxError; + syscall_body!(sys_arch_prctl, { + match ArchPrctlCode::try_from(code) { + // TODO: check the legality of the address + Ok(ArchPrctlCode::ArchSetFs) => { + unsafe { + axhal::arch::write_thread_pointer(*addr); + } + Ok(0) + } + Ok(ArchPrctlCode::ArchGetFs) => { + unsafe { + *addr = axhal::arch::read_thread_pointer(); + } + Ok(0) + } + Ok(ArchPrctlCode::ArchSetGs) => { + unsafe { + x86::msr::wrmsr(x86::msr::IA32_KERNEL_GSBASE, *addr as u64); + } + Ok(0) + } + Ok(ArchPrctlCode::ArchGetGs) => { + unsafe { + *addr = x86::msr::rdmsr(x86::msr::IA32_KERNEL_GSBASE) as usize; + } + Ok(0) + } + _ => Err(LinuxError::ENOSYS), + } + }) +} diff --git a/src/syscall_imp/time.rs b/src/syscall_imp/time.rs new file mode 100644 index 00000000..80aa6438 --- /dev/null +++ b/src/syscall_imp/time.rs @@ -0,0 +1,5 @@ +use arceos_posix_api as api; + +pub(crate) fn sys_clock_gettime(clock_id: i32, tp: *mut api::ctypes::timespec) -> i32 { + unsafe { api::sys_clock_gettime(clock_id, tp) } +}