Skip to content

Commit

Permalink
add and modify some syscalls and pass the tensorflow test; extend memory
Browse files Browse the repository at this point in the history
  • Loading branch information
AuYang261 committed Mar 15, 2024
1 parent e95f63b commit 94efd75
Show file tree
Hide file tree
Showing 24 changed files with 438 additions and 167 deletions.
1 change: 1 addition & 0 deletions api/ruxos_posix_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand Down
1 change: 1 addition & 0 deletions api/ruxos_posix_api/src/imp/fd_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub trait FileLike: Send + Sync {
fn into_any(self: Arc<Self>) -> Arc<dyn core::any::Any + Send + Sync>;
fn poll(&self) -> LinuxResult<PollState>;
fn set_nonblocking(&self, nonblocking: bool) -> LinuxResult;
fn pread(&self, buf: &mut [u8], offset: u64) -> LinuxResult<usize>;
}

lazy_static::lazy_static! {
Expand Down
81 changes: 59 additions & 22 deletions api/ruxos_posix_api/src/imp/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ impl FileLike for File {
fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult {
Ok(())
}

fn pread(&self, buf: &mut [u8], offset: u64) -> LinuxResult<usize> {
Ok(self.inner.lock().pread(buf, offset)?)
}
}

pub struct Directory {
Expand Down Expand Up @@ -118,7 +122,21 @@ impl FileLike for Directory {
}

fn stat(&self) -> LinuxResult<ctypes::stat> {
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<Self>) -> Arc<dyn core::any::Any + Send + Sync> {
Expand All @@ -135,6 +153,10 @@ impl FileLike for Directory {
fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult {
Ok(())
}

fn pread(&self, _buf: &mut [u8], _offset: u64) -> LinuxResult<usize> {
Err(LinuxError::EACCES)
}
}

/// Convert open flags to [`OpenOptions`].
Expand Down Expand Up @@ -179,18 +201,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()
}
})
Expand Down Expand Up @@ -491,6 +526,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,
Expand All @@ -499,23 +535,24 @@ 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::<usize, LinuxError>(LinuxError::EINVAL)
// 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)?)
// }
})
}

Expand Down
179 changes: 179 additions & 0 deletions api/ruxos_posix_api/src/imp/getrandom.rs
Original file line number Diff line number Diff line change
@@ -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 srand(_seed: c_uint) {
srand_lcg(_seed as u64);
}

/// Returns a 32-bit unsigned random integer
#[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
}
}

/// Returns a 64-bit unsigned random integer
#[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
}
}

/// 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::<i64>() / core::mem::size_of::<u8>());
let buflen_div = buflen / (core::mem::size_of::<i64>() / core::mem::size_of::<u8>());
for i in 0..buflen_div {
*((buf as *mut u8 as *mut i64).add(i)) = random() as i64;
}
for i in 0..buflen_mod {
*((buf as *mut u8).add(buflen - buflen_mod + i)) = rand() as u8;
}
Ok(buflen as ssize_t)
})
}
60 changes: 60 additions & 0 deletions api/ruxos_posix_api/src/imp/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,63 @@ pub unsafe fn sys_readv(fd: c_int, iov: *const ctypes::iovec, iocnt: c_int) -> c
Ok(ret)
})
}

/// 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(get_file_like(fd)?.pread(dst, offset as u64)? as ctypes::ssize_t)
}
#[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)
})
}
Loading

0 comments on commit 94efd75

Please sign in to comment.