From afa7e4cecbf7fe302d222810b0ee2cf3e76a28c3 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Sun, 5 Dec 2021 21:58:03 +0200 Subject: [PATCH] feature: simple pseudo devices --- kernel/src/arch/aarch64/boot/mod.rs | 24 ++++--- kernel/src/arch/aarch64/timer.rs | 4 +- kernel/src/dev/mod.rs | 1 + kernel/src/dev/pseudo.rs | 102 ++++++++++++++++++++++++++++ kernel/src/fs/devfs.rs | 4 +- 5 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 kernel/src/dev/pseudo.rs diff --git a/kernel/src/arch/aarch64/boot/mod.rs b/kernel/src/arch/aarch64/boot/mod.rs index 0c054a2..65c4ba2 100644 --- a/kernel/src/arch/aarch64/boot/mod.rs +++ b/kernel/src/arch/aarch64/boot/mod.rs @@ -11,6 +11,7 @@ use crate::dev::{ Device, }; use crate::fs::devfs; +use crate::dev::pseudo; use libsys::error::Errno; //use crate::debug::Level; use crate::mem::{ @@ -23,22 +24,16 @@ use cortex_a::asm::barrier::{self, dsb, isb}; use cortex_a::registers::{SCTLR_EL1, VBAR_EL1}; use tock_registers::interfaces::{ReadWriteable, Writeable}; -fn init_device_tree(fdt_base_phys: usize) -> Result<(), Errno> { +fn init_device_tree(fdt_base_phys: usize) -> Result, Errno> { use fdt_rs::prelude::*; let fdt = if fdt_base_phys != 0 { DeviceTree::from_phys(fdt_base_phys + 0xFFFFFF8000000000)? } else { warnln!("No FDT present"); - return Ok(()); + return Ok(None); }; - #[cfg(feature = "verbose")] - { - use crate::debug::Level; - fdt.dump(Level::Debug); - } - let mut cfg = CONFIG.lock(); if let Some(chosen) = fdt.node_by_path("/chosen") { @@ -56,7 +51,7 @@ fn init_device_tree(fdt_base_phys: usize) -> Result<(), Errno> { } } - Ok(()) + Ok(Some(fdt)) } #[no_mangle] @@ -87,7 +82,7 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! { // Enable MMU virt::enable().expect("Failed to initialize virtual memory"); - init_device_tree(fdt_base).expect("Device tree init failed"); + let fdt = init_device_tree(fdt_base).expect("Device tree init failed"); // Most basic machine init: initialize proper debug output // physical memory @@ -105,6 +100,15 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! { machine::init_board().unwrap(); + #[cfg(feature = "verbose")] + if let Some(fdt) = fdt { + use crate::debug::Level; + fdt.dump(Level::Debug); + } + + devfs::add_named_char_device(&pseudo::ZERO, "zero").unwrap(); + devfs::add_named_char_device(&pseudo::RANDOM, "random").unwrap(); + infoln!("Machine init finished"); unsafe { diff --git a/kernel/src/arch/aarch64/timer.rs b/kernel/src/arch/aarch64/timer.rs index 5a27914..7aa9ded 100644 --- a/kernel/src/arch/aarch64/timer.rs +++ b/kernel/src/arch/aarch64/timer.rs @@ -1,7 +1,9 @@ //! ARM generic timer implementation use crate::arch::machine::{self, IrqNumber}; +use crate::proc; use crate::dev::{ + pseudo, irq::{IntController, IntSource}, timer::TimestampSource, Device, @@ -34,9 +36,9 @@ impl IntSource for GenericTimer { fn handle_irq(&self) -> Result<(), Errno> { CNTP_TVAL_EL0.set(TIMER_TICK); CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET); - use crate::proc; proc::wait::tick(); proc::switch(); + pseudo::RANDOM.set_state(CNTPCT_EL0.get() as u32); Ok(()) } diff --git a/kernel/src/dev/mod.rs b/kernel/src/dev/mod.rs index fdaf7a8..76a3e4c 100644 --- a/kernel/src/dev/mod.rs +++ b/kernel/src/dev/mod.rs @@ -11,6 +11,7 @@ pub mod rtc; pub mod sd; pub mod serial; pub mod timer; +pub mod pseudo; pub mod tty; /// Generic device trait diff --git a/kernel/src/dev/pseudo.rs b/kernel/src/dev/pseudo.rs new file mode 100644 index 0000000..2115cb8 --- /dev/null +++ b/kernel/src/dev/pseudo.rs @@ -0,0 +1,102 @@ +use crate::arch::machine::{self, IrqNumber}; +use crate::dev::{ + irq::{IntController, IntSource}, + serial::SerialDevice, + tty::{CharRing, TtyDevice}, + Device, +}; +use crate::mem::virt::DeviceMemoryIo; +use crate::sync::IrqSafeSpinLock; +use crate::util::InitOnce; +use libsys::{error::Errno, ioctl::IoctlCmd}; +use core::sync::atomic::{AtomicU32, Ordering}; +use tock_registers::{ + interfaces::{ReadWriteable, Readable, Writeable}, + register_bitfields, register_structs, + registers::{ReadOnly, ReadWrite, WriteOnly}, +}; +use vfs::CharDevice; + +pub struct Random { + state: AtomicU32 +} +pub struct Zero; + +impl Device for Random { + fn name(&self) -> &'static str { + "Pseudo-random device" + } + + unsafe fn enable(&self) -> Result<(), Errno> { + Ok(()) + } +} + +impl CharDevice for Random { + fn read(&self, _blocking: bool, data: &mut [u8]) -> Result { + for byte in data.iter_mut() { + *byte = self.read_single() as u8; + } + Ok(data.len()) + } + + fn write(&self, _blocking: bool, _data: &[u8]) -> Result { + Ok(0) + } + + fn is_ready(&self, _write: bool) -> Result { + Ok(true) + } + + fn ioctl(&self, _cmd: IoctlCmd, _ptr: usize, _lim: usize) -> Result { + Err(Errno::InvalidArgument) + } +} + + +impl Device for Zero { + fn name(&self) -> &'static str { + "Zero device" + } + + unsafe fn enable(&self) -> Result<(), Errno> { + Ok(()) + } +} + +impl CharDevice for Zero { + fn read(&self, _blocking: bool, data: &mut [u8]) -> Result { + data.fill(0); + Ok(data.len()) + } + + fn write(&self, _blocking: bool, _data: &[u8]) -> Result { + Ok(0) + } + + fn is_ready(&self, _write: bool) -> Result { + Ok(true) + } + + fn ioctl(&self, _cmd: IoctlCmd, _ptr: usize, _lim: usize) -> Result { + Err(Errno::InvalidArgument) + } +} + +impl Random { + pub fn set_state(&self, state: u32) { + self.state.store(state, Ordering::Release); + } + + pub fn read_single(&self) -> u32 { + let mut x = self.state.load(Ordering::Acquire); + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + self.state.store(x, Ordering::Release); + x + } +} + +pub static RANDOM: Random = Random { state: AtomicU32::new(0) }; +pub static ZERO: Zero = Zero; diff --git a/kernel/src/fs/devfs.rs b/kernel/src/fs/devfs.rs index 3cb59c7..9bc7cc1 100644 --- a/kernel/src/fs/devfs.rs +++ b/kernel/src/fs/devfs.rs @@ -26,7 +26,7 @@ pub fn root() -> &'static VnodeRef { DEVFS_ROOT.get() } -fn _add_char_device(dev: &'static dyn CharDevice, name: &str) -> Result<(), Errno> { +pub fn add_named_char_device(dev: &'static dyn CharDevice, name: &str) -> Result<(), Errno> { infoln!("Add char device: {}", name); let node = Vnode::new(name, VnodeKind::Char, Vnode::CACHE_STAT); @@ -56,5 +56,5 @@ pub fn add_char_device(dev: &'static dyn CharDevice, kind: CharDeviceType) -> Re let name = core::str::from_utf8(&buf[..=prefix.len()]).map_err(|_| Errno::InvalidArgument)?; - _add_char_device(dev, name) + add_named_char_device(dev, name) }