use ax_memory_addr::PhysAddr;
use axaddrspace::GuestMemoryAccessor;
use axdevice_base::{DeviceContext, DmaGrant};
use axvm_types::GuestPhysAddr;
use crate::{VirtioError, VirtioResult};
pub trait GuestMemory {
fn read(&mut self, guest_addr: GuestPhysAddr, data: &mut [u8]) -> VirtioResult<()>;
fn write(&mut self, guest_addr: GuestPhysAddr, data: &[u8]) -> VirtioResult<()>;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct NoGuestMemoryAccessor;
impl GuestMemoryAccessor for NoGuestMemoryAccessor {
fn translate_and_get_limit(&self, _guest_addr: GuestPhysAddr) -> Option<(PhysAddr, usize)> {
None
}
}
pub struct AddressSpaceMemory<'a, T> {
accessor: &'a T,
}
impl<'a, T> AddressSpaceMemory<'a, T> {
pub const fn new(accessor: &'a T) -> Self {
Self { accessor }
}
}
impl<T: GuestMemoryAccessor> GuestMemory for AddressSpaceMemory<'_, T> {
fn read(&mut self, guest_addr: GuestPhysAddr, data: &mut [u8]) -> VirtioResult<()> {
self.accessor
.read_buffer(guest_addr, data)
.map_err(|_| VirtioError::InvalidAddress)
}
fn write(&mut self, guest_addr: GuestPhysAddr, data: &[u8]) -> VirtioResult<()> {
self.accessor
.write_buffer(guest_addr, data)
.map_err(|_| VirtioError::InvalidAddress)
}
}
pub struct DeviceContextMemory<'a> {
context: &'a mut dyn DeviceContext,
grant: &'a DmaGrant,
}
impl<'a> DeviceContextMemory<'a> {
pub fn new(context: &'a mut dyn DeviceContext, grant: &'a DmaGrant) -> Self {
Self { context, grant }
}
}
impl GuestMemory for DeviceContextMemory<'_> {
fn read(&mut self, guest_addr: GuestPhysAddr, data: &mut [u8]) -> VirtioResult<()> {
self.context
.read_guest_memory(self.grant, guest_addr, data)
.map_err(|_| VirtioError::MemoryError)
}
fn write(&mut self, guest_addr: GuestPhysAddr, data: &[u8]) -> VirtioResult<()> {
self.context
.write_guest_memory(self.grant, guest_addr, data)
.map_err(|_| VirtioError::MemoryError)
}
}