use axdevice_base::{
AccessWidth, BusAccess, BusKind, BusResponse, Device, DeviceAccess, DeviceError, DeviceResult,
Resource,
};
use axvm_types::GuestPhysAddr;
use crate::vgic::Vgic;
const VGIC_V2_BASE: usize = 0x800_0000;
const VGIC_V2_SIZE: usize = 0x10000;
static VGIC_V2_RESOURCES: [Resource; 1] = [Resource::MmioRange {
base: VGIC_V2_BASE as u64,
size: VGIC_V2_SIZE as u64,
}];
impl Vgic {
pub fn read_register(&self, addr: GuestPhysAddr, width: AccessWidth) -> DeviceResult<usize> {
if !contains_vgic_v2(addr) {
return Err(DeviceError::OutOfRange {
addr: addr.as_usize() as u64,
});
}
let addr = addr.as_usize() & 0xfff;
let value = match width {
AccessWidth::Byte => {
self.handle_read8(addr)?
}
AccessWidth::Word => {
self.handle_read16(addr)?
}
AccessWidth::Dword => {
self.handle_read32(addr)?
}
_ => 0,
};
Ok(value)
}
pub fn write_register(
&self,
addr: GuestPhysAddr,
width: AccessWidth,
val: usize,
) -> DeviceResult {
if !contains_vgic_v2(addr) {
return Err(DeviceError::OutOfRange {
addr: addr.as_usize() as u64,
});
}
let addr = addr.as_usize() & 0xfff;
match width {
AccessWidth::Byte => {
self.handle_write8(addr, val);
Ok(())
}
AccessWidth::Word => {
self.handle_write16(addr, val);
Ok(())
}
AccessWidth::Dword => {
self.handle_write32(addr, val);
Ok(())
}
_ => Ok(()),
}
}
}
impl Device for Vgic {
fn name(&self) -> &str {
"aarch64-vgic-v2"
}
fn resources(&self) -> &[Resource] {
&VGIC_V2_RESOURCES
}
fn access(
&self,
access: &BusAccess,
_context: &mut dyn DeviceAccess,
) -> Result<BusResponse, DeviceError> {
if access.kind != BusKind::Mmio {
return Err(DeviceError::OutOfRange { addr: access.addr });
}
let addr = GuestPhysAddr::from_usize(access.addr as usize);
if access.is_read {
self.read_register(addr, access.width)
.map(|value| BusResponse::Read {
value: value as u64,
})
} else {
self.write_register(addr, access.width, access.data as usize)
.map(|_| BusResponse::Write)
}
}
}
fn contains_vgic_v2(addr: GuestPhysAddr) -> bool {
let addr = addr.as_usize();
(VGIC_V2_BASE..VGIC_V2_BASE + VGIC_V2_SIZE).contains(&addr)
}