diff --git a/Cargo.toml b/Cargo.toml index 81e3a63..ce277fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,14 @@ name = "axdevice" version = "0.1.0" edition = "2021" +[features] + [dependencies] +log = "=0.4.19" +cfg-if = "1.0" +serde = { version = "1.0.204", default-features = false, features = ["derive", "alloc"] } +# System independent crates provided by ArceOS. +axerrno = "0.1.0" +memory_addr = "0.3.0" +axaddrspace = { git = "https://github.com/arceos-hypervisor/axaddrspace.git" } +axdevice_base = { git = "https://github.com/arceos-hypervisor/axdevice_crates.git"} diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..a70e225 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,16 @@ +use alloc::vec::Vec; +use axdevice_base::EmulatedDeviceConfig; + +/// The vector of DeviceConfig +pub struct AxVmDeviceConfig { + /// The vector of EmulatedDeviceConfig + pub emu_configs: Vec, +} + +/// The implemention for AxVmDeviceConfig +impl AxVmDeviceConfig { + /// The new function for AxVmDeviceConfig + pub fn new(emu_configs: Vec) -> Self { + Self { emu_configs } + } +} diff --git a/src/device.rs b/src/device.rs new file mode 100644 index 0000000..6db6a13 --- /dev/null +++ b/src/device.rs @@ -0,0 +1,93 @@ +use crate::AxVmDeviceConfig; + +use alloc::sync::Arc; +use alloc::vec::Vec; + +use axaddrspace::GuestPhysAddr; +use axdevice_base::EmulatedDeviceConfig; +use axdevice_base::{BaseDeviceOps, EmuDeviceType}; +use axerrno::AxResult; + +/// represent A vm own devices +pub struct AxVmDevices { + /// emu devices + emu_devices: Vec>, + // TODO passthrough devices or other type devices ... +} + +/// The implemention for AxVmDevices +impl AxVmDevices { + /// According AxVmDeviceConfig to init the AxVmDevices + pub fn new(config: AxVmDeviceConfig) -> Self { + let mut this = Self { + emu_devices: Vec::new(), + }; + + Self::init(&mut this, &config.emu_configs); + this + } + + /// According the emu_configs to init every specific device + fn init(this: &mut Self, emu_configs: &Vec) { + /* + for config in emu_configs { + let dev = match EmuDeviceType::from_usize(config.emu_type) { + // todo call specific initialization function of devcise + EmuDeviceType::EmuDeviceTConsole => , + EmuDeviceType::EmuDeviceTGicdV2 => , + EmuDeviceType::EmuDeviceTGPPT => , + EmuDeviceType::EmuDeviceTVirtioBlk => , + EmuDeviceType::EmuDeviceTVirtioNet => , + EmuDeviceType::EmuDeviceTVirtioConsole => , + EmuDeviceType::EmuDeviceTIOMMU => , + EmuDeviceType::EmuDeviceTICCSRE => , + EmuDeviceType::EmuDeviceTSGIR => , + EmuDeviceType::EmuDeviceTGICR => , + EmuDeviceType::EmuDeviceTMeta => , + _ => panic!("emu type: {} is still not supported", config.emu_type), + }; + if let Ok(emu_dev) = dev { + this.emu_devices.push(emu_dev) + } + } + */ + } + + /// Find specific device by ipa + pub fn find_dev(&self, ipa: GuestPhysAddr) -> Option> { + self.emu_devices + .iter() + .find(|&dev| dev.address_range().contains(ipa)) + .cloned() + } + + /// Handle the MMIO read by GuestPhysAddr and data width, return the value of the guest want to read + pub fn handle_mmio_read(&self, addr: GuestPhysAddr, width: usize) -> AxResult { + if let Some(emu_dev) = self.find_dev(addr) { + info!( + "emu: {:?} handler read ipa {:#x}", + emu_dev.address_range(), + addr + ); + return emu_dev.handle_read(addr, width); + } + panic!("emu_handle: no emul handler for data abort ipa {:#x}", addr); + } + + /// Handle the MMIO write by GuestPhysAddr, data width and the value need to write, call specific device to write the value + pub fn handle_mmio_write(&self, addr: GuestPhysAddr, width: usize, val: usize) { + if let Some(emu_dev) = self.find_dev(addr) { + info!( + "emu: {:?} handler write ipa {:#x}", + emu_dev.address_range(), + addr + ); + emu_dev.handle_write(addr, width, val); + return; + } + panic!( + "emu_handler: no emul handler for data abort ipa {:#x}", + addr + ); + } +} diff --git a/src/lib.rs b/src/lib.rs index b93cf3f..adf233e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,19 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +#![no_std] + +//! This module is designed for an environment where the standard library is not available (`no_std`). +//! +//! The `alloc` crate is used to enable dynamic memory allocation in the absence of the standard library. +//! +//! The `log` crate is included for logging purposes, with macros being imported globally. +//! +//! The module is structured into two main parts: `config` and `device`, which manage the configuration and handling of AxVm devices respectively. + +extern crate alloc; +#[macro_use] +extern crate log; + +mod config; +mod device; + +pub use config::AxVmDeviceConfig; +pub use device::AxVmDevices;