Basic device abstraction library for AxVisor virtual device subsystem, designed for no_std environments.
axdevice_base provides core traits, structures, and type definitions for virtual device development, including:
BaseDeviceOpstrait: Common interface that all virtual devices must implement.EmulatedDeviceConfig: Device initialization and configuration structure.- Device type enumeration
EmuDeviceType(re-exported fromaxvmconfigcrate). - Trait aliases for various device types:
BaseMmioDeviceOps: For MMIO (Memory-Mapped I/O) devices.BaseSysRegDeviceOps: For system register devices (ARM).BasePortDeviceOps: For port I/O devices (x86).
map_device_of_type: Helper function for runtime device type checking and casting.
no_stdcompatible: Designed for bare-metal and hypervisor environments.- Multi-architecture support: x86_64, AArch64, RISC-V64.
- Type-safe addressing: Different address range types for different device access methods.
- Serialization support: Device configuration can be serialized/deserialized via
serde.
Add this to your Cargo.toml:
[dependencies]
axdevice_base = "0.1"use axdevice_base::{BaseDeviceOps, EmuDeviceType};
use axaddrspace::{GuestPhysAddr, GuestPhysAddrRange, device::AccessWidth};
use axerrno::AxResult;
struct MyUartDevice {
base_addr: usize,
// ... device state
}
impl BaseDeviceOps<GuestPhysAddrRange> for MyUartDevice {
fn emu_type(&self) -> EmuDeviceType {
EmuDeviceType::Dummy // Use appropriate device type
}
fn address_range(&self) -> GuestPhysAddrRange {
(self.base_addr..self.base_addr + 0x1000).try_into().unwrap()
}
fn handle_read(&self, addr: GuestPhysAddr, width: AccessWidth) -> AxResult<usize> {
// Handle read operation from guest
Ok(0)
}
fn handle_write(&self, addr: GuestPhysAddr, width: AccessWidth, val: usize) -> AxResult {
// Handle write operation from guest
Ok(())
}
}use axdevice_base::EmulatedDeviceConfig;
let config = EmulatedDeviceConfig {
name: "uart0".into(),
base_ipa: 0x0900_0000,
length: 0x1000,
irq_id: 33,
emu_type: 1,
cfg_list: vec![115200], // device-specific config (e.g., baud rate)
};use axdevice_base::{BaseMmioDeviceOps, map_device_of_type};
use alloc::sync::Arc;
fn process_device(device: &Arc<dyn BaseMmioDeviceOps>) {
// Try to access device-specific methods if it's a UartDevice
if let Some(baud_rate) = map_device_of_type(device, |uart: &MyUartDevice| {
uart.get_baud_rate()
}) {
println!("UART baud rate: {}", baud_rate);
}
}| Architecture | MMIO Devices | Port I/O Devices | System Register Devices |
|---|---|---|---|
| x86_64 | ✓ | ✓ | - |
| AArch64 | ✓ | - | ✓ |
| RISC-V64 | ✓ | - | - |
For detailed API documentation, visit docs.rs/axdevice_base.
Issues and PRs are welcome! Please follow the ArceOS-hypervisor project guidelines.
Axdevice_base is licensed under the Apache License, Version 2.0. See the LICENSE file for details.