diff --git a/virtio-devices/src/device.rs b/virtio-devices/src/device.rs index c44a64c4f..911ab9311 100644 --- a/virtio-devices/src/device.rs +++ b/virtio-devices/src/device.rs @@ -209,6 +209,8 @@ pub trait VirtioDevice: Send { pub trait DmaRemapping: Send + Sync { /// Provide a way to translate GVA address ranges into GPAs. fn translate_gva(&self, id: u32, addr: u64) -> std::result::Result; + /// Provide a way to translate GPA address ranges into GVAs. + fn translate_gpa(&self, id: u32, addr: u64) -> std::result::Result; } /// Structure to handle device state common to all devices diff --git a/virtio-devices/src/iommu.rs b/virtio-devices/src/iommu.rs index 8d54a3c56..e59683f65 100644 --- a/virtio-devices/src/iommu.rs +++ b/virtio-devices/src/iommu.rs @@ -684,7 +684,7 @@ pub struct IommuMapping { impl DmaRemapping for IommuMapping { fn translate_gva(&self, id: u32, addr: u64) -> std::result::Result { - debug!("Translate addr 0x{:x}", addr); + debug!("Translate GVA addr 0x{:x}", addr); if let Some(domain) = self.endpoints.read().unwrap().get(&id) { if let Some(mapping) = self.mappings.read().unwrap().get(domain) { let range_start = if VIRTIO_IOMMU_PAGE_SIZE_MASK > addr { @@ -695,7 +695,25 @@ impl DmaRemapping for IommuMapping { for (&key, &value) in mapping.range((Included(&range_start), Included(&addr))) { if addr >= key && addr < key + value.size { let new_addr = addr - key + value.gpa; - debug!("Into new_addr 0x{:x}", new_addr); + debug!("Into GPA addr 0x{:x}", new_addr); + return Ok(new_addr); + } + } + } + } + + debug!("Into same addr..."); + Ok(addr) + } + + fn translate_gpa(&self, id: u32, addr: u64) -> std::result::Result { + debug!("Translate GPA addr 0x{:x}", addr); + if let Some(domain) = self.endpoints.read().unwrap().get(&id) { + if let Some(mapping) = self.mappings.read().unwrap().get(domain) { + for (&key, &value) in mapping.iter() { + if addr >= value.gpa && addr < value.gpa + value.size { + let new_addr = addr - value.gpa + key; + debug!("Into GVA addr 0x{:x}", new_addr); return Ok(new_addr); } } @@ -723,6 +741,9 @@ impl AccessPlatform for AccessPlatformMapping { fn translate_gva(&self, base: u64, _size: u64) -> std::result::Result { self.mapping.translate_gva(self.id, base) } + fn translate_gpa(&self, base: u64, _size: u64) -> std::result::Result { + self.mapping.translate_gpa(self.id, base) + } } pub struct Iommu { diff --git a/vm-virtio/src/lib.rs b/vm-virtio/src/lib.rs index 111e997af..6cf28f5a7 100644 --- a/vm-virtio/src/lib.rs +++ b/vm-virtio/src/lib.rs @@ -96,10 +96,13 @@ impl fmt::Display for VirtioDeviceType { pub trait AccessPlatform: Send + Sync + Debug { /// Provide a way to translate GVA address ranges into GPAs. fn translate_gva(&self, base: u64, size: u64) -> std::result::Result; + /// Provide a way to translate GPA address ranges into GVAs. + fn translate_gpa(&self, base: u64, size: u64) -> std::result::Result; } pub trait Translatable { fn translate_gva(&self, access_platform: Option<&Arc>, len: usize) -> Self; + fn translate_gpa(&self, access_platform: Option<&Arc>, len: usize) -> Self; } impl Translatable for GuestAddress { @@ -110,4 +113,11 @@ impl Translatable for GuestAddress { *self } } + fn translate_gpa(&self, access_platform: Option<&Arc>, len: usize) -> Self { + if let Some(access_platform) = access_platform { + GuestAddress(access_platform.translate_gpa(self.0, len as u64).unwrap()) + } else { + *self + } + } }