From ec2bcc376801dbc8ab30e697b86c69b6b65e10b1 Mon Sep 17 00:00:00 2001 From: Yukiteru Lee Date: Fri, 7 Aug 2020 09:00:11 +0800 Subject: [PATCH 1/2] add sys_getrandom --- linux-syscall/src/lib.rs | 2 +- linux-syscall/src/misc.rs | 48 +++++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/linux-syscall/src/lib.rs b/linux-syscall/src/lib.rs index be72e1be0..9e37f6162 100644 --- a/linux-syscall/src/lib.rs +++ b/linux-syscall/src/lib.rs @@ -218,7 +218,7 @@ impl Syscall<'_> { Sys::MEMBARRIER => self.unimplemented("membarrier", Ok(0)), // Sys::PRLIMIT64 => self.sys_prlimit64(a0, a1, a2.into(), a3.into()), // Sys::REBOOT => self.sys_reboot(a0 as u32, a1 as u32, a2 as u32, a3.into()), - // Sys::GETRANDOM => self.sys_getrandom(a0.into(), a1 as usize, a2 as u32), + Sys::GETRANDOM => self.sys_getrandom(a0 as *mut u8, a1 as usize, a2 as u32), Sys::RT_SIGQUEUEINFO => self.unimplemented("rt_sigqueueinfo", Ok(0)), // kernel module diff --git a/linux-syscall/src/misc.rs b/linux-syscall/src/misc.rs index 9dd4e08f1..a226a1a50 100644 --- a/linux-syscall/src/misc.rs +++ b/linux-syscall/src/misc.rs @@ -1,11 +1,13 @@ +#![allow(missing_docs)] + use super::time::TimeSpec; use super::*; use bitflags::bitflags; +use kernel_hal::timer_now; +use core::slice::from_raw_parts_mut; impl Syscall<'_> { #[cfg(target_arch = "x86_64")] - /// set architecture-specific thread state - /// for x86_64 currently pub fn sys_arch_prctl(&mut self, code: i32, addr: usize) -> SysResult { const ARCH_SET_FS: i32 = 0x1002; match code { @@ -18,11 +20,10 @@ impl Syscall<'_> { } } - /// get name and information about current kernel pub fn sys_uname(&self, buf: UserOutPtr) -> SysResult { info!("uname: buf={:?}", buf); - let strings = ["Linux", "orz", "0.1.0", "1", "machine", "domain"]; + let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"]; for (i, &s) in strings.iter().enumerate() { const OFFSET: usize = 65; buf.add(i * OFFSET).write_cstring(s)?; @@ -30,12 +31,6 @@ impl Syscall<'_> { Ok(0) } - /// provides a method for waiting until a certain condition becomes true. - /// - `uaddr` - points to the futex word. - /// - `op` - the operation to perform on the futex - /// - `val` - a value whose meaning and purpose depends on op - /// - `timeout` - not support now - /// TODO: support timeout pub async fn sys_futex( &self, uaddr: usize, @@ -43,6 +38,13 @@ impl Syscall<'_> { val: i32, timeout: UserInPtr, ) -> SysResult { + bitflags! { + struct FutexFlags: u32 { + const WAIT = 0; + const WAKE = 1; + const PRIVATE = 0x80; + } + } let op = FutexFlags::from_bits_truncate(op); info!( "futex: uaddr: {:#x}, op: {:?}, val: {}, timeout_ptr: {:?}", @@ -72,18 +74,20 @@ impl Syscall<'_> { } } } -} -bitflags! { - /// for op argument in futex() - struct FutexFlags: u32 { - /// tests that the value at the futex word pointed - /// to by the address uaddr still contains the expected value val, - /// and if so, then sleeps waiting for a FUTEX_WAKE operation on the futex word. - const WAIT = 0; - /// wakes at most val of the waiters that are waiting on the futex word at the address uaddr. - const WAKE = 1; - /// can be employed with all futex operations, tells the kernel that the futex is process-private and not shared with another process - const PRIVATE = 0x80; + #[allow(unsafe_code)] + pub fn sys_getrandom(&mut self, buf: *mut u8, len: usize, _flag: u32) -> SysResult { + //info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag); + let slice = unsafe { from_raw_parts_mut(buf, len) }; + let mut i = 0; + for elm in slice { + // to prevent overflow + let time = timer_now(); + *elm = (i + time.as_nanos() as u8 as u16) as u8; + i += 1; + } + + Ok(len) } + } From feccc153dbf5a58c08a8484761b6777a15d30b9f Mon Sep 17 00:00:00 2001 From: Yukiteru Lee Date: Fri, 7 Aug 2020 09:00:29 +0800 Subject: [PATCH 2/2] add stdin without condvar --- linux-object/Cargo.toml | 1 + linux-object/src/fs/file.rs | 5 +- linux-object/src/fs/stdio.rs | 149 ++++++++++++++++++++--------------- linux-object/src/process.rs | 4 +- 4 files changed, 90 insertions(+), 69 deletions(-) diff --git a/linux-object/Cargo.toml b/linux-object/Cargo.toml index fc45abc2c..77122e6e9 100644 --- a/linux-object/Cargo.toml +++ b/linux-object/Cargo.toml @@ -15,6 +15,7 @@ hashbrown = "0.7" zircon-object = { path = "../zircon-object", features = ["elf"] } kernel-hal = { path = "../kernel-hal" } downcast-rs = { git = "https://github.com/rcore-os/downcast-rs", rev = "a632ce1", default-features = false } +lazy_static = { version = "1.4", features = ["spin_no_std"] } rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "e17b27b" } rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "e17b27b" } rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "e17b27b" } diff --git a/linux-object/src/fs/file.rs b/linux-object/src/fs/file.rs index 5c9fa9dfd..6c1ed314c 100644 --- a/linux-object/src/fs/file.rs +++ b/linux-object/src/fs/file.rs @@ -69,8 +69,9 @@ impl File { match self.inode.read_at(offset as usize, buf) { Ok(read_len) => return Ok(read_len), Err(FsError::Again) => { - //thread::yield_now(); - unimplemented!() + // thread::yield_now(); + // unimplemented!() + self.poll()?; } Err(err) => return Err(err.into()), } diff --git a/linux-object/src/fs/stdio.rs b/linux-object/src/fs/stdio.rs index 460de1084..14e21d29d 100644 --- a/linux-object/src/fs/stdio.rs +++ b/linux-object/src/fs/stdio.rs @@ -3,77 +3,96 @@ use super::ioctl::*; use core::any::Any; +use alloc::sync::Arc; use rcore_fs::vfs::*; -//use spin::Mutex; +use spin::Mutex; +use lazy_static::lazy_static; +use alloc::collections::VecDeque; -//#[derive(Default)] -//pub struct Stdin { -// buf: Mutex>, -// pub pushed: Condvar, -//} -// -//impl Stdin { -// pub fn push(&self, c: char) { -// self.buf.lock().push_back(c); -// self.pushed.notify_one(); -// } -// pub fn pop(&self) -> char { -// loop { -// let mut buf_lock = self.buf.lock(); -// match buf_lock.pop_front() { -// Some(c) => return c, -// None => { -// self.pushed.wait(buf_lock); -// } -// } -// } -// } -// pub fn can_read(&self) -> bool { -// return self.buf.lock().len() > 0; -// } -//} +lazy_static! { + pub static ref STDIN: Arc = Default::default(); + pub static ref STDOUT: Arc = Default::default(); +} + +#[derive(Default)] +pub struct Stdin { + buf: Mutex>, + // TODO: add Condvar + // pub pushed: Condvar, +} + +impl Stdin { + pub fn push(&self, c: char) { + self.buf.lock().push_back(c); + // self.pushed.notify_one(); + } + pub fn pop(&self) -> char { + loop { + let mut buf_lock = self.buf.lock(); + match buf_lock.pop_front() { + Some(c) => return c, + None => { + // self.pushed.wait(buf_lock); + } + } + } + } + pub fn can_read(&self) -> bool { + return self.buf.lock().len() > 0; + } +} #[derive(Default)] pub struct Stdout; -//impl INode for Stdin { -// fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { -// if self.can_read() { -// buf[0] = self.pop() as u8; -// Ok(1) -// } else { -// Err(FsError::Again) -// } -// } -// fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { -// unimplemented!() -// } -// fn poll(&self) -> Result { -// Ok(PollStatus { -// read: self.can_read(), -// write: false, -// error: false, -// }) -// } -// fn io_control(&self, cmd: u32, data: usize) -> Result<()> { -// match cmd as usize { -// TCGETS | TIOCGWINSZ | TIOCSPGRP => { -// // pretend to be tty -// Ok(()) -// } -// TIOCGPGRP => { -// // pretend to be have a tty process group -// // TODO: verify pointer -// unsafe { *(data as *mut u32) = 0 }; -// Ok(()) -// } -// _ => Err(FsError::NotSupported), -// } -// } -// fn as_any_ref(&self) -> &dyn Any { -// self -// } -//} +impl INode for Stdin { + fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { + /* + if offset != 0 { + unimplemented!() + } + */ + if self.can_read() { + buf[0] = self.pop() as u8; + Ok(1) + } else { + let mut buffer = [0; 255]; + let len = kernel_hal::serial_read(&mut buffer); + for c in &buffer[..len] { + self.push((*c).into()); + } + Err(FsError::Again) + } + } + fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { + unimplemented!() + } + fn poll(&self) -> Result { + Ok(PollStatus { + read: self.can_read(), + write: false, + error: false, + }) + } + fn io_control(&self, cmd: u32, data: usize) -> Result<()> { + match cmd as usize { + TCGETS | TIOCGWINSZ | TIOCSPGRP => { + // pretend to be tty + Ok(()) + } + TIOCGPGRP => { + // pretend to be have a tty process group + // TODO: verify pointer + unsafe { *(data as *mut u32) = 0 }; + Ok(()) + } + _ => Err(FsError::NotSupported), + } + } + fn as_any_ref(&self) -> &dyn Any { + self + } +} impl INode for Stdout { fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { diff --git a/linux-object/src/process.rs b/linux-object/src/process.rs index b59067e6b..eefabf46d 100644 --- a/linux-object/src/process.rs +++ b/linux-object/src/process.rs @@ -150,7 +150,7 @@ impl LinuxProcess { /// Create a new process. pub fn new(rootfs: Arc) -> Self { let stdin = File::new( - Arc::new(Stdout), // FIXME: stdin + STDIN.clone(), // FIXME: stdin OpenOptions { read: true, write: false, @@ -160,7 +160,7 @@ impl LinuxProcess { String::from("/dev/stdin"), ) as Arc; let stdout = File::new( - Arc::new(Stdout), // TODO: open from '/dev/stdout' + STDOUT.clone(), // TODO: open from '/dev/stdout' OpenOptions { read: false, write: true,