From ac78d1519925e7d70ceedeeeee39e60e7dd5c2cf Mon Sep 17 00:00:00 2001 From: AuYang261 <459461160@qq.com> Date: Wed, 13 Mar 2024 14:30:11 +0800 Subject: [PATCH] add and modify some syscalls and pass the tensorflow test; extend memory --- api/ruxos_posix_api/Cargo.toml | 1 + api/ruxos_posix_api/src/imp/fs.rs | 122 ++++++++++++--- api/ruxos_posix_api/src/imp/getrandom.rs | 179 +++++++++++++++++++++++ api/ruxos_posix_api/src/imp/mod.rs | 1 + api/ruxos_posix_api/src/lib.rs | 5 +- modules/ruxfs/src/fops.rs | 7 +- platforms/aarch64-qemu-virt.toml | 4 +- platforms/riscv64-qemu-virt.toml | 3 +- platforms/x86_64-qemu-q35.toml | 4 +- scripts/make/qemu.mk | 2 +- ulib/ruxlibc/Cargo.toml | 2 +- ulib/ruxlibc/include/sys/random.h | 19 +++ ulib/ruxlibc/src/lib.rs | 2 +- ulib/ruxlibc/src/rand.rs | 144 +++--------------- ulib/ruxmusl/src/aarch64/mod.rs | 19 +++ ulib/ruxmusl/src/aarch64/syscall_id.rs | 5 + ulib/ruxmusl/src/x86_64/mod.rs | 30 ++++ ulib/ruxmusl/src/x86_64/syscall_id.rs | 11 ++ 18 files changed, 399 insertions(+), 161 deletions(-) create mode 100644 api/ruxos_posix_api/src/imp/getrandom.rs create mode 100644 ulib/ruxlibc/include/sys/random.h diff --git a/api/ruxos_posix_api/Cargo.toml b/api/ruxos_posix_api/Cargo.toml index ed00a274a..aec121a60 100644 --- a/api/ruxos_posix_api/Cargo.toml +++ b/api/ruxos_posix_api/Cargo.toml @@ -30,6 +30,7 @@ epoll = ["fd"] poll = ["fd"] tls = ["ruxfeat/tls"] irq = ["ruxfeat/irq"] +random-hw = [] musl = ["ruxhal/musl", "ruxruntime/musl", "axalloc/slab", "ruxtask/musl"] diff --git a/api/ruxos_posix_api/src/imp/fs.rs b/api/ruxos_posix_api/src/imp/fs.rs index 789de93db..65a539467 100644 --- a/api/ruxos_posix_api/src/imp/fs.rs +++ b/api/ruxos_posix_api/src/imp/fs.rs @@ -8,7 +8,7 @@ */ use alloc::sync::Arc; -use core::ffi::{c_char, c_int, c_long}; +use core::ffi::{c_char, c_int, c_long, c_void}; use axerrno::{LinuxError, LinuxResult}; use axio::{PollState, SeekFrom}; @@ -118,7 +118,21 @@ impl FileLike for Directory { } fn stat(&self) -> LinuxResult { - Err(LinuxError::EACCES) + let metadata = self.inner.lock().get_attr()?; + let ty = metadata.file_type() as u8; + let perm = metadata.perm().bits() as u32; + let st_mode = ((ty as u32) << 12) | perm; + Ok(ctypes::stat { + st_ino: 1, + st_nlink: 1, + st_mode, + st_uid: 1000, + st_gid: 1000, + st_size: metadata.size() as _, + st_blocks: metadata.blocks() as _, + st_blksize: 512, + ..Default::default() + }) } fn into_any(self: Arc) -> Arc { @@ -179,18 +193,31 @@ pub fn sys_open(filename: *const c_char, flags: c_int, mode: ctypes::mode_t) -> } /// Open a file under a specific dir -/// -/// TODO: Currently only support openat root directory -pub fn sys_openat(_fd: usize, path: *const c_char, flags: c_int, mode: ctypes::mode_t) -> c_int { +pub fn sys_openat(fd: usize, path: *const c_char, flags: c_int, mode: ctypes::mode_t) -> c_int { let path = char_ptr_to_str(path); - debug!("sys_openat <= {:?}, {:#o} {:#o}", path, flags, mode); + let fd: c_int = fd as c_int; + debug!("sys_openat <= {}, {:?}, {:#o} {:#o}", fd, path, flags, mode); syscall_body!(sys_openat, { let options = flags_to_options(flags, mode); if (flags as u32) & ctypes::O_DIRECTORY != 0 { - let dir = ruxfs::fops::Directory::open_dir(path?, &options)?; + let dir = if fd == ctypes::AT_FDCWD { + ruxfs::fops::Directory::open_dir(path?, &options)? + } else { + Directory::from_fd(fd)? + .inner + .lock() + .open_dir_at(path?, &options)? + }; Directory::new(dir).add_to_fd_table() } else { - let file = ruxfs::fops::File::open(path?, &options)?; + let file = if fd == ctypes::AT_FDCWD { + ruxfs::fops::File::open(path?, &options)? + } else { + Directory::from_fd(fd)? + .inner + .lock() + .open_file_at(path?, &options)? + }; File::new(file).add_to_fd_table() } }) @@ -491,6 +518,7 @@ pub fn sys_fchownat( } /// read value of a symbolic link relative to directory file descriptor +/// TODO: currently only support symlink, so return EINVAL anyway pub fn sys_readlinkat( fd: c_int, pathname: *const c_char, @@ -499,23 +527,11 @@ pub fn sys_readlinkat( ) -> usize { let path = char_ptr_to_str(pathname); debug!( - "sys_readlinkat <= path = {:?}, fd = {:}, bufsize = {:}", - path, fd, bufsize + "sys_readlinkat <= path = {:?}, fd = {:}, buf = {:p}, bufsize = {:}", + path, fd, buf, bufsize ); syscall_body!(sys_readlinkat, { - let mut options = OpenOptions::new(); - options.read(true); - let dst = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, bufsize as _) }; - // if fd == AT_FDCWD then readat the relative path - if fd == ctypes::AT_FDCWD as c_int { - let file = ruxfs::fops::File::open(path?, &options)?; - let file = File::new(file); - Ok(file.read(dst)?) - } else { - let dir = Directory::from_fd(fd)?; - let mut file = dir.inner.lock().open_file_at(path?, &options)?; - Ok(file.read(dst)?) - } + Err::(LinuxError::EINVAL) }) } @@ -572,3 +588,63 @@ pub unsafe fn sys_getdents64( Ok(n * 280) }) } + +/// Read data from the file indicated by `fd`, starting at the position given by `offset`. +/// +/// Return the read size if success. +pub fn sys_pread( + fd: c_int, + buf: *mut c_void, + count: usize, + offset: ctypes::off_t, +) -> ctypes::ssize_t { + debug!( + "sys_pread <= fd: {} buf: {:#x} count: {} offset: {}", + fd, buf as usize, count, offset + ); + syscall_body!(sys_pread, { + if buf.is_null() { + return Err(LinuxError::EFAULT); + } + let dst = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, count) }; + #[cfg(feature = "fd")] + { + Ok(File::from_fd(fd)?.inner.lock().read_at(offset as _, dst)?) + } + #[cfg(not(feature = "fd"))] + match fd { + 0 => Ok(super::stdio::stdin().read(dst)? as ctypes::ssize_t), + 1 | 2 => Err(LinuxError::EPERM), + _ => Err(LinuxError::EBADF), + } + }) +} + +/// Reads `iocnt` buffers from the file associated with the file descriptor `fd` into the +/// buffers described by `iov`, starting at the position given by `offset` +pub unsafe fn sys_preadv( + fd: c_int, + iov: *const ctypes::iovec, + iocnt: c_int, + offset: ctypes::off_t, +) -> ctypes::ssize_t { + debug!( + "sys_preadv <= fd: {}, iocnt: {}, offset: {}", + fd, iocnt, offset + ); + syscall_body!(sys_preadv, { + if !(0..=1024).contains(&iocnt) { + return Err(LinuxError::EINVAL); + } + + let iovs = unsafe { core::slice::from_raw_parts(iov, iocnt as usize) }; + let mut ret = 0; + for iov in iovs.iter() { + if iov.iov_base.is_null() { + continue; + } + ret += sys_pread(fd, iov.iov_base, iov.iov_len, offset); + } + Ok(ret) + }) +} diff --git a/api/ruxos_posix_api/src/imp/getrandom.rs b/api/ruxos_posix_api/src/imp/getrandom.rs new file mode 100644 index 000000000..49186e8e3 --- /dev/null +++ b/api/ruxos_posix_api/src/imp/getrandom.rs @@ -0,0 +1,179 @@ +/* Copyright (c) [2023] [Syswonder Community] + * [Ruxos] is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/// If adding `random-hw` to features, rand()/random() will try to use CPU instruction to generate the random. +/// If CPU doesn't support instructions for random Generation, rand()/random() will return persudo random using LCG algorithm instead; +/// Without feature `random-hw`, rand()/random() will simply return 64-bit persudo random generated from LCG algorithm by default. +/// For x86_64, intel's CPU support `rdrand` instruction since IvyBridge, AMD's CPU support `rdrand` since Ryzen. +/// For aarch64, resigter `rndr` is supported for part of CPU core since ARMv8.5. For more information, you can read: https://developer.arm.com/documentation/ddi0601/2023-06/AArch64-Registers/RNDR--Random-Number?lang=en +/// We can determine whether the CPU supports this instruction by CPUID(x86_64) or ID_AA64ISAR0_EL1(aarch), which is implement in function `has_rdrand()`. +/// As of now, riscv64 does not support generating random numbers through instructions. +use core::ffi::{c_int, c_long, c_uint, c_void}; + +use core::sync::atomic::{AtomicU64, Ordering::SeqCst}; + +use crate::ctypes::{size_t, ssize_t}; + +use axerrno::LinuxError; + +static SEED: AtomicU64 = AtomicU64::new(0xae_f3); + +/// Returns a 32-bit unsigned pseudo random interger using LCG. +fn rand_lcg32() -> u32 { + let new_seed = SEED + .load(SeqCst) + .wrapping_mul(6364136223846793005) + .wrapping_add(1); + SEED.store(new_seed, SeqCst); + (new_seed >> 33) as u32 +} + +/// Returns a 64-bit unsigned pseudo random interger using LCG. +fn random_lcg64() -> u64 { + let new_seed = SEED + .load(SeqCst) + .wrapping_mul(6364136223846793005) + .wrapping_add(1); + SEED.store(new_seed, SeqCst); + new_seed >> 1 +} + +/// Sets the seed for the random number generator implemented by LCG. +fn srand_lcg(seed: u64) { + SEED.store(seed - 1, SeqCst); +} + +/// Checking if the CPU core is compatible with hardware random number instructions. +#[cfg(feature = "random-hw")] +fn has_rdrand() -> bool { + #[cfg(target_arch = "x86_64")] + { + let mut ecx: u32; + unsafe { + core::arch::asm!( + "mov eax, 1", + "cpuid", + out("ecx") ecx + ) + } + ecx & (1 << 30) != 0 + } + #[cfg(target_arch = "aarch64")] + { + let mut id_aa64_isar0_el1: u64; + unsafe { + core::arch::asm!( + "mrs {},ID_AA64ISAR0_EL1", + out(reg) id_aa64_isar0_el1 + ) + } + id_aa64_isar0_el1 & (0b1111 << 60) == 0b0001 << 60 + } + #[cfg(target_arch = "riscv64")] + { + false + } +} + +/// Return 64-bit unsigned random interger using cpu instruction +#[cfg(feature = "random-hw")] +fn random_hw() -> u64 { + let mut _random: u64; + + #[cfg(target_arch = "x86_64")] + { + unsafe { + core::arch::asm! { + "rdrand {0:r}", + out(reg) _random + } + } + _random + } + + #[cfg(target_arch = "aarch64")] + { + unsafe { + core::arch::asm! { + "mrs {}, s3_3_c2_c4_0", // s3_3_c2_c4_0 is register `rndr` + out(reg) _random + } + } + _random + } + + #[cfg(target_arch = "riscv64")] + { + panic!("riscv64 has no rdrand instructions") + } +} + +/// Sets the seed for the 32-bit random number generator based on LCG. +#[no_mangle] +pub unsafe extern "C" fn sys_srand(_seed: c_uint) { + srand_lcg(_seed as u64); +} + +/// Returns a 32-bit unsigned random integer +#[no_mangle] +pub unsafe extern "C" fn sys_rand() -> c_int { + #[cfg(feature = "random-hw")] + { + match has_rdrand() { + true => (random_hw() >> 33) as c_int, + false => rand_lcg32() as c_int, + } + } + #[cfg(not(feature = "random-hw"))] + { + rand_lcg32() as c_int + } +} + +/// Returns a 64-bit unsigned random integer +#[no_mangle] +pub unsafe extern "C" fn sys_random() -> c_long { + #[cfg(feature = "random-hw")] + { + match has_rdrand() { + true => (random_hw() >> 1) as c_long, + false => random_lcg64() as c_long, + } + } + #[cfg(not(feature = "random-hw"))] + { + random_lcg64() as c_long + } +} + +/// Fills the buffer pointed to by buf with up to buflen random bytes. +pub unsafe extern "C" fn sys_getrandom(buf: *mut c_void, buflen: size_t, flags: c_int) -> ssize_t { + debug!( + "sys_getrandom <= buf: {:?}, buflen: {}, flags: {}", + buf, buflen, flags + ); + syscall_body!(sys_getrandom, { + if buf.is_null() { + return Err(LinuxError::EFAULT); + } + if flags != 0 { + return Err(LinuxError::EINVAL); + } + // fill the buffer 8 bytes at a time first, then fill the remaining bytes + let buflen_mod = buflen % (core::mem::size_of::() / core::mem::size_of::()); + let buflen_div = buflen / (core::mem::size_of::() / core::mem::size_of::()); + for i in 0..buflen_div { + *((buf as *mut u8 as *mut i64).add(i)) = sys_random() as i64; + } + for i in 0..buflen_mod { + *((buf as *mut u8).add(buflen - buflen_mod + i)) = sys_rand() as u8; + } + Ok(buflen as ssize_t) + }) +} diff --git a/api/ruxos_posix_api/src/imp/mod.rs b/api/ruxos_posix_api/src/imp/mod.rs index 4ac260a1f..0198abf50 100644 --- a/api/ruxos_posix_api/src/imp/mod.rs +++ b/api/ruxos_posix_api/src/imp/mod.rs @@ -9,6 +9,7 @@ mod stdio; +pub mod getrandom; pub mod io; pub mod prctl; pub mod resources; diff --git a/api/ruxos_posix_api/src/lib.rs b/api/ruxos_posix_api/src/lib.rs index 130006390..6cac87f24 100644 --- a/api/ruxos_posix_api/src/lib.rs +++ b/api/ruxos_posix_api/src/lib.rs @@ -45,6 +45,7 @@ pub mod config { #[allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals, clippy::upper_case_acronyms, missing_docs)] pub mod ctypes; +pub use imp::getrandom::{sys_getrandom, sys_rand, sys_random, sys_srand}; pub use imp::io::{sys_read, sys_readv, sys_write, sys_writev}; pub use imp::prctl::{sys_arch_prctl, sys_prctl}; pub use imp::resources::{sys_getrlimit, sys_prlimit64, sys_setrlimit}; @@ -62,8 +63,8 @@ pub use imp::fd_ops::{sys_close, sys_dup, sys_dup2, sys_fcntl}; #[cfg(feature = "fs")] pub use imp::fs::{ sys_fchownat, sys_fdatasync, sys_fstat, sys_fsync, sys_getcwd, sys_getdents64, sys_lseek, - sys_lstat, sys_mkdir, sys_mkdirat, sys_newfstatat, sys_open, sys_openat, sys_readlinkat, - sys_rename, sys_renameat, sys_rmdir, sys_stat, sys_unlink, sys_unlinkat, + sys_lstat, sys_mkdir, sys_mkdirat, sys_newfstatat, sys_open, sys_openat, sys_pread, sys_preadv, + sys_readlinkat, sys_rename, sys_renameat, sys_rmdir, sys_stat, sys_unlink, sys_unlinkat, }; #[cfg(feature = "epoll")] pub use imp::io_mpx::{sys_epoll_create, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait}; diff --git a/modules/ruxfs/src/fops.rs b/modules/ruxfs/src/fops.rs index dfc8b46fc..c71f49054 100644 --- a/modules/ruxfs/src/fops.rs +++ b/modules/ruxfs/src/fops.rs @@ -273,7 +273,7 @@ impl Directory { node.open()?; Ok(Self { - node: WithCap::new(node, access_cap), + node: WithCap::new(node, access_cap | Cap::EXECUTE), entry_idx: 0, }) } @@ -345,6 +345,11 @@ impl Directory { pub fn rename(&self, old: &str, new: &str) -> AxResult { crate::root::rename(old, new) } + + /// Gets the file attributes. + pub fn get_attr(&self) -> AxResult { + self.node.access(Cap::empty())?.get_attr() + } } impl Drop for File { diff --git a/platforms/aarch64-qemu-virt.toml b/platforms/aarch64-qemu-virt.toml index 2dbebd790..7ff8fbb0d 100644 --- a/platforms/aarch64-qemu-virt.toml +++ b/platforms/aarch64-qemu-virt.toml @@ -8,9 +8,9 @@ family = "aarch64-qemu-virt" # Base address of the whole physical memory. phys-memory-base = "0x4000_0000" # Size of the whole physical memory. -phys-memory-size = "0x800_0000" # 128M +# phys-memory-size = "0x800_0000" # 128M # phys-memory-size = "0x1000_0000" # 1G -# phys-memory-size = "0x8000_0000" # 2G +phys-memory-size = "0x8000_0000" # 2G # phys-memory-size = "0xc000_0000" # 3G # phys-memory-size = "0x1_0000_0000" # 4G # phys-memory-size = "0x1_8000_0000" # 6G diff --git a/platforms/riscv64-qemu-virt.toml b/platforms/riscv64-qemu-virt.toml index 8c1051c89..2c0e69ce0 100644 --- a/platforms/riscv64-qemu-virt.toml +++ b/platforms/riscv64-qemu-virt.toml @@ -8,7 +8,8 @@ family = "riscv64-qemu-virt" # Base address of the whole physical memory. phys-memory-base = "0x8000_0000" # Size of the whole physical memory. -phys-memory-size = "0x800_0000" # 128M +# phys-memory-size = "0x800_0000" # 128M +phys-memory-size = "0x8000_0000" # 2G # Base physical address of the kernel image. kernel-base-paddr = "0x8020_0000" # Base virtual address of the kernel image. diff --git a/platforms/x86_64-qemu-q35.toml b/platforms/x86_64-qemu-q35.toml index 7cff45e77..78fa13af5 100644 --- a/platforms/x86_64-qemu-q35.toml +++ b/platforms/x86_64-qemu-q35.toml @@ -8,8 +8,8 @@ family = "x86-pc" # Base address of the whole physical memory. phys-memory-base = "0" # Size of the whole physical memory. -phys-memory-size = "0x800_0000" # 128M -# phys-memory-size = "0x8000_0000" # 2G +# phys-memory-size = "0x800_0000" # 128M +phys-memory-size = "0x8000_0000" # 2G # Base physical address of the kernel image. kernel-base-paddr = "0x20_0000" # Base virtual address of the kernel image. diff --git a/scripts/make/qemu.mk b/scripts/make/qemu.mk index 336b943f0..5a6340438 100644 --- a/scripts/make/qemu.mk +++ b/scripts/make/qemu.mk @@ -29,7 +29,7 @@ qemu_args-aarch64 := \ -machine virt \ -kernel $(OUT_BIN) -qemu_args-y := -m 128M -smp $(SMP) $(qemu_args-$(ARCH)) \ +qemu_args-y := -m 2G -smp $(SMP) $(qemu_args-$(ARCH)) \ -append ";$(ARGS);$(ENVS)" qemu_args-$(BLK) += \ diff --git a/ulib/ruxlibc/Cargo.toml b/ulib/ruxlibc/Cargo.toml index e32edb2cd..870bb3d38 100644 --- a/ulib/ruxlibc/Cargo.toml +++ b/ulib/ruxlibc/Cargo.toml @@ -49,7 +49,7 @@ pipe = ["ruxos_posix_api/pipe"] select = ["ruxos_posix_api/select"] poll = ["ruxos_posix_api/poll"] epoll = ["ruxos_posix_api/epoll"] -random-hw = [] +random-hw = ["ruxos_posix_api/random-hw"] [dependencies] ruxfeat = { path = "../../api/ruxfeat" } diff --git a/ulib/ruxlibc/include/sys/random.h b/ulib/ruxlibc/include/sys/random.h new file mode 100644 index 000000000..fa2b72542 --- /dev/null +++ b/ulib/ruxlibc/include/sys/random.h @@ -0,0 +1,19 @@ +#ifndef _SYS_RANDOM_H +#define _SYS_RANDOM_H +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_size_t +#define __NEED_ssize_t + +#define GRND_NONBLOCK 0x0001 +#define GRND_RANDOM 0x0002 +#define GRND_INSECURE 0x0004 + +ssize_t getrandom(void *, size_t, unsigned); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ulib/ruxlibc/src/lib.rs b/ulib/ruxlibc/src/lib.rs index bed472d52..3ecaa4913 100644 --- a/ulib/ruxlibc/src/lib.rs +++ b/ulib/ruxlibc/src/lib.rs @@ -97,7 +97,7 @@ pub use self::io::{read, writev}; pub use self::errno::strerror; pub use self::mktime::mktime; -pub use self::rand::{rand, random, srand}; +pub use self::rand::{getrandom, rand, random, srand}; pub use self::resource::{getrlimit, setrlimit}; pub use self::setjmp::{longjmp, setjmp}; pub use self::string::{strlen, strnlen}; diff --git a/ulib/ruxlibc/src/rand.rs b/ulib/ruxlibc/src/rand.rs index a1cca9c6a..07eefdd60 100644 --- a/ulib/ruxlibc/src/rand.rs +++ b/ulib/ruxlibc/src/rand.rs @@ -7,143 +7,33 @@ * See the Mulan PSL v2 for more details. */ -/// If adding `random-hw` to features, rand()/random() will try to use CPU instruction to generate the random. -/// If CPU doesn't support instructions for random Generation, rand()/random() will return persudo random using LCG algorithm instead; -/// Without feature `random-hw`, rand()/random() will simply return 64-bit persudo random generated from LCG algorithm by default. -/// For x86_64, intel's CPU support `rdrand` instruction since IvyBridge, AMD's CPU support `rdrand` since Ryzen. -/// For aarch64, resigter `rndr` is supported for part of CPU core since ARMv8.5. For more information, you can read: https://developer.arm.com/documentation/ddi0601/2023-06/AArch64-Registers/RNDR--Random-Number?lang=en -/// We can determine whether the CPU supports this instruction by CPUID(x86_64) or ID_AA64ISAR0_EL1(aarch), which is implement in function `has_rdrand()`. -/// As of now, riscv64 does not support generating random numbers through instructions. -use core::ffi::{c_int, c_long, c_uint}; +use crate::ctypes::size_t; +use core::ffi::{c_int, c_long, c_uint, c_void}; -use core::sync::atomic::{AtomicU64, Ordering::SeqCst}; +use ruxos_posix_api::{sys_getrandom, sys_rand, sys_random, sys_srand}; -static SEED: AtomicU64 = AtomicU64::new(0xae_f3); +use crate::utils::e; -/// Returns a 32-bit unsigned pseudo random interger using LCG. -fn rand_lcg32() -> u32 { - let new_seed = SEED - .load(SeqCst) - .wrapping_mul(6364136223846793005) - .wrapping_add(1); - SEED.store(new_seed, SeqCst); - (new_seed >> 33) as u32 -} - -/// Returns a 64-bit unsigned pseudo random interger using LCG. -fn random_lcg64() -> u64 { - let new_seed = SEED - .load(SeqCst) - .wrapping_mul(6364136223846793005) - .wrapping_add(1); - SEED.store(new_seed, SeqCst); - new_seed >> 1 -} - -/// Sets the seed for the random number generator implemented by LCG. -fn srand_lcg(seed: u64) { - SEED.store(seed - 1, SeqCst); -} - -/// Checking if the CPU core is compatible with hardware random number instructions. -#[cfg(feature = "random-hw")] -fn has_rdrand() -> bool { - #[cfg(target_arch = "x86_64")] - { - let mut ecx: u32; - unsafe { - core::arch::asm!( - "mov eax, 1", - "cpuid", - out("ecx") ecx - ) - } - ecx & (1 << 30) != 0 - } - #[cfg(target_arch = "aarch64")] - { - let mut id_aa64_isar0_el1: u64; - unsafe { - core::arch::asm!( - "mrs {},ID_AA64ISAR0_EL1", - out(reg) id_aa64_isar0_el1 - ) - } - id_aa64_isar0_el1 & (0b1111 << 60) == 0b0001 << 60 - } - #[cfg(target_arch = "riscv64")] - { - false - } -} - -/// Return 64-bit unsigned random interger using cpu instruction -#[cfg(feature = "random-hw")] -fn random_hw() -> u64 { - let mut _random: u64; - - #[cfg(target_arch = "x86_64")] - { - unsafe { - core::arch::asm! { - "rdrand {0:r}", - out(reg) _random - } - } - _random - } - - #[cfg(target_arch = "aarch64")] - { - unsafe { - core::arch::asm! { - "mrs {}, s3_3_c2_c4_0", // s3_3_c2_c4_0 is register `rndr` - out(reg) _random - } - } - _random - } - - #[cfg(target_arch = "riscv64")] - { - panic!("riscv64 has no rdrand instructions") - } -} - -/// Sets the seed for the 32-bit random number generator based on LCG. +/// srand #[no_mangle] -pub unsafe extern "C" fn srand(_seed: c_uint) { - srand_lcg(_seed as u64); +pub unsafe extern "C" fn srand(seed: c_uint) { + sys_srand(seed); } -/// Returns a 32-bit unsigned random integer +/// rand #[no_mangle] pub unsafe extern "C" fn rand() -> c_int { - #[cfg(feature = "random-hw")] - { - match has_rdrand() { - true => (random_hw() >> 33) as c_int, - false => rand_lcg32() as c_int, - } - } - #[cfg(not(feature = "random-hw"))] - { - rand_lcg32() as c_int - } + e(sys_rand() as c_int) } -/// Returns a 64-bit unsigned random integer +/// random #[no_mangle] pub unsafe extern "C" fn random() -> c_long { - #[cfg(feature = "random-hw")] - { - match has_rdrand() { - true => (random_hw() >> 1) as c_long, - false => random_lcg64() as c_long, - } - } - #[cfg(not(feature = "random-hw"))] - { - random_lcg64() as c_long - } + e(sys_random().try_into().unwrap()) as _ +} + +/// Get random +#[no_mangle] +pub unsafe extern "C" fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_int) -> size_t { + e(sys_getrandom(buf, buflen, flags).try_into().unwrap()) as _ } diff --git a/ulib/ruxmusl/src/aarch64/mod.rs b/ulib/ruxmusl/src/aarch64/mod.rs index ca04bb619..679a5381a 100644 --- a/ulib/ruxmusl/src/aarch64/mod.rs +++ b/ulib/ruxmusl/src/aarch64/mod.rs @@ -119,6 +119,20 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[1] as *const ctypes::iovec, args[2] as c_int, ) as _, + #[cfg(feature = "fs")] + SyscallId::PREAD64 => ruxos_posix_api::sys_pread( + args[0] as c_int, + args[1] as *mut core::ffi::c_void, + args[2] as ctypes::size_t, + args[3] as ctypes::off_t, + ) as _, + #[cfg(feature = "fs")] + SyscallId::PREADV => ruxos_posix_api::sys_preadv( + args[0] as c_int, + args[1] as *const ctypes::iovec, + args[2] as c_int, + args[3] as ctypes::off_t, + ) as _, #[cfg(feature = "select")] SyscallId::PSELECT6 => ruxos_posix_api::sys_pselect6( args[0] as c_int, @@ -349,6 +363,11 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[2] as *const ctypes::rlimit, args[3] as *mut ctypes::rlimit, ) as _, + SyscallId::GETRANDOM => ruxos_posix_api::sys_getrandom( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + args[2] as c_int, + ) as _, } } } diff --git a/ulib/ruxmusl/src/aarch64/syscall_id.rs b/ulib/ruxmusl/src/aarch64/syscall_id.rs index ed5087e4b..efbf20336 100644 --- a/ulib/ruxmusl/src/aarch64/syscall_id.rs +++ b/ulib/ruxmusl/src/aarch64/syscall_id.rs @@ -47,6 +47,10 @@ pub enum SyscallId { READV = 65, #[cfg(feature = "fd")] WRITEV = 66, + #[cfg(feature = "fs")] + PREAD64 = 67, + #[cfg(feature = "fs")] + PREADV = 69, #[cfg(feature = "select")] PSELECT6 = 72, #[cfg(feature = "poll")] @@ -122,4 +126,5 @@ pub enum SyscallId { #[cfg(feature = "alloc")] MPROTECT = 226, PRLIMIT64 = 261, + GETRANDOM = 278, } diff --git a/ulib/ruxmusl/src/x86_64/mod.rs b/ulib/ruxmusl/src/x86_64/mod.rs index 74a4284a8..9b4fc85e6 100644 --- a/ulib/ruxmusl/src/x86_64/mod.rs +++ b/ulib/ruxmusl/src/x86_64/mod.rs @@ -103,6 +103,14 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { #[cfg(feature = "fd")] SyscallId::IOCTL => ruxos_posix_api::sys_ioctl(args[0] as c_int, args[1], args[2]) as _, + #[cfg(feature = "fs")] + SyscallId::PREAD64 => ruxos_posix_api::sys_pread( + args[0] as c_int, + args[1] as *mut c_void, + args[2] as ctypes::size_t, + args[3] as ctypes::off_t, + ) as _, + #[cfg(feature = "fd")] SyscallId::READV => ruxos_posix_api::sys_readv( args[0] as c_int, @@ -442,6 +450,14 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[3] as *const core::ffi::c_char, ) as _, + #[cfg(feature = "fs")] + SyscallId::READLINKAT => ruxos_posix_api::sys_readlinkat( + args[0] as c_int, + args[1] as *const core::ffi::c_char, + args[2] as *mut core::ffi::c_char, + args[3], + ) as _, + #[cfg(feature = "select")] SyscallId::PSELECT6 => ruxos_posix_api::sys_pselect6( args[0] as c_int, @@ -485,12 +501,26 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[1] as c_int, ) as _, + #[cfg(feature = "fs")] + SyscallId::PREADV => ruxos_posix_api::sys_preadv( + args[0] as c_int, + args[1] as *const ctypes::iovec, + args[2] as c_int, + args[3] as ctypes::off_t, + ) as _, + SyscallId::PRLIMIT64 => ruxos_posix_api::sys_prlimit64( args[0] as ctypes::pid_t, args[1] as c_int, args[2] as *const ctypes::rlimit, args[3] as *mut ctypes::rlimit, ) as _, + + SyscallId::GETRANDOM => ruxos_posix_api::sys_getrandom( + args[0] as *mut c_void, + args[1] as ctypes::size_t, + args[2] as c_int, + ) as _, } } } diff --git a/ulib/ruxmusl/src/x86_64/syscall_id.rs b/ulib/ruxmusl/src/x86_64/syscall_id.rs index 3db7a540f..7992518ad 100644 --- a/ulib/ruxmusl/src/x86_64/syscall_id.rs +++ b/ulib/ruxmusl/src/x86_64/syscall_id.rs @@ -50,6 +50,9 @@ pub enum SyscallId { #[cfg(feature = "fd")] IOCTL = 16, + #[cfg(feature = "fs")] + PREAD64 = 17, + #[cfg(feature = "fd")] READV = 19, @@ -207,6 +210,9 @@ pub enum SyscallId { #[cfg(feature = "fs")] RENAMEAT = 264, + #[cfg(feature = "fs")] + READLINKAT = 267, + #[cfg(feature = "select")] PSELECT6 = 270, @@ -225,5 +231,10 @@ pub enum SyscallId { #[cfg(feature = "pipe")] PIPE2 = 293, + #[cfg(feature = "fs")] + PREADV = 295, + PRLIMIT64 = 302, + + GETRANDOM = 318, }