diff --git a/fs/memfs/src/block.rs b/fs/memfs/src/block.rs index e02dd6c..e3c9289 100644 --- a/fs/memfs/src/block.rs +++ b/fs/memfs/src/block.rs @@ -13,6 +13,9 @@ pub struct BlockRef<'a, A: BlockAllocator + Copy> { pub unsafe trait BlockAllocator { fn alloc(&self) -> *mut u8; + /// # Safety + /// + /// Unsafe: accepts arbitrary block addresses unsafe fn dealloc(&self, block: *mut u8); } @@ -42,6 +45,9 @@ impl<'a, A: BlockAllocator + Copy> BlockRef<'a, A> { } } + /// # Safety + /// + /// Unsafe: does not perform checks on `data` pointer pub unsafe fn from_raw(alloc: A, data: *mut u8) -> Self { Self { inner: Some(&mut *(data as *mut _)), diff --git a/fs/memfs/src/file.rs b/fs/memfs/src/file.rs index b2d59b7..2348625 100644 --- a/fs/memfs/src/file.rs +++ b/fs/memfs/src/file.rs @@ -48,7 +48,7 @@ impl<'a, A: BlockAllocator + Copy + 'static> VnodeImpl for FileInode<'a, A> { Ok(self.data.size()) } - fn stat(&mut self, node: VnodeRef, stat: &mut Stat) -> Result<(), Errno> { + fn stat(&mut self, _node: VnodeRef, stat: &mut Stat) -> Result<(), Errno> { stat.size = self.data.size() as u64; stat.blksize = 4096; stat.mode = 0o755; diff --git a/fs/memfs/src/lib.rs b/fs/memfs/src/lib.rs index e4a3462..22ad694 100644 --- a/fs/memfs/src/lib.rs +++ b/fs/memfs/src/lib.rs @@ -49,6 +49,9 @@ impl Filesystem for Ramfs { } impl Ramfs { + /// # Safety + /// + /// Unsafe: accepts arbitrary `base` and `size` parameters pub unsafe fn open(base: *const u8, size: usize, alloc: A) -> Result, Errno> { let res = Rc::new(Self { root: RefCell::new(None), @@ -90,8 +93,7 @@ impl Ramfs { return Err(Errno::DoesNotExist); } // TODO file modes - let node = at.create(element, FileMode::default_dir(), VnodeKind::Directory)?; - node + at.create(element, FileMode::default_dir(), VnodeKind::Directory)? } }; diff --git a/fs/vfs/src/fs.rs b/fs/vfs/src/fs.rs index 8708706..0496601 100644 --- a/fs/vfs/src/fs.rs +++ b/fs/vfs/src/fs.rs @@ -11,5 +11,5 @@ pub trait Filesystem { /// Returns storage device of the filesystem (if any) fn dev(self: Rc) -> Option<&'static dyn BlockDevice>; /// Returns filesystem's private data struct (if any) - fn data<'a>(&'a self) -> Option>; + fn data(&self) -> Option>; } diff --git a/fs/vfs/src/node.rs b/fs/vfs/src/node.rs index 352eb97..8782ff7 100644 --- a/fs/vfs/src/node.rs +++ b/fs/vfs/src/node.rs @@ -102,7 +102,7 @@ impl Vnode { }) } - pub fn name<'a>(&'a self) -> &'a str { + pub fn name(&self) -> &str { &self.name } diff --git a/init/src/main.rs b/init/src/main.rs index 0035ef2..c90312c 100644 --- a/init/src/main.rs +++ b/init/src/main.rs @@ -5,54 +5,34 @@ #[macro_use] extern crate libusr; -use libusr::io; -use libusr::sys::{OpenFlags, AT_FDCWD}; - #[no_mangle] fn main() -> i32 { - loop { - let pid = unsafe { libusr::sys::sys_fork() }; + let mut buf = [0; 128]; - if pid == 0 { - trace!("Hello!"); - unsafe { - libusr::sys::sys_ex_nanosleep(3_000_000_000, core::ptr::null_mut()); + print!("\x1B[2J\x1B[1;1H"); + println!("Hello!"); + + loop { + print!("> "); + + let count = unsafe { + libusr::sys::sys_read(0, buf.as_mut_ptr(), buf.len()) + }; + if count < 0 { + trace!("Read from stdio failed"); + break; + } + let count = count as usize; + + if let Ok(s) = core::str::from_utf8(&buf[..count]) { + println!("Got string {:?}", s); + + if s == "quit" { + break; } - trace!("Exiting"); - return 0; } else { - trace!("Spawned {}", pid); - unsafe { - libusr::sys::sys_ex_nanosleep(5_000_000_000, core::ptr::null_mut()); - } + println!("Got string (non-utf8) {:?}", &buf[..count]); } } - //let mut buf = [0; 128]; - - // print!("\x1B[2J\x1B[1;1H"); - // println!("Hello!"); - - // loop { - // print!("> "); - - // let count = unsafe { - // libusr::sys::sys_read(0, buf.as_mut_ptr(), buf.len()) - // }; - // if count < 0 { - // trace!("Read from stdio failed"); - // break; - // } - // let count = count as usize; - - // if let Ok(s) = core::str::from_utf8(&buf[..count]) { - // println!("Got string {:?}", s); - - // if s == "quit" { - // break; - // } - // } else { - // println!("Got string (non-utf8) {:?}", &buf[..count]); - // } - // } - // -1 + -1 } diff --git a/kernel/src/arch/aarch64/exception.rs b/kernel/src/arch/aarch64/exception.rs index 607d5b4..66effb4 100644 --- a/kernel/src/arch/aarch64/exception.rs +++ b/kernel/src/arch/aarch64/exception.rs @@ -17,7 +17,6 @@ pub const EC_DATA_ABORT_EL0: u64 = 0b100100; /// SVC instruction in AA64 state pub const EC_SVC_AA64: u64 = 0b010101; -#[allow(missing_docs)] #[derive(Debug)] #[repr(C)] pub struct ExceptionFrame { @@ -89,7 +88,8 @@ extern "C" fn __aa64_exc_sync_handler(exc: &mut ExceptionFrame) { match syscall::sys_fork(exc) { Ok(pid) => exc.x[0] = pid.value() as usize, Err(err) => { - todo!() + warnln!("fork() syscall failed: {:?}", err); + exc.x[0] = usize::MAX; }, } return; diff --git a/kernel/src/arch/aarch64/mach_orangepi3/mod.rs b/kernel/src/arch/aarch64/mach_orangepi3/mod.rs index 250d143..2e707b0 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/mod.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/mod.rs @@ -27,7 +27,6 @@ use rtc::Rtc; use uart::Uart; use wdog::RWdog; -#[allow(missing_docs)] pub fn init_board_early() -> Result<(), Errno> { unsafe { UART0.enable()?; @@ -37,7 +36,6 @@ pub fn init_board_early() -> Result<(), Errno> { Ok(()) } -#[allow(missing_docs)] pub fn init_board() -> Result<(), Errno> { unsafe { GIC.enable()?; diff --git a/kernel/src/arch/aarch64/mach_qemu/mod.rs b/kernel/src/arch/aarch64/mach_qemu/mod.rs index 7a5197e..88d8770 100644 --- a/kernel/src/arch/aarch64/mach_qemu/mod.rs +++ b/kernel/src/arch/aarch64/mach_qemu/mod.rs @@ -30,7 +30,6 @@ const ECAM_BASE: usize = 0x4010000000; const PHYS_BASE: usize = 0x40000000; const PHYS_SIZE: usize = 0x10000000; -#[allow(missing_docs)] pub fn init_board_early() -> Result<(), Errno> { unsafe { // Enable UART early on @@ -41,7 +40,6 @@ pub fn init_board_early() -> Result<(), Errno> { Ok(()) } -#[allow(missing_docs)] pub fn init_board() -> Result<(), Errno> { unsafe { GIC.enable()?; diff --git a/kernel/src/arch/aarch64/reg/cntkctl_el1.rs b/kernel/src/arch/aarch64/reg/cntkctl_el1.rs index ab2221e..9b57041 100644 --- a/kernel/src/arch/aarch64/reg/cntkctl_el1.rs +++ b/kernel/src/arch/aarch64/reg/cntkctl_el1.rs @@ -7,7 +7,6 @@ use tock_registers::{ register_bitfields! { u64, - #[allow(missing_docs)] /// Counter-timer Kernel Control Register pub CNTKCTL_EL1 [ /// If set, disables CNTPCT and CNTFRQ trapping from EL0 diff --git a/kernel/src/arch/aarch64/reg/cpacr_el1.rs b/kernel/src/arch/aarch64/reg/cpacr_el1.rs index 3c7077b..2f58ee4 100644 --- a/kernel/src/arch/aarch64/reg/cpacr_el1.rs +++ b/kernel/src/arch/aarch64/reg/cpacr_el1.rs @@ -7,7 +7,6 @@ use tock_registers::{ register_bitfields! { u64, - #[allow(missing_docs)] /// EL1 Architectural Feature Access Control Register pub CPACR_EL1 [ /// Enable EL0 and EL1 SIMD/FP accesses to EL1 diff --git a/kernel/src/config.rs b/kernel/src/config.rs index f46a190..80ec869 100644 --- a/kernel/src/config.rs +++ b/kernel/src/config.rs @@ -72,7 +72,7 @@ impl Config { } } - pub fn set_cmdline(&self, cmdline: &str) { + pub fn set_cmdline(&self, _cmdline: &str) { // TODO } } @@ -91,7 +91,7 @@ impl ConfigString { pub fn set_from_str(&mut self, data: &str) { let bytes = data.as_bytes(); - self.buf[..bytes.len()].copy_from_slice(&bytes); + self.buf[..bytes.len()].copy_from_slice(bytes); self.len = bytes.len(); } } diff --git a/kernel/src/dev/mod.rs b/kernel/src/dev/mod.rs index fda658b..144de1c 100644 --- a/kernel/src/dev/mod.rs +++ b/kernel/src/dev/mod.rs @@ -3,17 +3,14 @@ use error::Errno; // Device classes -#[allow(missing_docs)] pub mod fdt; pub mod gpio; pub mod irq; -#[allow(missing_docs)] pub mod sd; pub mod pci; pub mod rtc; pub mod serial; pub mod timer; -#[allow(missing_docs)] pub mod tty; /// Generic device trait diff --git a/kernel/src/dev/pci/mod.rs b/kernel/src/dev/pci/mod.rs index eb23cd9..6245e18 100644 --- a/kernel/src/dev/pci/mod.rs +++ b/kernel/src/dev/pci/mod.rs @@ -8,21 +8,18 @@ pub mod pcie; macro_rules! ecam_field { ($getter:ident, $off:expr, u16) => { - #[allow(missing_docs)] #[inline(always)] fn $getter(&self) -> u16 { self.readw($off) } }; ($getter:ident, $off:expr, u8) => { - #[allow(missing_docs)] #[inline(always)] fn $getter(&self) -> u8 { self.readb($off) } }; ($getter:ident, $setter:ident, $off:expr, u16) => { - #[allow(missing_docs)] #[inline(always)] unsafe fn $setter(&self, v: u16) { self.writew($off, v) diff --git a/kernel/src/dev/sd.rs b/kernel/src/dev/sd.rs index 35ab321..eb541bf 100644 --- a/kernel/src/dev/sd.rs +++ b/kernel/src/dev/sd.rs @@ -295,24 +295,21 @@ impl SdCardStatus { impl SdResponseType { pub const fn is_busy(self) -> bool { - match self { - Self::R1b | Self::R5b => true, - _ => false, - } + matches!(self, Self::R1b | Self::R5b) } } impl SdResponse { pub fn unwrap_one(&self) -> u32 { - match self { - &SdResponse::One(v) => v, + match *self { + SdResponse::One(v) => v, _ => panic!("Unexpected response type"), } } pub fn unwrap_four(&self) -> [u32; 4] { - match self { - &SdResponse::Four(v) => v, + match *self { + SdResponse::Four(v) => v, _ => panic!("Unexpected response type"), } } @@ -343,10 +340,7 @@ impl SdCommand<'_> { } pub const fn is_acmd(&self) -> bool { - match self.number { - SdCommandNumber::Acmd41 | SdCommandNumber::Acmd51 => true, - _ => false, - } + matches!(self.number, SdCommandNumber::Acmd41 | SdCommandNumber::Acmd51) } pub const fn number(&self) -> u32 { diff --git a/kernel/src/dev/tty.rs b/kernel/src/dev/tty.rs index 7f2a636..0980887 100644 --- a/kernel/src/dev/tty.rs +++ b/kernel/src/dev/tty.rs @@ -3,7 +3,6 @@ use crate::proc::wait::Wait; use crate::sync::IrqSafeSpinLock; use vfs::CharDevice; -#[allow(missing_docs)] #[derive(Debug)] struct CharRingInner { rd: usize, @@ -19,7 +18,6 @@ pub struct CharRing { inner: IrqSafeSpinLock>, } -#[allow(missing_docs)] impl CharRingInner { #[inline] const fn is_readable(&self) -> bool { @@ -44,7 +42,6 @@ impl CharRingInner { } } -#[allow(missing_docs)] impl CharRing { pub const fn new() -> Self { Self { diff --git a/kernel/src/init.rs b/kernel/src/init.rs index cef850e..c2c285d 100644 --- a/kernel/src/init.rs +++ b/kernel/src/init.rs @@ -3,7 +3,7 @@ use crate::fs::{devfs, MemfsBlockAlloc}; use crate::mem; use crate::proc::{elf, Process}; use memfs::Ramfs; -use vfs::{FileMode, Filesystem, Ioctx, OpenFlags}; +use vfs::{Filesystem, Ioctx, OpenFlags}; #[inline(never)] pub extern "C" fn init_fn(_arg: usize) -> ! { diff --git a/kernel/src/main.rs b/kernel/src/main.rs index f4e5c7d..38867ef 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -34,10 +34,8 @@ pub mod fs; pub mod mem; pub mod proc; pub mod sync; -#[allow(missing_docs)] pub mod syscall; pub mod util; -#[allow(missing_docs)] pub mod init; #[panic_handler] diff --git a/kernel/src/mem/phys/manager.rs b/kernel/src/mem/phys/manager.rs index 0a7301f..cf8f33f 100644 --- a/kernel/src/mem/phys/manager.rs +++ b/kernel/src/mem/phys/manager.rs @@ -85,10 +85,10 @@ unsafe impl Manager for SimpleManager { fn clone_page(&mut self, src: usize) -> Result { let src_index = self.page_index(src); - let src_page = &self.pages[src_index]; - assert_eq!(src_page.refcount, 1); - assert!(src_page.usage != PageUsage::Available && src_page.usage != PageUsage::Reserved); - let dst_index = self.alloc_single_index(src_page.usage)?; + let src_usage = self.pages[src_index].usage; + assert_eq!(self.pages[src_index].refcount, 1); + let dst_index = self.alloc_single_index(src_usage)?; + assert!(src_usage != PageUsage::Available && src_usage != PageUsage::Reserved); let dst = (self.base_index + dst_index) * PAGE_SIZE; unsafe { memcpy(virtualize(dst) as *mut u8, virtualize(src) as *mut u8, 4096); diff --git a/kernel/src/mem/phys/mod.rs b/kernel/src/mem/phys/mod.rs index f38e486..4489ba6 100644 --- a/kernel/src/mem/phys/mod.rs +++ b/kernel/src/mem/phys/mod.rs @@ -13,8 +13,6 @@ pub use reserved::ReservedRegion; type ManagerImpl = SimpleManager; -const MAX_PAGES: usize = 1024 * 1024; - /// These describe what a memory page is used for #[derive(PartialEq, Debug, Clone, Copy)] pub enum PageUsage { @@ -83,12 +81,19 @@ pub fn alloc_page(pu: PageUsage) -> Result { } /// Releases a single physical memory page back for further allocation. +/// +/// # Safety +/// +/// Unsafe: accepts arbitrary `page` arguments pub unsafe fn free_page(page: usize) -> Result<(), Errno> { MANAGER.lock().as_mut().unwrap().free_page(page) } -pub fn clone_page(src: usize) -> Result { - MANAGER.lock().as_mut().unwrap().clone_page(src) +/// # Safety +/// +/// Unsafe: accepts arbitrary `page` arguments +pub unsafe fn clone_page(page: usize) -> Result { + MANAGER.lock().as_mut().unwrap().clone_page(page) } fn find_contiguous>(iter: T, count: usize) -> Option { @@ -115,6 +120,11 @@ fn find_contiguous>(iter: T, count: usize) -> O /// Initializes physical memory manager using an iterator of available /// physical memory ranges +/// +/// # Safety +/// +/// Unsafe: caller must ensure validity of passed memory regions. +/// The function may not be called twice. pub unsafe fn init_from_iter + Clone>(iter: T) { let mut mem_base = usize::MAX; for reg in iter.clone() { @@ -157,6 +167,10 @@ pub unsafe fn init_from_iter + Clone>(iter: T) /// Initializes physical memory manager using a single memory region. /// /// See [init_from_iter]. +/// +/// # Safety +/// +/// Unsafe: see [init_from_iter]. pub unsafe fn init_from_region(base: usize, size: usize) { let iter = SimpleMemoryIterator::new(MemoryRegion { start: base, diff --git a/kernel/src/mem/virt/mod.rs b/kernel/src/mem/virt/mod.rs index 5d4a9ec..97b8639 100644 --- a/kernel/src/mem/virt/mod.rs +++ b/kernel/src/mem/virt/mod.rs @@ -69,6 +69,10 @@ impl DeviceMemoryIo { /// Allocates and maps device MMIO memory. /// /// See [DeviceMemory::map] + /// + /// # Safety + /// + /// Unsafe: accepts arbitrary physical addresses pub unsafe fn map(name: &'static str, phys: usize, count: usize) -> Result { DeviceMemory::map(name, phys, count).map(Self::new) } diff --git a/kernel/src/mem/virt/table.rs b/kernel/src/mem/virt/table.rs index ab72542..7f8bbab 100644 --- a/kernel/src/mem/virt/table.rs +++ b/kernel/src/mem/virt/table.rs @@ -185,7 +185,7 @@ impl Space { } pub fn fork(&mut self) -> Result<&'static mut Self, Errno> { - let mut res = Self::alloc_empty()?; + let res = Self::alloc_empty()?; for l0i in 0..512 { if let Some(l1_table) = self.0.next_level_table(l0i) { for l1i in 0..512 { @@ -199,7 +199,7 @@ impl Space { let src_phys = unsafe { entry.address_unchecked() }; let virt_addr = (l0i << 30) | (l1i << 21) | (l2i << 12); debugln!("Fork page {:#x}:{:#x}", virt_addr, src_phys); - let dst_phys = phys::clone_page(src_phys)?; + let dst_phys = unsafe { phys::clone_page(src_phys)? }; res.map(virt_addr, dst_phys, unsafe { entry.fork_flags() })?; } diff --git a/kernel/src/proc/mod.rs b/kernel/src/proc/mod.rs index cd1a838..1876305 100644 --- a/kernel/src/proc/mod.rs +++ b/kernel/src/proc/mod.rs @@ -1,39 +1,37 @@ //! Process and thread manipulation facilities -use crate::mem; use crate::init; use crate::sync::IrqSafeSpinLock; -use alloc::{boxed::Box, collections::BTreeMap}; +use alloc::collections::BTreeMap; pub mod elf; pub mod process; pub use process::{Pid, Process, ProcessRef, State as ProcessState}; -#[allow(missing_docs)] pub mod wait; pub mod sched; pub use sched::Scheduler; pub(self) use sched::SCHED; -macro_rules! spawn { - (fn ($dst_arg:ident : usize) $body:block, $src_arg:expr) => {{ - #[inline(never)] - extern "C" fn __inner_func($dst_arg : usize) -> ! { - let __res = $body; - { - #![allow(unreachable_code)] - SCHED.current_process().exit(__res); - panic!(); - } - } - - let __proc = $crate::proc::Process::new_kernel(__inner_func, $src_arg).unwrap(); - $crate::proc::SCHED.enqueue(__proc.id()); - }}; - - (fn () $body:block) => (spawn!(fn (_arg: usize) $body, 0usize)) -} +// macro_rules! spawn { +// (fn ($dst_arg:ident : usize) $body:block, $src_arg:expr) => {{ +// #[inline(never)] +// extern "C" fn __inner_func($dst_arg : usize) -> ! { +// let __res = $body; +// { +// #![allow(unreachable_code)] +// SCHED.current_process().exit(__res); +// panic!(); +// } +// } +// +// let __proc = $crate::proc::Process::new_kernel(__inner_func, $src_arg).unwrap(); +// $crate::proc::SCHED.enqueue(__proc.id()); +// }}; +// +// (fn () $body:block) => (spawn!(fn (_arg: usize) $body, 0usize)) +// } /// Performs a task switch. /// diff --git a/kernel/src/proc/process.rs b/kernel/src/proc/process.rs index cff22c0..34ebb56 100644 --- a/kernel/src/proc/process.rs +++ b/kernel/src/proc/process.rs @@ -181,6 +181,12 @@ impl ProcessIo { } } +impl Default for ProcessIo { + fn default() -> Self { + Self::new() + } +} + impl Process { const USTACK_VIRT_TOP: usize = 0x100000000; const USTACK_PAGES: usize = 4; @@ -301,7 +307,7 @@ impl Process { }) }); debugln!("Process {} forked into {}", src_inner.id, dst_id); - assert!(PROCESSES.lock().insert(dst_id, dst.clone()).is_none()); + assert!(PROCESSES.lock().insert(dst_id, dst).is_none()); SCHED.enqueue(dst_id); Ok(dst_id) diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 91242ea..18e5458 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -55,7 +55,7 @@ fn validate_user_ptr_null<'a>(base: usize, len: usize) -> Result(base: usize, limit: usize) -> Result<&'a str, Errno> { }) } +/// # Safety +/// +/// Unsafe: accepts and clones process states. Only legal to call +/// from exception handlers. pub unsafe fn sys_fork(regs: &mut ExceptionFrame) -> Result { - let proc = Process::current(); - let res = proc.fork(regs); - res + Process::current().fork(regs) } -pub unsafe fn syscall(num: usize, args: &[usize]) -> Result { +pub fn syscall(num: usize, args: &[usize]) -> Result { match num { // Process management system calls abi::SYS_EXIT => { @@ -196,7 +198,7 @@ pub unsafe fn syscall(num: usize, args: &[usize]) -> Result { let res = wait::sleep(Duration::from_nanos(args[0] as u64), &mut rem); if res == Err(Errno::Interrupt) { warnln!("Sleep interrupted, {:?} remaining", rem); - if let Some(_) = rem_buf { + if rem_buf.is_some() { todo!() } } diff --git a/syscall/src/stat.rs b/syscall/src/stat.rs index 09c2e20..70b0d01 100644 --- a/syscall/src/stat.rs +++ b/syscall/src/stat.rs @@ -1,12 +1,10 @@ -use core::fmt; - pub const AT_FDCWD: i32 = -2; bitflags! { pub struct OpenFlags: u32 { - const O_RDONLY = 1 << 0; - const O_WRONLY = 2 << 0; - const O_RDWR = 3 << 0; + const O_RDONLY = 1; + const O_WRONLY = 2; + const O_RDWR = 3; const O_ACCESS = 0xF; const O_CREAT = 1 << 4;