From ad17789d94d9843c0f6cb135c4f5dfd9c9d21afb Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Wed, 3 Nov 2021 13:24:57 +0200 Subject: [PATCH] refactor: change add_char_device --- init/src/main.rs | 13 ++- kernel/src/arch/aarch64/boot/mod.rs | 58 +++++++--- kernel/src/arch/aarch64/mach_orangepi3/mod.rs | 2 + kernel/src/arch/aarch64/mach_orangepi3/rtc.rs | 1 - .../src/arch/aarch64/mach_orangepi3/uart.rs | 25 ++++- kernel/src/arch/aarch64/mach_qemu/mod.rs | 4 +- kernel/src/config.rs | 105 ++++++++++++++++++ kernel/src/dev/fdt.rs | 2 +- kernel/src/fs/devfs.rs | 35 +++++- kernel/src/init.rs | 53 +++++++++ kernel/src/main.rs | 4 + kernel/src/mem/phys/mod.rs | 4 +- kernel/src/proc/mod.rs | 50 +-------- kernel/src/sync.rs | 4 +- 14 files changed, 277 insertions(+), 83 deletions(-) create mode 100644 kernel/src/config.rs create mode 100644 kernel/src/init.rs diff --git a/init/src/main.rs b/init/src/main.rs index 237de55..c90312c 100644 --- a/init/src/main.rs +++ b/init/src/main.rs @@ -9,7 +9,12 @@ extern crate libusr; fn main() -> i32 { 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()) }; @@ -21,13 +26,13 @@ fn main() -> i32 { 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]); } - - unsafe { - libusr::sys::sys_ex_nanosleep(1_000_000_000, core::ptr::null_mut()); - } } -1 } diff --git a/kernel/src/arch/aarch64/boot/mod.rs b/kernel/src/arch/aarch64/boot/mod.rs index 58698e4..2fc28df 100644 --- a/kernel/src/arch/aarch64/boot/mod.rs +++ b/kernel/src/arch/aarch64/boot/mod.rs @@ -5,7 +5,9 @@ use crate::arch::{ machine, }; use crate::fs::devfs; -use crate::dev::{fdt::DeviceTree, irq::IntSource, Device}; +use crate::dev::{fdt::{DeviceTree, find_prop}, irq::IntSource, Device}; +use error::Errno; +use crate::config::{CONFIG, ConfigKey}; //use crate::debug::Level; use crate::mem::{ self, heap, @@ -17,6 +19,39 @@ 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> { + 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(()); + }; + + use crate::debug::Level; + fdt.dump(Level::Debug); + + let mut cfg = CONFIG.lock(); + + if let Some(chosen) = fdt.node_by_path("/chosen") { + if let Some(initrd_start) = find_prop(chosen.clone(), "linux,initrd-start") { + let initrd_end = find_prop(chosen.clone(), "linux,initrd-end").unwrap(); + let initrd_start = initrd_start.u32(0).unwrap() as usize; + let initrd_end = initrd_end.u32(0).unwrap() as usize; + + cfg.set_usize(ConfigKey::InitrdBase, initrd_start); + cfg.set_usize(ConfigKey::InitrdSize, initrd_end - initrd_start); + } + + if let Some(cmdline) = find_prop(chosen, "bootargs") { + cfg.set_cmdline(cmdline.str().unwrap()); + } + } + + Ok(()) +} + #[no_mangle] extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! { // Disable FP instruction trapping @@ -49,6 +84,8 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! { // physical memory machine::init_board_early().unwrap(); + init_device_tree(fdt_base).expect("Device tree init failed"); + // Setup a heap unsafe { let heap_base_phys = phys::alloc_contiguous_pages(PageUsage::KernelHeap, 4096) @@ -61,29 +98,14 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! { machine::init_board().unwrap(); - let initrd; - if fdt_base != 0 { - let fdt = DeviceTree::from_phys(fdt_base + 0xFFFFFF8000000000); - if let Ok(fdt) = fdt { - use crate::debug::Level; - fdt.dump(Level::Debug); - initrd = fdt.initrd(); - } else { - initrd = None; - errorln!("Failed to init FDT"); - } - } else { - initrd = None; - warnln!("No FDT present"); - } - + debugln!("Config: {:#x?}", CONFIG.lock()); infoln!("Machine init finished"); unsafe { machine::local_timer().enable().unwrap(); machine::local_timer().init_irqs().unwrap(); - proc::enter(initrd); + proc::enter(); } } diff --git a/kernel/src/arch/aarch64/mach_orangepi3/mod.rs b/kernel/src/arch/aarch64/mach_orangepi3/mod.rs index ececce0..250d143 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/mod.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/mod.rs @@ -11,6 +11,7 @@ use crate::dev::{ timer::TimestampSource, Device, }; +use crate::fs::devfs::{self, CharDeviceType}; use crate::mem::phys; use error::Errno; @@ -43,6 +44,7 @@ pub fn init_board() -> Result<(), Errno> { GPIO.enable()?; UART0.init_irqs()?; + devfs::add_char_device(&UART0, CharDeviceType::TtySerial)?; R_WDOG.enable()?; diff --git a/kernel/src/arch/aarch64/mach_orangepi3/rtc.rs b/kernel/src/arch/aarch64/mach_orangepi3/rtc.rs index 0f75b49..01eaf1b 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/rtc.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/rtc.rs @@ -71,7 +71,6 @@ impl RtcDevice for Rtc {} impl IntSource for Rtc { fn handle_irq(&self) -> Result<(), Errno> { self.regs.get().lock().arm_alarm0_irq(1); - debugln!("Tick!"); Ok(()) } diff --git a/kernel/src/arch/aarch64/mach_orangepi3/uart.rs b/kernel/src/arch/aarch64/mach_orangepi3/uart.rs index a2641a2..83b696d 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/uart.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/uart.rs @@ -2,8 +2,9 @@ use crate::arch::machine::{self, IrqNumber}; use crate::dev::{ irq::{IntController, IntSource}, serial::SerialDevice, - Device, + tty::CharRing, Device, }; +use vfs::CharDevice; use crate::mem::virt::DeviceMemoryIo; use crate::sync::IrqSafeSpinLock; use crate::util::InitOnce; @@ -78,6 +79,7 @@ struct UartInner { pub(super) struct Uart { inner: InitOnce>, + ring: CharRing<16>, base: usize, irq: IrqNumber, } @@ -120,6 +122,23 @@ impl SerialDevice for Uart { } } +impl CharDevice for Uart { + fn read(&self, blocking: bool, data: &mut [u8]) -> Result { + assert!(blocking); + self.ring.line_read(data, self) + } + + fn write(&self, blocking: bool, data: &[u8]) -> Result { + assert!(blocking); + for &byte in data { + unsafe { + self.send(byte)?; + } + } + Ok(data.len()) + } +} + impl IntSource for Uart { fn handle_irq(&self) -> Result<(), Errno> { let byte = self.inner.get().lock().regs.DR_DLL.get(); @@ -132,8 +151,7 @@ impl IntSource for Uart { } } - use crate::dev::gpio::GpioDevice; - machine::GPIO.toggle_pin(machine::PinAddress::new(3, 26)); + self.ring.putc(byte as u8, false).ok(); Ok(()) } @@ -150,6 +168,7 @@ impl Uart { pub const unsafe fn new(base: usize, irq: IrqNumber) -> Self { Self { inner: InitOnce::new(), + ring: CharRing::new(), base, irq, } diff --git a/kernel/src/arch/aarch64/mach_qemu/mod.rs b/kernel/src/arch/aarch64/mach_qemu/mod.rs index be8039f..7a5197e 100644 --- a/kernel/src/arch/aarch64/mach_qemu/mod.rs +++ b/kernel/src/arch/aarch64/mach_qemu/mod.rs @@ -11,7 +11,7 @@ use crate::dev::{ serial::{pl011::Pl011, SerialDevice}, Device, }; -use crate::fs::devfs; +use crate::fs::devfs::{self, CharDeviceType}; use crate::mem::phys; use error::Errno; @@ -47,7 +47,7 @@ pub fn init_board() -> Result<(), Errno> { GIC.enable()?; UART0.init_irqs()?; - devfs::add_char_device("uart0", &UART0)?; + devfs::add_char_device(&UART0, CharDeviceType::TtySerial)?; RTC.enable()?; RTC.init_irqs()?; diff --git a/kernel/src/config.rs b/kernel/src/config.rs new file mode 100644 index 0000000..cf6ddd5 --- /dev/null +++ b/kernel/src/config.rs @@ -0,0 +1,105 @@ +#![allow(missing_docs)] + +use crate::sync::IrqSafeSpinLock; +use core::fmt; + +#[derive(Debug)] +pub struct Config { + cmdline: ConfigString<256>, + console: ConfigString<16>, + mem_limit: usize, + initrd_base: usize, + initrd_size: usize, +} + +#[derive(Clone, Copy, Debug)] +pub enum ConfigKey { + Cmdline, + Console, + MemLimit, + InitrdBase, + InitrdSize +} + +struct ConfigString { + buf: [u8; N], + len: usize, +} + +pub static CONFIG: IrqSafeSpinLock = IrqSafeSpinLock::new(Config::default()); + +impl const Default for Config { + fn default() -> Self { + Self { + cmdline: ConfigString::empty(), + console: ConfigString::empty(), + mem_limit: usize::MAX, + initrd_base: 0, + initrd_size: 0 + } + } +} + +impl Config { + pub fn set_usize(&mut self, key: ConfigKey, value: usize) { + match key { + ConfigKey::InitrdBase => { self.initrd_base = value } + ConfigKey::InitrdSize => { self.initrd_size = value } + ConfigKey::MemLimit => { self.mem_limit = value } + _ => panic!("Invalid usize key: {:?}", key) + } + } + + pub fn set_str(&mut self, key: ConfigKey, value: &str) { + match key { + ConfigKey::Cmdline => { self.cmdline.set_from_str(value) } + _ => panic!("Invalid str key: {:?}", key) + } + } + + pub fn get_usize(&self, key: ConfigKey) -> usize { + match key { + ConfigKey::InitrdBase => self.initrd_base, + ConfigKey::InitrdSize => self.initrd_size, + ConfigKey::MemLimit => self.mem_limit, + _ => panic!("Invalid usize key: {:?}", key) + } + } + + pub fn get_str(&self, key: ConfigKey) -> &str { + match key { + ConfigKey::Cmdline => self.cmdline.as_str(), + ConfigKey::Console => self.console.as_str(), + _ => panic!("Invalid str key: {:?}", key) + } + } + + pub fn set_cmdline(&self, cmdline: &str) { + // TODO + } +} + +impl ConfigString { + pub const fn empty() -> Self { + Self { + buf: [0; N], + len: 0, + } + } + + pub fn as_str(&self) -> &str { + core::str::from_utf8(&self.buf[..self.len]).unwrap() + } + + pub fn set_from_str(&mut self, data: &str) { + let bytes = data.as_bytes(); + self.buf[..bytes.len()].copy_from_slice(&bytes); + self.len = bytes.len(); + } +} + +impl fmt::Debug for ConfigString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.as_str()) + } +} diff --git a/kernel/src/dev/fdt.rs b/kernel/src/dev/fdt.rs index 0dcee12..b776825 100644 --- a/kernel/src/dev/fdt.rs +++ b/kernel/src/dev/fdt.rs @@ -88,7 +88,7 @@ fn find_node<'a>(at: INode<'a>, path: &str) -> Option> { } } -fn find_prop<'a>(at: INode<'a>, name: &str) -> Option> { +pub fn find_prop<'a>(at: INode<'a>, name: &str) -> Option> { at.props().find(|p| p.name().unwrap() == name) } diff --git a/kernel/src/fs/devfs.rs b/kernel/src/fs/devfs.rs index a938891..d310661 100644 --- a/kernel/src/fs/devfs.rs +++ b/kernel/src/fs/devfs.rs @@ -1,7 +1,13 @@ -use vfs::{Vnode, VnodeKind, CharDevice, VnodeRef, CharDeviceWrapper}; -use alloc::boxed::Box; use crate::util::InitOnce; +use alloc::boxed::Box; +use core::sync::atomic::{AtomicUsize, Ordering}; use error::Errno; +use vfs::{CharDevice, CharDeviceWrapper, Vnode, VnodeKind, VnodeRef}; + +#[derive(Debug)] +pub enum CharDeviceType { + TtySerial, +} static DEVFS_ROOT: InitOnce = InitOnce::new(); @@ -13,8 +19,9 @@ pub fn root() -> &'static VnodeRef { DEVFS_ROOT.get() } -pub fn add_char_device(name: &str, dev: &'static dyn CharDevice) -> Result<(), Errno> { - debugln!("Add device: {}", name); +fn _add_char_device(dev: &'static dyn CharDevice, name: &str) -> Result<(), Errno> { + infoln!("Add char device: {}", name); + let node = Vnode::new(name, VnodeKind::Char, 0); node.set_data(Box::new(CharDeviceWrapper::new(dev))); @@ -22,3 +29,23 @@ pub fn add_char_device(name: &str, dev: &'static dyn CharDevice) -> Result<(), E Ok(()) } + +pub fn add_char_device(dev: &'static dyn CharDevice, kind: CharDeviceType) -> Result<(), Errno> { + static TTYS_COUNT: AtomicUsize = AtomicUsize::new(0); + let mut buf = [0u8; 32]; + + let (count, prefix) = match kind { + CharDeviceType::TtySerial => (&TTYS_COUNT, b"ttyS"), + }; + + let value = count.fetch_add(1, Ordering::Relaxed); + if value > 9 { + panic!("Too many character devices of type {:?}", kind); + } + buf[..prefix.len()].copy_from_slice(prefix); + buf[prefix.len()] = (value as u8) + b'0'; + + let name = core::str::from_utf8(&buf[..=prefix.len()]).map_err(|_| Errno::InvalidArgument)?; + + _add_char_device(dev, name) +} diff --git a/kernel/src/init.rs b/kernel/src/init.rs new file mode 100644 index 0000000..323e00d --- /dev/null +++ b/kernel/src/init.rs @@ -0,0 +1,53 @@ +use crate::config::{ConfigKey, CONFIG}; +use crate::fs::{devfs, MemfsBlockAlloc}; +use crate::mem; +use crate::proc::{elf, Process}; +use memfs::Ramfs; +use vfs::{FileMode, Filesystem, Ioctx}; + +#[inline(never)] +pub extern "C" fn init_fn(_arg: usize) -> ! { + let proc = Process::current(); + + debugln!("Running kernel init process"); + + let cfg = CONFIG.lock(); + let initrd_start = cfg.get_usize(ConfigKey::InitrdBase); + let initrd_size = cfg.get_usize(ConfigKey::InitrdSize); + let console = cfg.get_str(ConfigKey::Console); + + if initrd_start == 0 { + panic!("No initrd specified"); + } + + let initrd_start = mem::virtualize(initrd_start); + let fs = + unsafe { Ramfs::open(initrd_start as *mut u8, initrd_size, MemfsBlockAlloc {}).unwrap() }; + let root = fs.root().unwrap(); + + let ioctx = Ioctx::new(root); + + let node = ioctx.find(None, "/init", true).unwrap(); + let mut file = node.open().unwrap(); + + proc.set_ioctx(ioctx); + + // Open stdout + { + let devfs_root = devfs::root(); + let tty_node = if console.is_empty() { + devfs_root.lookup("ttyS0") + } else { + devfs_root.lookup(console) + }.expect("Failed to open stdout for init process"); + + let mut io = proc.io.lock(); + // TODO fd cloning? + io.place_file(tty_node.open().unwrap()).unwrap(); + } + + drop(cfg); + + Process::execve(|space| elf::load_elf(space, &mut file), 0).unwrap(); + panic!("Unreachable"); +} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 7564aa2..3fb9c48 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -7,6 +7,7 @@ const_raw_ptr_deref, const_fn_fn_ptr_basics, const_fn_trait_bound, + const_trait_impl, const_panic, panic_info_message, alloc_error_handler, @@ -27,6 +28,7 @@ extern crate alloc; pub mod debug; pub mod arch; +pub mod config; pub mod dev; pub mod fs; pub mod mem; @@ -35,6 +37,8 @@ pub mod sync; #[allow(missing_docs)] pub mod syscall; pub mod util; +#[allow(missing_docs)] +pub mod init; #[panic_handler] fn panic_handler(pi: &core::panic::PanicInfo) -> ! { diff --git a/kernel/src/mem/phys/mod.rs b/kernel/src/mem/phys/mod.rs index 7e3fc49..d1b678b 100644 --- a/kernel/src/mem/phys/mod.rs +++ b/kernel/src/mem/phys/mod.rs @@ -1,5 +1,6 @@ //! Physical memory management facilities +use crate::config::{ConfigKey, CONFIG}; use crate::mem::PAGE_SIZE; use core::mem::size_of; use error::Errno; @@ -133,12 +134,13 @@ pub unsafe fn init_from_iter + Clone>(iter: T) // Step 3. Initialize the memory manager with available pages let mut manager = ManagerImpl::initialize(mem_base, pages_base, total_pages); let mut usable_pages = 0usize; + let cfg = CONFIG.lock(); 'l0: for region in iter { for addr in (region.start..region.end).step_by(PAGE_SIZE) { if !reserved::is_reserved(addr) { manager.add_page(addr); usable_pages += 1; - if usable_pages == MAX_PAGES { + if usable_pages >= cfg.get_usize(ConfigKey::MemLimit) { break 'l0; } } diff --git a/kernel/src/proc/mod.rs b/kernel/src/proc/mod.rs index 261784f..cd1a838 100644 --- a/kernel/src/proc/mod.rs +++ b/kernel/src/proc/mod.rs @@ -1,6 +1,7 @@ //! Process and thread manipulation facilities use crate::mem; +use crate::init; use crate::sync::IrqSafeSpinLock; use alloc::{boxed::Box, collections::BTreeMap}; @@ -57,53 +58,8 @@ pub(self) static PROCESSES: IrqSafeSpinLock> = /// # Safety /// /// Unsafe: May only be called once. -pub unsafe fn enter(initrd: Option<(usize, usize)>) -> ! { +pub unsafe fn enter() -> ! { SCHED.init(); - let initrd = Box::into_raw(Box::new(initrd)); - - spawn!(fn (initrd_ptr: usize) { - use memfs::Ramfs; - use vfs::{Filesystem, Ioctx, FileMode}; - use crate::fs::{MemfsBlockAlloc, devfs}; - debugln!("Running kernel init process"); - - let initrd = unsafe { *(initrd_ptr as *const Option<(usize, usize)>) }; - if let Some((start, end)) = initrd { - let proc = Process::current(); - let size = end - start; - let start = mem::virtualize(start); - - infoln!("Constructing initrd filesystem in memory, this may take a while..."); - let fs = unsafe { - Ramfs::open(start as *mut u8, size, MemfsBlockAlloc {}).unwrap() - }; - infoln!("Done constructing ramfs"); - let root = fs.root().unwrap(); - let devfs_root = devfs::root(); - - let dir = root.mkdir("dev", FileMode::default_dir()).unwrap(); - dir.mount(devfs_root.clone()).unwrap(); - - let ioctx = Ioctx::new(root); - - // Open a test file - let node = ioctx.find(None, "/init", true).unwrap(); - let mut file = node.open().unwrap(); - - proc.set_ioctx(ioctx); - - // Open stdout - { - let mut io = proc.io.lock(); - let node = io.ioctx().find(None, "/dev/uart0", true).unwrap(); - // TODO fd cloning? - io.place_file(node.open().unwrap()).unwrap(); - } - - Process::execve(|space| elf::load_elf(space, &mut file), 0).unwrap(); - } else { - infoln!("No initrd, exiting!"); - } - }, initrd as usize); + SCHED.enqueue(Process::new_kernel(init::init_fn, 0).unwrap().id()); SCHED.enter(); } diff --git a/kernel/src/sync.rs b/kernel/src/sync.rs index 6102a37..22c8966 100644 --- a/kernel/src/sync.rs +++ b/kernel/src/sync.rs @@ -71,9 +71,9 @@ impl DerefMut for IrqSafeSpinLockGuard<'_, T> { } } -impl fmt::Debug for IrqSafeSpinLockGuard<'_, T> { +impl fmt::Debug for IrqSafeSpinLockGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", &*self) + fmt::Debug::fmt(unsafe { &*self.lock.value.get() }, f) } }