From d1320cde0642ecd9dd56ffeca89712ffcbe1ca75 Mon Sep 17 00:00:00 2001 From: Martin Schmidt Date: Wed, 2 Oct 2024 23:07:42 +0200 Subject: [PATCH] refactor: reuse driver_manager code for drivers initialization from dt --- kernel/src/driver_manager.rs | 88 +++++++++++++++-------------------- kernel/src/drivers/mod.rs | 2 +- kernel/src/drivers/ns16550.rs | 2 +- kernel/src/drivers/pl011.rs | 2 +- kernel/src/generic_main.rs | 41 ++-------------- kernel/src/kernel_console.rs | 8 ++-- kernel/src/lib.rs | 1 + 7 files changed, 50 insertions(+), 94 deletions(-) diff --git a/kernel/src/driver_manager.rs b/kernel/src/driver_manager.rs index 4756f7d8..fb34d74b 100644 --- a/kernel/src/driver_manager.rs +++ b/kernel/src/driver_manager.rs @@ -1,36 +1,20 @@ -use alloc::{boxed::Box, collections::LinkedList, sync::Arc}; +use alloc::boxed::Box; use super::device_tree::DeviceTree; use super::drivers::{self, Matcher}; use super::error::Error; use super::kernel_console; -use drivers::{Console, Driver}; -use fdt::node::FdtNode; +use drivers::Console; +use fdt::{node::FdtNode, standard_nodes::MemoryRegion}; -use crate::hal; -use crate::mm::alloc_pages_for_hal; -use hal_core::mm::{PageMap, Permissions}; +use crate::globals; +use crate::HAL; +use hal_core::mm::{NullPageAllocator, PageMap, Permissions}; -pub struct DriverManager { - drivers: LinkedList>, -} +pub struct DriverManager; impl DriverManager { - fn new() -> Self { - Self { - drivers: LinkedList::new(), - } - } - - pub fn with_devices(dt: &DeviceTree) -> Result { - let mut mgr = Self::new(); - - mgr.do_console(dt)?; - - Ok(mgr) - } - - fn do_console(&mut self, dt: &DeviceTree) -> Result<(), Error> { + pub fn do_console(dt: &DeviceTree) -> Result<(), Error> { let cons_node = dt.console_node().ok_or(Error::DeviceNotFound( "dtb doesn't contain a console node...", ))?; @@ -38,9 +22,9 @@ impl DriverManager { map_dt_regions(&cons_node)?; if let Some(cons_driver) = - self.find_driver::(&cons_node, drivers::CONSOLE_MATCHERS) + Self::find_driver::(&cons_node, drivers::CONSOLE_MATCHERS) { - self.register_console(cons_driver)?; + kernel_console::set_console(cons_driver)?; Ok(()) } else { unmap_dt_regions(&cons_node)?; @@ -48,6 +32,16 @@ impl DriverManager { } } + pub fn map_irq_chip(dt: &DeviceTree) -> Result<(), Error> { + let intc = dt + .interrupt_controller() + .expect("device tree has no interrupt-controller node..."); + + map_dt_regions(&intc)?; + + Ok(()) + } + fn extract_compatibles<'a>(node: &'a FdtNode) -> impl Iterator { let compatible = node .properties() @@ -57,11 +51,7 @@ impl DriverManager { compatible.split('\0') } - pub fn find_driver( - &self, - node: &FdtNode, - matchers: &[&Matcher], - ) -> Option> { + pub fn find_driver(node: &FdtNode, matchers: &[&Matcher]) -> Option> { for compat in Self::extract_compatibles(node) { let matching_constructor = matchers .iter() @@ -76,32 +66,30 @@ impl DriverManager { None } +} - fn register_console(&mut self, cons: Box) -> Result<(), Error> { - let cons: Arc = Arc::from(cons); - self.register_driver(cons.clone()); - kernel_console::set_console(cons.clone())?; +fn num_pages(memory_region: &MemoryRegion) -> Result { + let size = memory_region.size.ok_or(Error::InvalidFdtNode)?; - Ok(()) - } - - fn register_driver(&mut self, drv: Arc) { - self.drivers.push_back(drv); + if size < HAL.page_size() { + Ok(1) + } else { + Ok(size / HAL.page_size()) } } fn map_dt_regions(node: &FdtNode) -> Result<(), Error> { if let Some(reg) = node.reg() { + let mut kpt = HAL.kpt().lock(); for memory_region in reg { let start = memory_region.starting_address as usize; - let size = memory_region.size.ok_or(Error::InvalidFdtNode)?; + let num_pages = num_pages(&memory_region)?; - assert!(size % hal::mm::PAGE_SIZE == 0); - hal::mm::current().identity_map_range( + kpt.identity_map_range( start.into(), - size / hal::mm::PAGE_SIZE, + num_pages, Permissions::READ | Permissions::WRITE, - alloc_pages_for_hal, + &globals::PHYSICAL_MEMORY_MANAGER, )?; } } @@ -110,18 +98,16 @@ fn map_dt_regions(node: &FdtNode) -> Result<(), Error> { } fn unmap_dt_regions(node: &FdtNode) -> Result<(), Error> { - let pagesize = hal::mm::PAGE_SIZE; - if let Some(reg) = node.reg() { for memory_region in reg { let start = memory_region.starting_address as usize; let size = memory_region.size.ok_or(Error::InvalidFdtNode)?; - assert!(size % hal::mm::PAGE_SIZE == 0); + assert!(size % HAL.page_size() == 0); - let kernel_pt = hal::mm::current(); - for page in (start..start + size).step_by(pagesize) { + let mut kernel_pt = HAL.kpt().lock(); + for page in (start..start + size).step_by(HAL.page_size()) { kernel_pt - .add_invalid_entry(page.into(), |_| unreachable!()) + .add_invalid_entry(page.into(), &NullPageAllocator) .unwrap(); } } diff --git a/kernel/src/drivers/mod.rs b/kernel/src/drivers/mod.rs index 4de8f6ee..1fdf9606 100644 --- a/kernel/src/drivers/mod.rs +++ b/kernel/src/drivers/mod.rs @@ -31,4 +31,4 @@ impl Matcher { } type ConsoleMatcher = Matcher; -pub const CONSOLE_MATCHERS: &[&ConsoleMatcher] = &[&pl011::MATCHER, &ns16550::MATCHER]; +pub static CONSOLE_MATCHERS: &[&ConsoleMatcher] = &[&pl011::MATCHER, &ns16550::MATCHER]; diff --git a/kernel/src/drivers/ns16550.rs b/kernel/src/drivers/ns16550.rs index 9946e4c5..3ed09f93 100644 --- a/kernel/src/drivers/ns16550.rs +++ b/kernel/src/drivers/ns16550.rs @@ -81,7 +81,7 @@ impl Console for Ns16550 { } } -pub(super) const MATCHER: ConsoleMatcher = ConsoleMatcher { +pub(super) static MATCHER: ConsoleMatcher = ConsoleMatcher { compatibles: &["ns16550a"], constructor: |reg| { Ok(Box::new(Ns16550::new( diff --git a/kernel/src/drivers/pl011.rs b/kernel/src/drivers/pl011.rs index d14a0505..2413a726 100644 --- a/kernel/src/drivers/pl011.rs +++ b/kernel/src/drivers/pl011.rs @@ -62,7 +62,7 @@ impl Pl011 { } } -pub(super) const MATCHER: ConsoleMatcher = ConsoleMatcher { +pub(super) static MATCHER: ConsoleMatcher = ConsoleMatcher { compatibles: &["arm,pl011"], constructor: |reg| { Ok(Box::new(Pl011::new( diff --git a/kernel/src/generic_main.rs b/kernel/src/generic_main.rs index 80d9a5a2..d668b3f2 100644 --- a/kernel/src/generic_main.rs +++ b/kernel/src/generic_main.rs @@ -1,4 +1,5 @@ use super::device_tree::DeviceTree; +use super::driver_manager::DriverManager; use super::drivers::qemuexit::QemuExit; use super::drivers::Driver; use super::globals; @@ -10,8 +11,6 @@ use crate::tests::{self, TestResult}; use log::info; -use hal_core::mm::{PageMap, Permissions, VAddr}; - pub fn generic_main(dt: DeviceTree, hacky_devices: &[&dyn Driver]) -> ! { info!("Entered generic_main"); let qemu_exit = QemuExit::new(); @@ -23,44 +22,14 @@ pub fn generic_main(dt: DeviceTree, hacky_devices: &[& globals::PHYSICAL_MEMORY_MANAGER .init_from_device_tree(&dt) .unwrap(); + // Below this comment, using alloc is possible. mm::map_address_space(&dt, devices).expect("failed to map the addres space"); - // Driver stuff - // let _drvmgr = DriverManager::with_devices(&dt).unwrap(); - - cfg_if::cfg_if! { - if #[cfg(target_arch = "aarch64")] { - // XXX: Ideally we'd read the device tree but we're not doing for now... - log::trace!("mapping gic pages"); - let (gicd_base, gicc_base) = (0x800_0000, 0x801_0000); - HAL.kpt().lock().identity_map_range( - VAddr::new(gicd_base), - 0x0001_0000 / HAL.page_size(), - Permissions::READ | Permissions::WRITE, - &globals::PHYSICAL_MEMORY_MANAGER - ).unwrap(); - HAL.kpt().lock().identity_map_range( - VAddr::new(gicc_base), - 0x0001_0000 / HAL.page_size(), - Permissions::READ | Permissions::WRITE, - &globals::PHYSICAL_MEMORY_MANAGER - ).unwrap(); - } else if #[cfg(target_arch = "riscv64")] { - let base = 0xc000000; - let max_offset = 0x3FFFFFC; - HAL.kpt().lock().identity_map_range( - VAddr::new(base), - max_offset / HAL.page_size() + 1, - Permissions::READ | Permissions::WRITE, - &globals::PHYSICAL_MEMORY_MANAGER, - ).unwrap(); - } - } + DriverManager::do_console(&dt).expect("couldn't initialize a console from the device tree"); + DriverManager::map_irq_chip(&dt).expect("failed to map irq chip from the device tree"); log::trace!("initializing irq chip"); - - crate::HAL - .init_irq_chip(&globals::PHYSICAL_MEMORY_MANAGER) + HAL.init_irq_chip(&globals::PHYSICAL_MEMORY_MANAGER) .expect("initialization of irq chip failed"); HAL.unmask_interrupts(); diff --git a/kernel/src/kernel_console.rs b/kernel/src/kernel_console.rs index 56762c61..c0f49f5f 100644 --- a/kernel/src/kernel_console.rs +++ b/kernel/src/kernel_console.rs @@ -3,14 +3,14 @@ use core::fmt::{self, Write}; use crate::drivers::Console; use crate::Error; -use alloc::sync::Arc; +use alloc::boxed::Box; use log::{Level, LevelFilter, Metadata, Record}; use spin::Mutex; struct KernelConsole { earlyinit_console: Option<&'static (dyn Console + Sync)>, - console: Option>, + console: Option>, } impl KernelConsole { @@ -38,7 +38,7 @@ impl fmt::Write for KernelConsole { } } -fn print_fmt(args: fmt::Arguments) { +pub fn print_fmt(args: fmt::Arguments) { KERNEL_CONSOLE.lock().write_fmt(args).unwrap(); } @@ -72,7 +72,7 @@ pub fn set_earlyinit_console(new_console: &'static (dyn Console + Sync)) { KERNEL_CONSOLE.lock().earlyinit_console = Some(new_console); } -pub fn set_console(new_console: Arc) -> Result<(), Error> { +pub fn set_console(new_console: Box) -> Result<(), Error> { KERNEL_CONSOLE.lock().console = Some(new_console); // TODO: return an error if the error already was some (unless we consider it is ok) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index cd3d56dc..36e3c23c 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -12,6 +12,7 @@ pub extern crate alloc; +pub mod driver_manager; pub mod drivers; mod utils;