diff --git a/Cargo.lock b/Cargo.lock index 5dbabbab2e..6cf50be1dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,10 +195,24 @@ dependencies = [ "ctor_bare", "flatten_objects", "lazy_static", - "spin", + "spin 0.9.8", "static_assertions", ] +[[package]] +name = "arm-gic-driver" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a886a953642fbf21eb5928c49a05f021fae007219ae8cb2dafbf403dfeba974a" +dependencies = [ + "aarch64-cpu 10.0.0", + "bitflags 2.9.1", + "enum_dispatch", + "log", + "rdif-intc", + "tock-registers 0.9.0", +] + [[package]] name = "arm_gicv2" version = "0.1.0" @@ -226,6 +240,23 @@ dependencies = [ "chrono", ] +[[package]] +name = "as-any" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0f477b951e452a0b6b4a10b53ccd569042d1d01729b519e02074a9c0958a063" + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -335,6 +366,7 @@ dependencies = [ name = "axdriver" version = "0.1.0" dependencies = [ + "arm-gic-driver", "axalloc", "axconfig", "axdma", @@ -344,10 +376,14 @@ dependencies = [ "axdriver_net", "axdriver_pci", "axdriver_virtio", + "axerrno", "axhal", "cfg-if", "crate_interface", + "lazyinit", "log", + "memory_addr", + "rdrive", ] [[package]] @@ -382,7 +418,7 @@ dependencies = [ "fxmac_rs", "ixgbe-driver", "log", - "spin", + "spin 0.9.8", ] [[package]] @@ -461,7 +497,7 @@ checksum = "81b87ae981272ca8d5d8f106a4452c63f4b5ac36e17ee8f848ee1b250538b9f8" dependencies = [ "axfs_vfs", "log", - "spin", + "spin 0.9.8", ] [[package]] @@ -472,7 +508,7 @@ checksum = "9f50c26614485d837a3fc09a92f24a226caddc25a30df7e6aaf4bd19b304c399" dependencies = [ "axfs_vfs", "log", - "spin", + "spin 0.9.8", ] [[package]] @@ -573,7 +609,7 @@ dependencies = [ "lazyinit", "log", "smoltcp 0.12.0", - "spin", + "spin 0.9.8", ] [[package]] @@ -755,6 +791,7 @@ dependencies = [ "axconfig", "axdisplay", "axdriver", + "axerrno", "axfs", "axhal", "axlog", @@ -1142,6 +1179,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1157,6 +1206,12 @@ dependencies = [ "log", ] +[[package]] +name = "fdt-parser" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ca123a5721e4a28ef60d6e1600cd0a33a9ab376c4b88de04c99bce757e458b" + [[package]] name = "flatten_objects" version = "0.2.4" @@ -1166,6 +1221,67 @@ dependencies = [ "bitmaps", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "fxmac_rs" version = "0.2.0" @@ -1233,7 +1349,7 @@ dependencies = [ "atomic-polyfill", "hash32 0.2.1", "rustc_version", - "spin", + "spin 0.9.8", "stable_deref_trait", ] @@ -1356,7 +1472,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin", + "spin 0.9.8", ] [[package]] @@ -1552,7 +1668,7 @@ dependencies = [ "cfg-if", "kernel_guard", "percpu_macros", - "spin", + "spin 0.9.8", "x86", ] @@ -1567,6 +1683,18 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1679,6 +1807,120 @@ dependencies = [ "bitflags 2.9.1", ] +[[package]] +name = "rdif-base" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6953f438bbbdf58e55513c31e70fa0f85daba2927e8a59130a04608141bb552" +dependencies = [ + "as-any", + "async-trait", + "rdif-def", + "thiserror", +] + +[[package]] +name = "rdif-block" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7b8e19dc3cb6cd7241085a9560a91d4346edbc525bcbfc3c86e5eeb11559c19" +dependencies = [ + "cfg-if", + "rdif-base", +] + +[[package]] +name = "rdif-clk" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee94bb098e921346fffa3bb8d18e80fbb903c8ad2cb0a103ee9a65ae1a7d77fa" +dependencies = [ + "rdif-base", +] + +[[package]] +name = "rdif-def" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c238eb44d86fabc99028adc973f896ce2202aeb6184cc8b89863f2d157d7ca06" +dependencies = [ + "thiserror", +] + +[[package]] +name = "rdif-intc" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e7622f78dc9b40958500119553f3c15b9bb9829002d87d0f4b114ebe302a40" +dependencies = [ + "cfg-if", + "rdif-base", + "thiserror", +] + +[[package]] +name = "rdif-power" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37eb02828548e3d1bb13d2a5d892219dfa295c3c0c00a1a647a68f947e5d070a" +dependencies = [ + "rdif-base", +] + +[[package]] +name = "rdif-serial" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3381d491f588cfb20dfa661dc374411a2cb91c751b2e18516e0d2edca6a58e" +dependencies = [ + "futures", + "rdif-base", + "spin_on", + "thiserror", +] + +[[package]] +name = "rdif-systick" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cdd145eab68c38f23dfcc8b3b1ed20c48bbb1a4278dd9c7bf64e9219cc61158" +dependencies = [ + "rdif-base", +] + +[[package]] +name = "rdrive" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ce47e5a3d10943dfdb8c31dcca7a91c353ea43f4ac2eb72c92462e83a2baa4" +dependencies = [ + "enum_dispatch", + "fdt-parser", + "log", + "paste", + "rdif-base", + "rdif-block", + "rdif-clk", + "rdif-intc", + "rdif-power", + "rdif-serial", + "rdif-systick", + "rdrive-macros", + "spin 0.10.0", + "thiserror", +] + +[[package]] +name = "rdrive-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab3105c9af32e901a2adc7d920b39ff8b6ee0f6f0b7dfdeaf18f306ec12606f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "regex" version = "1.11.1" @@ -1863,6 +2105,24 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spin_on" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076e103ed41b9864aa838287efe5f4e3a7a0362dd00671ae62a212e5e4612da2" +dependencies = [ + "pin-utils", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/api/axfeat/Cargo.toml b/api/axfeat/Cargo.toml index dedc478203..b7b1ba04d6 100644 --- a/api/axfeat/Cargo.toml +++ b/api/axfeat/Cargo.toml @@ -56,6 +56,7 @@ display = ["alloc", "paging", "axdriver/virtio-gpu", "dep:axdisplay", "axruntime rtc = ["axhal/rtc", "axruntime/rtc"] # Device drivers +driver-dyn = ["axruntime/driver-dyn","axdriver?/dyn"] bus-mmio = ["axdriver?/bus-mmio"] bus-pci = ["axdriver?/bus-pci"] driver-ramdisk = ["axdriver?/ramdisk", "axfs?/use-ramdisk"] diff --git a/modules/axdriver/Cargo.toml b/modules/axdriver/Cargo.toml index a5e16a9f38..5e5e453566 100644 --- a/modules/axdriver/Cargo.toml +++ b/modules/axdriver/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/arceos-org/arceos/tree/main/modules/axdriver" documentation = "https://arceos-org.github.io/arceos/axdriver/index.html" [features] -dyn = [] +dyn = ["dep:rdrive", "dep:arm-gic-driver"] bus-mmio = [] bus-pci = ["dep:axdriver_pci", "dep:axhal", "dep:axconfig"] net = ["axdriver_net"] @@ -46,3 +46,10 @@ axalloc = { workspace = true, optional = true } axhal = { workspace = true, optional = true } axconfig = { workspace = true, optional = true } axdma = { workspace = true, optional = true } +rdrive = { version = "0.15", optional = true } +axerrno = "0.1" +lazyinit = "0.2" +memory_addr = "0.4" + +[target.'cfg(target_arch = "aarch64")'.dependencies] +arm-gic-driver = { version = "0.14", optional = true } \ No newline at end of file diff --git a/modules/axdriver/src/dyn_drivers/blk/mod.rs b/modules/axdriver/src/dyn_drivers/blk/mod.rs new file mode 100644 index 0000000000..0a67772f6b --- /dev/null +++ b/modules/axdriver/src/dyn_drivers/blk/mod.rs @@ -0,0 +1,87 @@ +use axdriver_base::{BaseDriverOps, DevError, DevResult, DeviceType}; +use axdriver_block::BlockDriverOps; +use rdrive::{Device, driver::block::io}; + +#[cfg(feature = "virtio-blk")] +mod virtio; + +pub struct Block(Device); + +impl BaseDriverOps for Block { + fn device_type(&self) -> DeviceType { + DeviceType::Block + } + fn device_name(&self) -> &str { + self.0.descriptor().name + } +} + +impl BlockDriverOps for Block { + fn num_blocks(&self) -> u64 { + self.0.lock().unwrap().num_blocks() as _ + } + fn block_size(&self) -> usize { + self.0.lock().unwrap().block_size() + } + fn flush(&mut self) -> DevResult { + self.0 + .lock() + .unwrap() + .flush() + .map_err(maping_io_err_to_dev_err) + } + + fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DevResult { + self.0 + .lock() + .unwrap() + .read_block(block_id as _, buf) + .map_err(maping_io_err_to_dev_err) + } + + fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult { + self.0 + .lock() + .unwrap() + .write_block(block_id as _, buf) + .map_err(maping_io_err_to_dev_err) + } +} + +impl From> for Block { + fn from(base: Device) -> Self { + Self(base) + } +} + +fn maping_io_err_to_dev_err(err: io::Error) -> DevError { + match err.kind { + io::ErrorKind::Other(_error) => DevError::Io, + io::ErrorKind::NotAvailable => DevError::BadState, + io::ErrorKind::BrokenPipe => DevError::BadState, + io::ErrorKind::InvalidParameter { name: _ } => DevError::InvalidParam, + io::ErrorKind::InvalidData => DevError::InvalidParam, + io::ErrorKind::TimedOut => DevError::Io, + io::ErrorKind::Interrupted => DevError::Again, + io::ErrorKind::Unsupported => DevError::Unsupported, + io::ErrorKind::OutOfMemory => DevError::NoMemory, + io::ErrorKind::WriteZero => DevError::InvalidParam, + } +} + +fn maping_dev_err_to_io_err(err: DevError) -> io::Error { + let kind = match err { + DevError::Again => io::ErrorKind::Interrupted, + DevError::AlreadyExists => io::ErrorKind::Other("Already exists".into()), + DevError::BadState => io::ErrorKind::BrokenPipe, + DevError::InvalidParam => io::ErrorKind::InvalidData, + DevError::Io => io::ErrorKind::Other("I/O error".into()), + DevError::NoMemory => io::ErrorKind::OutOfMemory, + DevError::ResourceBusy => io::ErrorKind::Other("Resource busy".into()), + DevError::Unsupported => io::ErrorKind::Unsupported, + }; + io::Error { + kind, + success_pos: 0, + } +} diff --git a/modules/axdriver/src/dyn_drivers/blk/virtio.rs b/modules/axdriver/src/dyn_drivers/blk/virtio.rs new file mode 100644 index 0000000000..05f5e21a20 --- /dev/null +++ b/modules/axdriver/src/dyn_drivers/blk/virtio.rs @@ -0,0 +1,99 @@ +extern crate alloc; + +use alloc::format; +use axdriver_base::DeviceType; +use axdriver_block::BlockDriverOps; +use axdriver_virtio::MmioTransport; +use axhal::mem::PhysAddr; +use rdrive::{ + DriverGeneric, PlatformDevice, driver::block::*, module_driver, probe::OnProbeError, + register::FdtInfo, +}; + +use crate::dyn_drivers::blk::maping_dev_err_to_io_err; +use crate::dyn_drivers::iomap; +use crate::virtio::VirtIoHalImpl; + +type Device = axdriver_virtio::VirtIoBlkDev; + +module_driver!( + name: "Virtio Block", + level: ProbeLevel::PostKernel, + priority: ProbePriority::DEFAULT, + probe_kinds: &[ + ProbeKind::Fdt { + compatibles: &["virtio,mmio"], + on_probe: probe + } + ], +); + +fn probe(info: FdtInfo<'_>, plat_dev: PlatformDevice) -> Result<(), OnProbeError> { + let base_reg = info + .node + .reg() + .and_then(|mut regs| regs.next()) + .ok_or(OnProbeError::other(alloc::format!( + "[{}] has no reg", + info.node.name() + )))?; + + let mmio_size = base_reg.size.unwrap_or(0x1000); + let mmio_base = PhysAddr::from_usize(base_reg.address as usize); + + let mmio_base = iomap(mmio_base, mmio_size)?.as_ptr(); + + let (ty, transport) = + axdriver_virtio::probe_mmio_device(mmio_base, mmio_size).ok_or(OnProbeError::NotMatch)?; + + if ty != DeviceType::Block { + return Err(OnProbeError::NotMatch); + } + + let dev = Device::try_new(transport).map_err(|e| { + OnProbeError::other(format!( + "failed to initialize Virtio Block device at [PA:{mmio_base:?},): {e:?}" + )) + })?; + + let dev = BlockDivce(dev); + plat_dev.register_block(dev); + debug!("virtio block device registered successfully"); + Ok(()) +} + +struct BlockDivce(Device); + +impl DriverGeneric for BlockDivce { + fn open(&mut self) -> Result<(), rdrive::KError> { + Ok(()) + } + + fn close(&mut self) -> Result<(), rdrive::KError> { + Ok(()) + } +} + +impl rdrive::driver::block::Interface for BlockDivce { + fn num_blocks(&self) -> usize { + self.0.num_blocks() as _ + } + + fn block_size(&self) -> usize { + self.0.block_size() + } + + fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> Result<(), io::Error> { + self.0 + .read_block(block_id as u64, buf) + .map_err(maping_dev_err_to_io_err) + } + fn write_block(&mut self, block_id: usize, buf: &[u8]) -> Result<(), io::Error> { + self.0 + .write_block(block_id as u64, buf) + .map_err(maping_dev_err_to_io_err) + } + fn flush(&mut self) -> Result<(), io::Error> { + self.0.flush().map_err(maping_dev_err_to_io_err) + } +} diff --git a/modules/axdriver/src/dyn_drivers/intc/gicv2.rs b/modules/axdriver/src/dyn_drivers/intc/gicv2.rs new file mode 100644 index 0000000000..2fb3f06863 --- /dev/null +++ b/modules/axdriver/src/dyn_drivers/intc/gicv2.rs @@ -0,0 +1,44 @@ +extern crate alloc; + +use alloc::format; +use arm_gic_driver::v2::Gic; +use rdrive::{PlatformDevice, module_driver, probe::OnProbeError, register::FdtInfo}; + +use crate::dyn_drivers::iomap; + +module_driver!( + name: "GICv2", + level: ProbeLevel::PreKernel, + priority: ProbePriority::INTC, + probe_kinds: &[ + ProbeKind::Fdt { + compatibles: &["arm,cortex-a15-gic", "arm,gic-400"], + on_probe: probe_gic + }, + ] , +); + +fn probe_gic(info: FdtInfo<'_>, dev: PlatformDevice) -> Result<(), OnProbeError> { + let mut reg = info.node.reg().ok_or(OnProbeError::other(format!( + "[{}] has no reg", + info.node.name() + )))?; + + let gicd_reg = reg.next().unwrap(); + let gicc_reg = reg.next().unwrap(); + + let gicd = iomap( + (gicd_reg.address as usize).into(), + gicd_reg.size.unwrap_or(0x1000), + )?; + let gicc = iomap( + (gicc_reg.address as usize).into(), + gicc_reg.size.unwrap_or(0x1000), + )?; + + let gic = Gic::new(gicd, gicc); + + dev.register_intc(gic); + + Ok(()) +} diff --git a/modules/axdriver/src/dyn_drivers/intc/gicv3.rs b/modules/axdriver/src/dyn_drivers/intc/gicv3.rs new file mode 100644 index 0000000000..496a05564d --- /dev/null +++ b/modules/axdriver/src/dyn_drivers/intc/gicv3.rs @@ -0,0 +1,44 @@ +extern crate alloc; + +use alloc::format; +use arm_gic_driver::v3::Gic; +use rdrive::{PlatformDevice, module_driver, probe::OnProbeError, register::FdtInfo}; + +use crate::dyn_drivers::iomap; + +module_driver!( + name: "GICv3", + level: ProbeLevel::PreKernel, + priority: ProbePriority::INTC, + probe_kinds: &[ + ProbeKind::Fdt { + compatibles: &["arm,gic-v3"], + on_probe: probe_gic + } + ], +); + +fn probe_gic(info: FdtInfo<'_>, dev: PlatformDevice) -> Result<(), OnProbeError> { + let mut reg = info.node.reg().ok_or(OnProbeError::other(format!( + "[{}] has no reg", + info.node.name() + )))?; + + let gicd_reg = reg.next().unwrap(); + let gicr_reg = reg.next().unwrap(); + + let gicd = iomap( + (gicd_reg.address as usize).into(), + gicd_reg.size.unwrap_or(0x1000), + )?; + let gicr = iomap( + (gicr_reg.address as usize).into(), + gicr_reg.size.unwrap_or(0x1000), + )?; + + let gic = Gic::new(gicd, gicr); + + dev.register_intc(gic); + + Ok(()) +} diff --git a/modules/axdriver/src/dyn_drivers/intc/mod.rs b/modules/axdriver/src/dyn_drivers/intc/mod.rs new file mode 100644 index 0000000000..867b15ecb7 --- /dev/null +++ b/modules/axdriver/src/dyn_drivers/intc/mod.rs @@ -0,0 +1,4 @@ +#[cfg(target_arch = "aarch64")] +mod gicv2; +#[cfg(target_arch = "aarch64")] +mod gicv3; diff --git a/modules/axdriver/src/dyn_drivers/mod.rs b/modules/axdriver/src/dyn_drivers/mod.rs new file mode 100644 index 0000000000..01788b0763 --- /dev/null +++ b/modules/axdriver/src/dyn_drivers/mod.rs @@ -0,0 +1,78 @@ +use core::{error::Error, ops::Deref, ptr::NonNull}; + +use alloc::{boxed::Box, format, string::ToString}; +use axerrno::{AxError, AxResult}; +use axhal::mem::{PhysAddr, VirtAddr, phys_to_virt}; +use lazyinit::LazyInit; +use memory_addr::MemoryAddr; +use rdrive::register::{DriverRegister, DriverRegisterSlice}; + +mod intc; + +#[cfg(feature = "block")] +pub mod blk; + +/// A function type that maps a physical address to a virtual address. map flags should be read/write/device. +pub type IoMapFunc = fn(PhysAddr, usize) -> AxResult; + +static IO_MAP_FUNC: LazyInit = LazyInit::new(); + +/// Sets up the device driver subsystem. +pub fn setup(dtb: usize, io_map_func: IoMapFunc) { + IO_MAP_FUNC.init_once(io_map_func); + if dtb == 0 { + warn!("Device tree base address is 0, skipping device driver setup."); + return; + } + + let dtb_virt = phys_to_virt(dtb.into()); + if let Some(dtb) = NonNull::new(dtb_virt.as_mut_ptr()) { + rdrive::init(rdrive::Platform::Fdt { addr: dtb }).unwrap(); + rdrive::register_append(&driver_registers()); + rdrive::probe_pre_kernel().unwrap(); + } +} + +#[allow(unused)] +/// maps a mmio physical address to a virtual address. +fn iomap(addr: PhysAddr, size: usize) -> Result, Box> { + let end = (addr + size).align_up_4k(); + let start = addr.align_down_4k(); + let offset = addr - start; + let size = end - start; + let iomap = *IO_MAP_FUNC + .get() + .ok_or_else(|| "IO map function not initialized".to_string())?; + + let virt = match iomap(start, size) { + Ok(val) => val, + Err(AxError::AlreadyExists) => phys_to_virt(start), + Err(e) => { + return Err(format!( + "Failed to map MMIO region: {e:?} (addr: {start:?}, size: {size:#x})" + ) + .into()); + } + }; + let start_virt = virt + offset; + Ok(unsafe { NonNull::new_unchecked(start_virt.as_mut_ptr()) }) +} + +fn driver_registers() -> impl Deref { + unsafe extern "C" { + fn __sdriver_register(); + fn __edriver_register(); + } + + unsafe { + let len = __edriver_register as usize - __sdriver_register as usize; + + if len == 0 { + return DriverRegisterSlice::empty(); + } + + let data = core::slice::from_raw_parts(__sdriver_register as _, len); + + DriverRegisterSlice::from_raw(data) + } +} diff --git a/modules/axdriver/src/lib.rs b/modules/axdriver/src/lib.rs index cc9144645a..09829c6ed0 100644 --- a/modules/axdriver/src/lib.rs +++ b/modules/axdriver/src/lib.rs @@ -67,6 +67,7 @@ extern crate alloc; #[macro_use] mod macros; +#[cfg(not(feature = "dyn"))] mod bus; mod drivers; mod dummy; @@ -78,6 +79,12 @@ mod virtio; #[cfg(feature = "ixgbe")] mod ixgbe; +#[cfg(feature = "dyn")] +mod dyn_drivers; + +#[cfg(feature = "dyn")] +pub use dyn_drivers::{IoMapFunc, setup}; + pub mod prelude; #[allow(unused_imports)] @@ -119,18 +126,25 @@ impl AllDevices { /// Probes all supported devices. fn probe(&mut self) { - for_each_drivers!(type Driver, { - if let Some(dev) = Driver::probe_global() { - info!( - "registered a new {:?} device: {:?}", - dev.device_type(), - dev.device_name(), - ); - self.add_device(dev); - } - }); - - self.probe_bus_devices(); + #[cfg(feature = "dyn")] + for dev in structs::probe_all_devices() { + self.add_device(dev); + } + #[cfg(not(feature = "dyn"))] + { + for_each_drivers!(type Driver, { + if let Some(dev) = Driver::probe_global() { + info!( + "registered a new {:?} device: {:?}", + dev.device_type(), + dev.device_name(), + ); + self.add_device(dev); + } + }); + + self.probe_bus_devices(); + } } /// Adds one device into the corresponding container, according to its device category. diff --git a/modules/axdriver/src/structs/dyn.rs b/modules/axdriver/src/structs/dyn.rs index c4d04cb97f..95a3c57ec0 100644 --- a/modules/axdriver/src/structs/dyn.rs +++ b/modules/axdriver/src/structs/dyn.rs @@ -1,7 +1,10 @@ #![allow(unused_imports)] +use core::{ops::Deref, ptr::NonNull}; + use crate::prelude::*; use alloc::{boxed::Box, vec, vec::Vec}; +use rdrive::register::{DriverRegister, DriverRegisterSlice}; /// The unified type of the NIC devices. #[cfg(feature = "net")] @@ -83,3 +86,19 @@ impl Default for AxDeviceContainer { Self(Default::default()) } } + +pub fn probe_all_devices() -> Vec { + rdrive::probe_all(true).unwrap(); + #[allow(unused_mut)] + let mut devices = Vec::new(); + #[cfg(feature = "block")] + { + let ls = rdrive::get_list::(); + for dev in ls { + devices.push(super::AxDeviceEnum::from_block( + crate::dyn_drivers::blk::Block::from(dev), + )); + } + } + devices +} diff --git a/modules/axhal/linker.lds.S b/modules/axhal/linker.lds.S index 2b11d95fa0..d84a7a48d8 100644 --- a/modules/axhal/linker.lds.S +++ b/modules/axhal/linker.lds.S @@ -36,6 +36,11 @@ SECTIONS _sdata = .; *(.data.boot_page_table) . = ALIGN(4K); + + __sdriver_register = .; + KEEP(*(.driver.register*)) + __edriver_register = .; + *(.data .data.*) *(.sdata .sdata.*) *(.got .got.*) diff --git a/modules/axruntime/Cargo.toml b/modules/axruntime/Cargo.toml index 335ca4fb11..a25fd0c777 100644 --- a/modules/axruntime/Cargo.toml +++ b/modules/axruntime/Cargo.toml @@ -17,6 +17,7 @@ irq = ["axhal/irq", "axtask?/irq", "percpu"] tls = ["axhal/tls", "axtask?/tls"] alloc = ["axalloc"] paging = ["axhal/paging", "axmm"] +driver-dyn = ["axdriver/dyn"] multitask = ["axtask/multitask"] fs = ["axdriver", "axfs"] @@ -36,6 +37,7 @@ axnet = { workspace = true, optional = true } axdisplay = { workspace = true, optional = true } axtask = { workspace = true, optional = true } axplat = "0.1" +axerrno = "0.1" crate_interface = "0.1" percpu = { version = "0.2", optional = true } diff --git a/modules/axruntime/src/lib.rs b/modules/axruntime/src/lib.rs index a1462cda15..929524a9c5 100644 --- a/modules/axruntime/src/lib.rs +++ b/modules/axruntime/src/lib.rs @@ -154,6 +154,9 @@ pub fn rust_main(cpu_id: usize, arg: usize) -> ! { #[cfg(feature = "paging")] axmm::init_memory_management(); + #[cfg(feature = "driver-dyn")] + axdriver::setup(arg, iomap); + info!("Initialize platform devices..."); axhal::init_later(cpu_id, arg); @@ -275,3 +278,20 @@ fn init_tls() { unsafe { axhal::asm::write_thread_pointer(main_tls.tls_ptr() as usize) }; core::mem::forget(main_tls); } + +#[cfg(feature = "driver-dyn")] +fn iomap(addr: axhal::mem::PhysAddr, size: usize) -> axerrno::AxResult { + let virt = axhal::mem::phys_to_virt(addr); + #[cfg(feature = "paging")] + { + use axhal::paging::MappingFlags; + + axmm::kernel_aspace().lock().map_linear( + virt, + addr, + size, + MappingFlags::DEVICE | MappingFlags::READ | MappingFlags::WRITE, + )?; + } + Ok(virt) +} diff --git a/ulib/axstd/Cargo.toml b/ulib/axstd/Cargo.toml index bf05a66927..95a63729c0 100644 --- a/ulib/axstd/Cargo.toml +++ b/ulib/axstd/Cargo.toml @@ -66,6 +66,7 @@ rtc = ["axfeat/rtc"] # Device drivers bus-mmio = ["axfeat/bus-mmio"] bus-pci = ["axfeat/bus-pci"] +driver-dyn = ["axfeat/driver-dyn"] driver-ramdisk = ["axfeat/driver-ramdisk"] driver-ixgbe = ["axfeat/driver-ixgbe"] driver-fxmac = ["axfeat/driver-fxmac"]