Skip to content

Commit

Permalink
refactor: reuse driver_manager code for drivers initialization from dt
Browse files Browse the repository at this point in the history
  • Loading branch information
n1tram1 authored and Skallwar committed Oct 9, 2024
1 parent 06547b2 commit d46f599
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 94 deletions.
88 changes: 37 additions & 51 deletions kernel/src/driver_manager.rs
Original file line number Diff line number Diff line change
@@ -1,53 +1,47 @@
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<Arc<dyn Driver>>,
}
pub struct DriverManager;

impl DriverManager {
fn new() -> Self {
Self {
drivers: LinkedList::new(),
}
}

pub fn with_devices(dt: &DeviceTree) -> Result<Self, Error> {
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...",
))?;

map_dt_regions(&cons_node)?;

if let Some(cons_driver) =
self.find_driver::<dyn Console + Sync + Send>(&cons_node, drivers::CONSOLE_MATCHERS)
Self::find_driver::<dyn Console + Sync + Send>(&cons_node, drivers::CONSOLE_MATCHERS)
{
self.register_console(cons_driver)?;
kernel_console::set_console(cons_driver)?;
Ok(())
} else {
unmap_dt_regions(&cons_node)?;
Err(Error::NoMatchingDriver("console"))
}
}

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<Item = &'a str> {
let compatible = node
.properties()
Expand All @@ -57,11 +51,7 @@ impl DriverManager {
compatible.split('\0')
}

pub fn find_driver<T: ?Sized>(
&self,
node: &FdtNode,
matchers: &[&Matcher<T>],
) -> Option<Box<T>> {
pub fn find_driver<T: ?Sized>(node: &FdtNode, matchers: &[&Matcher<T>]) -> Option<Box<T>> {
for compat in Self::extract_compatibles(node) {
let matching_constructor = matchers
.iter()
Expand All @@ -76,32 +66,30 @@ impl DriverManager {

None
}
}

fn register_console(&mut self, cons: Box<dyn Console + Sync + Send>) -> Result<(), Error> {
let cons: Arc<dyn Console + Sync + Send> = Arc::from(cons);
self.register_driver(cons.clone());
kernel_console::set_console(cons.clone())?;
fn num_pages(memory_region: &MemoryRegion) -> Result<usize, Error> {
let size = memory_region.size.ok_or(Error::InvalidFdtNode)?;

Ok(())
}

fn register_driver(&mut self, drv: Arc<dyn Driver>) {
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,
)?;
}
}
Expand All @@ -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();
}
}
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/drivers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ impl<T: ?Sized> Matcher<T> {
}
type ConsoleMatcher = Matcher<dyn Console + Send + Sync>;

pub const CONSOLE_MATCHERS: &[&ConsoleMatcher] = &[&pl011::MATCHER, &ns16550::MATCHER];
pub static CONSOLE_MATCHERS: &[&ConsoleMatcher] = &[&pl011::MATCHER, &ns16550::MATCHER];
2 changes: 1 addition & 1 deletion kernel/src/drivers/ns16550.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/drivers/pl011.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
41 changes: 5 additions & 36 deletions kernel/src/generic_main.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -10,8 +11,6 @@ use crate::tests::{self, TestResult};

use log::info;

use hal_core::mm::{PageMap, Permissions, VAddr};

pub fn generic_main<const LAUNCH_TESTS: bool>(dt: DeviceTree, hacky_devices: &[&dyn Driver]) -> ! {
info!("Entered generic_main");
let qemu_exit = QemuExit::new();
Expand All @@ -23,44 +22,14 @@ pub fn generic_main<const LAUNCH_TESTS: bool>(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();
Expand Down
8 changes: 4 additions & 4 deletions kernel/src/kernel_console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Arc<dyn Console + Sync + Send>>,
console: Option<Box<dyn Console + Sync + Send>>,
}

impl KernelConsole {
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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<dyn Console + Sync + Send>) -> Result<(), Error> {
pub fn set_console(new_console: Box<dyn Console + Sync + Send>) -> 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)
Expand Down
1 change: 1 addition & 0 deletions kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

pub extern crate alloc;

pub mod driver_manager;
pub mod drivers;
mod utils;

Expand Down

0 comments on commit d46f599

Please sign in to comment.