virtio-devices: Introduce new function translating GPAs into GVAs

In anticipation for the vDPA need to translate a GPA back into a GVA, we
extend the existing trait DmaRemapping and AccessPlatform to perform
such operation.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2022-04-04 14:11:29 +02:00
parent 059e787cb5
commit 1cdf8b232d
3 changed files with 35 additions and 2 deletions

View File

@ -209,6 +209,8 @@ pub trait VirtioDevice: Send {
pub trait DmaRemapping: Send + Sync { pub trait DmaRemapping: Send + Sync {
/// Provide a way to translate GVA address ranges into GPAs. /// Provide a way to translate GVA address ranges into GPAs.
fn translate_gva(&self, id: u32, addr: u64) -> std::result::Result<u64, std::io::Error>; fn translate_gva(&self, id: u32, addr: u64) -> std::result::Result<u64, std::io::Error>;
/// Provide a way to translate GPA address ranges into GVAs.
fn translate_gpa(&self, id: u32, addr: u64) -> std::result::Result<u64, std::io::Error>;
} }
/// Structure to handle device state common to all devices /// Structure to handle device state common to all devices

View File

@ -684,7 +684,7 @@ pub struct IommuMapping {
impl DmaRemapping for IommuMapping { impl DmaRemapping for IommuMapping {
fn translate_gva(&self, id: u32, addr: u64) -> std::result::Result<u64, std::io::Error> { fn translate_gva(&self, id: u32, addr: u64) -> std::result::Result<u64, std::io::Error> {
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(domain) = self.endpoints.read().unwrap().get(&id) {
if let Some(mapping) = self.mappings.read().unwrap().get(domain) { if let Some(mapping) = self.mappings.read().unwrap().get(domain) {
let range_start = if VIRTIO_IOMMU_PAGE_SIZE_MASK > addr { 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))) { for (&key, &value) in mapping.range((Included(&range_start), Included(&addr))) {
if addr >= key && addr < key + value.size { if addr >= key && addr < key + value.size {
let new_addr = addr - key + value.gpa; 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<u64, std::io::Error> {
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); return Ok(new_addr);
} }
} }
@ -723,6 +741,9 @@ impl AccessPlatform for AccessPlatformMapping {
fn translate_gva(&self, base: u64, _size: u64) -> std::result::Result<u64, std::io::Error> { fn translate_gva(&self, base: u64, _size: u64) -> std::result::Result<u64, std::io::Error> {
self.mapping.translate_gva(self.id, base) self.mapping.translate_gva(self.id, base)
} }
fn translate_gpa(&self, base: u64, _size: u64) -> std::result::Result<u64, std::io::Error> {
self.mapping.translate_gpa(self.id, base)
}
} }
pub struct Iommu { pub struct Iommu {

View File

@ -96,10 +96,13 @@ impl fmt::Display for VirtioDeviceType {
pub trait AccessPlatform: Send + Sync + Debug { pub trait AccessPlatform: Send + Sync + Debug {
/// Provide a way to translate GVA address ranges into GPAs. /// Provide a way to translate GVA address ranges into GPAs.
fn translate_gva(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error>; fn translate_gva(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error>;
/// Provide a way to translate GPA address ranges into GVAs.
fn translate_gpa(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error>;
} }
pub trait Translatable { pub trait Translatable {
fn translate_gva(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self; fn translate_gva(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self;
fn translate_gpa(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self;
} }
impl Translatable for GuestAddress { impl Translatable for GuestAddress {
@ -110,4 +113,11 @@ impl Translatable for GuestAddress {
*self *self
} }
} }
fn translate_gpa(&self, access_platform: Option<&Arc<dyn AccessPlatform>>, len: usize) -> Self {
if let Some(access_platform) = access_platform {
GuestAddress(access_platform.translate_gpa(self.0, len as u64).unwrap())
} else {
*self
}
}
} }