Skip to content

Commit 79117c2

Browse files
committed
feat: add dyn platform and driver support
feat: add iomap api feat: add gicv2 gicv3 - Introduced a new block driver module with implementations for block operations. - Added virtio block driver support with MMIO transport. - Refactored interrupt controller (GIC) driver probes to use OnProbeError for error handling. - Enhanced dynamic driver probing to include block devices when the "block" feature is enabled. - Improved error handling in block driver operations by mapping errors between driver and I/O layers. feat: add axklib
1 parent 73ce902 commit 79117c2

File tree

24 files changed

+1398
-184
lines changed

24 files changed

+1398
-184
lines changed

Cargo.lock

Lines changed: 494 additions & 144 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ members = [
1717
"modules/axsync",
1818
"modules/axtask",
1919
"modules/axipi",
20+
"modules/axklib-impl",
2021

2122
"api/axfeat",
2223
"api/arceos_api",
2324
"api/arceos_posix_api",
25+
"api/axklib",
2426

2527
"ulib/axstd",
2628
"ulib/axlibc",
@@ -51,6 +53,7 @@ axlibc = { path = "ulib/axlibc" }
5153
arceos_api = { path = "api/arceos_api" }
5254
arceos_posix_api = { path = "api/arceos_posix_api" }
5355
axfeat = { path = "api/axfeat" }
56+
axklib = {path = "api/axklib"}
5457

5558
axalloc = { path = "modules/axalloc" }
5659
axconfig = { path = "modules/axconfig" }

api/axfeat/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ smp = ["axhal/smp", "axruntime/smp", "axtask?/smp", "kspin/smp"]
1919
fp-simd = ["axhal/fp-simd"]
2020

2121
# Interrupts
22-
irq = ["axhal/irq", "axruntime/irq", "axtask?/irq"]
22+
irq = ["axhal/irq", "axruntime/irq", "axtask?/irq", "axklib-impl?/irq"]
2323
ipi = ["irq", "dep:axipi", "axhal/ipi", "axruntime/ipi"]
2424

2525
# Custom or default platforms
@@ -57,6 +57,7 @@ display = ["alloc", "paging", "axdriver/virtio-gpu", "dep:axdisplay", "axruntime
5757
rtc = ["axhal/rtc", "axruntime/rtc"]
5858

5959
# Device drivers
60+
driver-dyn = ["axruntime/driver-dyn","axdriver?/dyn", "dep:axklib-impl"]
6061
bus-mmio = ["axdriver?/bus-mmio"]
6162
bus-pci = ["axdriver?/bus-pci"]
6263
driver-ramdisk = ["axdriver?/ramdisk", "axfs?/use-ramdisk"]
@@ -85,3 +86,4 @@ axsync = { workspace = true, optional = true }
8586
axtask = { workspace = true, optional = true }
8687
axipi = { workspace = true, optional = true }
8788
kspin = { version = "0.1", optional = true }
89+
axklib-impl = {path = "../../modules/axklib-impl", optional = true}

api/axfeat/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,6 @@
3939
//! [ArceOS]: https://github.com/arceos-org/arceos
4040
4141
#![no_std]
42+
43+
#[cfg(feature = "driver-dyn")]
44+
extern crate axklib_impl;

api/axklib/Cargo.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "axklib"
3+
version.workspace = true
4+
edition.workspace = true
5+
authors = ["周睿 <zrufo747@outlook.com>"]
6+
license.workspace = true
7+
homepage.workspace = true
8+
documentation.workspace = true
9+
repository.workspace = true
10+
keywords.workspace = true
11+
categories.workspace = true
12+
13+
[features]
14+
irq = []
15+
16+
[dependencies]
17+
trait-ffi = "0.2"
18+
memory_addr = "0.4"
19+
axerrno = "0.1"

api/axklib/src/lib.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//! axklib — small kernel-helper abstractions used across the microkernel
2+
//!
3+
//! This crate exposes a tiny, no_std-compatible trait (`Klib`) that the
4+
//! platform/board layer must implement. The trait provides a handful of
5+
//! common kernel helpers such as memory mapping helpers, timing utilities,
6+
//! and IRQ registration. The implementation is supplied by the platform
7+
//! (see `modules/axklib-impl`) and consumed by drivers and other modules.
8+
//!
9+
//! The crate also provides small convenience modules (`mem`, `time`, `irq`)
10+
//! that re-export the trait methods with shorter names to make call sites
11+
//! more ergonomic.
12+
//!
13+
//! Example usage:
14+
//!
15+
//! ```ignore
16+
//! // map 4K of device MMIO at physical address `paddr`
17+
//! let vaddr = axklib::mem::iomap(paddr, 0x1000)?;
18+
//!
19+
//! // busy-wait for 100 microseconds
20+
//! axklib::time::busy_wait(core::time::Duration::from_micros(100));
21+
//!
22+
//! // register an IRQ handler
23+
//! axklib::irq::register(32, my_irq_handler);
24+
//! ```
25+
26+
#![no_std]
27+
// #![allow(missing_docs)]
28+
29+
use core::time::Duration;
30+
31+
pub use axerrno::AxResult;
32+
/// Type alias for a simple IRQ handler function pointer.
33+
///
34+
/// Handlers use the raw ABI required by the platform and take no arguments.
35+
pub type IrqHandler = fn();
36+
37+
pub use memory_addr::{PhysAddr, VirtAddr};
38+
39+
use trait_ffi::*;
40+
41+
/// The kernel helper trait that platform implementations must provide.
42+
#[def_extern_trait]
43+
pub trait Klib {
44+
/// Map a physical memory region into the kernel's virtual address space.
45+
///
46+
/// Parameters:
47+
/// - `addr`: The physical start address of the region to map.
48+
/// - `size`: The size in bytes of the region to map. Typically page-aligned.
49+
///
50+
/// Returns:
51+
/// - `Ok(VirtAddr)` with the virtual address corresponding to the mapped
52+
/// physical region on success.
53+
/// - `Err(_)` with an `AxResult` error code on failure.
54+
///
55+
/// Notes:
56+
/// - The returned `VirtAddr` is page-aligned when the underlying mapping
57+
/// mechanism requires it.
58+
/// - The actual mapping behavior is platform-specific; callers should
59+
/// treat this as an allocation-like operation and ensure the mapping
60+
/// is later cleaned up if the platform/ABI requires it.
61+
fn mem_iomap(addr: PhysAddr, size: usize) -> AxResult<VirtAddr>;
62+
63+
/// Busy-wait the current execution context for the provided duration.
64+
///
65+
/// This is intended for short delays where sleeping or timer-based
66+
/// suspension is not available or not appropriate (for example, very
67+
/// early boot or simple spin-waits). Implementations should aim to be
68+
/// reasonably accurate for small durations but exact timing guarantees
69+
/// are platform-dependent.
70+
fn time_busy_wait(dur: Duration);
71+
72+
/// Enable or disable the edge/level for a platform IRQ.
73+
///
74+
/// `irq` is a platform IRQ number. `enabled` selects whether the IRQ
75+
/// should be enabled (true) or disabled (false).
76+
fn irq_set_enable(irq: usize, enabled: bool);
77+
78+
/// Register a simple IRQ handler for the given IRQ number.
79+
///
80+
/// Returns `true` if the handler was successfully registered, `false`
81+
/// otherwise. The exact semantics (e.g. whether multiple handlers are
82+
/// allowed) are platform-specific; callers should consult the platform
83+
/// implementation.
84+
fn irq_register(irq: usize, handler: IrqHandler) -> bool;
85+
}
86+
87+
/// Convenience re-export for memory IO mapping.
88+
pub mod mem {
89+
pub use super::klib::mem_iomap as iomap;
90+
}
91+
92+
/// Convenience re-export for busy-wait timing.
93+
pub mod time {
94+
pub use super::klib::time_busy_wait as busy_wait;
95+
}
96+
97+
/// Convenience re-exports for IRQ operations.
98+
pub mod irq {
99+
pub use super::klib::irq_register as register;
100+
pub use super::klib::irq_set_enable as set_enable;
101+
}

modules/axdriver/Cargo.toml

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,69 @@
11
[package]
2-
name = "axdriver"
3-
version.workspace = true
4-
edition.workspace = true
52
authors = ["Yuekai Jia <equation618@gmail.com>", "ChengXiang Qi <kuangjux@outlook.com>"]
63
description = "ArceOS device drivers"
7-
license.workspace = true
4+
documentation = "https://arceos-org.github.io/arceos/axdriver/index.html"
5+
edition.workspace = true
86
homepage.workspace = true
7+
license.workspace = true
8+
name = "axdriver"
99
repository = "https://github.com/arceos-org/arceos/tree/main/modules/axdriver"
10-
documentation = "https://arceos-org.github.io/arceos/axdriver/index.html"
10+
version.workspace = true
1111

1212
[features]
13-
dyn = []
13+
block = ["axdriver_block"]
1414
bus-mmio = []
1515
bus-pci = ["dep:axdriver_pci", "dep:axhal", "dep:axconfig"]
16-
net = ["axdriver_net"]
17-
block = ["axdriver_block"]
1816
display = ["axdriver_display"]
17+
dyn = [
18+
"dep:rdrive",
19+
"dep:arm-gic-driver",
20+
"arm-gic-driver?/rdif",
21+
"dep:rdif-intc",
22+
"dep:rdif-block",
23+
"dep:dma-api",
24+
"dep:axklib",
25+
]
26+
net = ["axdriver_net"]
1927

2028
# Enabled by features `virtio-*`
2129
virtio = ["axdriver_virtio", "dep:axalloc", "dep:axhal", "dep:axconfig"]
2230

2331
# various types of drivers
24-
virtio-blk = ["block", "virtio", "axdriver_virtio/block"]
25-
virtio-net = ["net", "virtio", "axdriver_virtio/net"]
26-
virtio-gpu = ["display", "virtio", "axdriver_virtio/gpu"]
27-
ramdisk = ["block", "axdriver_block/ramdisk"]
2832
bcm2835-sdhci = ["block", "axdriver_block/bcm2835-sdhci"]
29-
ixgbe = ["net", "axdriver_net/ixgbe", "dep:axalloc", "dep:axhal", "dep:axdma"]
3033
fxmac = ["net", "axdriver_net/fxmac", "dep:axalloc", "dep:axhal", "dep:axdma"]
34+
ixgbe = ["net", "axdriver_net/ixgbe", "dep:axalloc", "dep:axhal", "dep:axdma"]
35+
ramdisk = ["block", "axdriver_block/ramdisk"]
36+
virtio-blk = ["block", "virtio", "axdriver_virtio/block"]
37+
virtio-gpu = ["display", "virtio", "axdriver_virtio/gpu"]
38+
virtio-net = ["net", "virtio", "axdriver_virtio/net"]
3139
# more devices example: e1000 = ["net", "axdriver_net/e1000"]
3240

3341
default = ["bus-pci"]
3442

3543
[dependencies]
36-
log = "=0.4.21"
44+
axalloc = {workspace = true, optional = true}
45+
axconfig = {workspace = true, optional = true}
46+
axdma = {workspace = true, optional = true}
47+
axklib = {workspace = true, optional = true}
48+
49+
axdriver_base = {git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2"}
50+
axdriver_block = {git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true}
51+
axdriver_display = {git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true}
52+
axdriver_net = {git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true}
53+
axdriver_pci = {git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true}
54+
axdriver_virtio = {git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true}
55+
axerrno = "0.1"
56+
axhal = {workspace = true, optional = true}
3757
cfg-if = "1.0"
3858
crate_interface = "0.1.4"
39-
axdriver_base = { git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2" }
40-
axdriver_block = { git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true }
41-
axdriver_net = { git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true }
42-
axdriver_display = { git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true }
43-
axdriver_pci = { git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true }
44-
axdriver_virtio = { git = "https://github.com/arceos-org/axdriver_crates.git", tag = "v0.1.2", optional = true }
45-
axalloc = { workspace = true, optional = true }
46-
axhal = { workspace = true, optional = true }
47-
axconfig = { workspace = true, optional = true }
48-
axdma = { workspace = true, optional = true }
59+
dma-api = {version = "0.5", features = ["alloc"], optional = true}
60+
lazyinit = "0.2"
61+
log = "=0.4.21"
62+
memory_addr = "0.4"
63+
rdif-block = {version = "0.6.2", optional = true}
64+
rdif-intc = {version = "0.12", optional = true}
65+
rdrive = {version = "0.18", optional = true}
66+
spin = "0.10"
67+
68+
[target.'cfg(target_arch = "aarch64")'.dependencies]
69+
arm-gic-driver = {version = "0.15", optional = true}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use axdriver_base::{BaseDriverOps, DevError, DevResult, DeviceType};
2+
use axdriver_block::BlockDriverOps;
3+
use rdif_block::BlkError;
4+
use rdrive::Device;
5+
use spin::Mutex;
6+
7+
#[cfg(feature = "virtio-blk")]
8+
mod virtio;
9+
10+
pub struct Block {
11+
dev: Device<rdif_block::Block>,
12+
queue: Mutex<rdif_block::CmdQueue>,
13+
}
14+
15+
impl BaseDriverOps for Block {
16+
fn device_type(&self) -> DeviceType {
17+
DeviceType::Block
18+
}
19+
fn device_name(&self) -> &str {
20+
self.dev.descriptor().name
21+
}
22+
}
23+
24+
impl BlockDriverOps for Block {
25+
fn num_blocks(&self) -> u64 {
26+
self.queue.lock().num_blocks() as _
27+
}
28+
fn block_size(&self) -> usize {
29+
self.queue.lock().block_size()
30+
}
31+
fn flush(&mut self) -> DevResult {
32+
Ok(())
33+
}
34+
35+
fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DevResult {
36+
let blk_count = buf.len() / self.block_size();
37+
let blocks = self
38+
.queue
39+
.lock()
40+
.read_blocks_blocking(block_id as _, blk_count);
41+
for (block, chunk) in blocks.into_iter().zip(buf.chunks_mut(self.block_size())) {
42+
let block = block.map_err(maping_blk_err_to_dev_err)?;
43+
if block.len() != chunk.len() {
44+
return Err(DevError::Io);
45+
}
46+
chunk.copy_from_slice(&block);
47+
}
48+
Ok(())
49+
}
50+
51+
fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult {
52+
let blocks = self.queue.lock().write_blocks_blocking(block_id as _, buf);
53+
for block in blocks {
54+
block.map_err(maping_blk_err_to_dev_err)?;
55+
}
56+
Ok(())
57+
}
58+
}
59+
60+
impl From<Device<rdif_block::Block>> for Block {
61+
fn from(base: Device<rdif_block::Block>) -> Self {
62+
let queue = base.lock().unwrap().create_queue().unwrap();
63+
Self {
64+
dev: base,
65+
queue: Mutex::new(queue),
66+
}
67+
}
68+
}
69+
70+
fn maping_blk_err_to_dev_err(err: BlkError) -> DevError {
71+
match err {
72+
BlkError::NotSupported => DevError::Unsupported,
73+
BlkError::Retry => DevError::Again,
74+
BlkError::NoMemory => DevError::NoMemory,
75+
BlkError::InvalidBlockIndex(_) => DevError::InvalidParam,
76+
BlkError::Other(error) => {
77+
error!("Block device error: {error}");
78+
DevError::Io
79+
}
80+
}
81+
}
82+
83+
fn maping_dev_err_to_blk_err(err: DevError) -> BlkError {
84+
match err {
85+
DevError::Again => BlkError::Retry,
86+
DevError::AlreadyExists => BlkError::Other("Already exists".into()),
87+
DevError::BadState => BlkError::Other("Bad internal state".into()),
88+
DevError::InvalidParam => BlkError::Other("Invalid parameter".into()),
89+
DevError::Io => BlkError::Other("I/O error".into()),
90+
DevError::NoMemory => BlkError::NoMemory,
91+
DevError::ResourceBusy => BlkError::Other("Resource busy".into()),
92+
DevError::Unsupported => BlkError::NotSupported,
93+
}
94+
}
95+
96+
pub trait PlatformDeviceBlock {
97+
fn register_block<T: rdif_block::Interface>(self, dev: T);
98+
}
99+
100+
impl PlatformDeviceBlock for rdrive::PlatformDevice {
101+
fn register_block<T: rdif_block::Interface>(self, dev: T) {
102+
let dev = rdif_block::Block::new(dev);
103+
self.register(dev);
104+
}
105+
}

0 commit comments

Comments
 (0)