virtio-devices: iommu: Support AArch64

The MSI IOVA address on X86 and AArch64 is different.

This commit refactored the code to receive the MSI IOVA address and size
from device_manager, which provides the actual IOVA space data for both
architectures.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2021-09-06 20:58:48 +08:00 committed by Sebastien Boeuf
parent b30ddc0837
commit b3fa56544c
2 changed files with 26 additions and 4 deletions

View File

@ -54,8 +54,6 @@ const EVENT_Q_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
/// will conflict with x86. /// will conflict with x86.
const PROBE_PROP_SIZE: u32 = const PROBE_PROP_SIZE: u32 =
(size_of::<VirtioIommuProbeProperty>() + size_of::<VirtioIommuProbeResvMem>()) as u32; (size_of::<VirtioIommuProbeProperty>() + size_of::<VirtioIommuProbeResvMem>()) as u32;
const MSI_IOVA_START: u64 = 0xfee0_0000;
const MSI_IOVA_END: u64 = 0xfeef_ffff;
/// Virtio IOMMU features /// Virtio IOMMU features
#[allow(unused)] #[allow(unused)]
@ -352,6 +350,7 @@ impl Request {
mapping: &Arc<IommuMapping>, mapping: &Arc<IommuMapping>,
ext_mapping: &BTreeMap<u32, Arc<dyn ExternalDmaMapping>>, ext_mapping: &BTreeMap<u32, Arc<dyn ExternalDmaMapping>>,
ext_domain_mapping: &mut BTreeMap<u32, Arc<dyn ExternalDmaMapping>>, ext_domain_mapping: &mut BTreeMap<u32, Arc<dyn ExternalDmaMapping>>,
msi_iova_space: (u64, u64),
) -> result::Result<usize, Error> { ) -> result::Result<usize, Error> {
// The head contains the request type which MUST be readable. // The head contains the request type which MUST be readable.
if avail_desc.is_write_only() { if avail_desc.is_write_only() {
@ -372,6 +371,8 @@ impl Request {
return Err(Error::InvalidRequest); return Err(Error::InvalidRequest);
}; };
let (msi_iova_start, msi_iova_end) = msi_iova_space;
// Create the reply // Create the reply
let mut reply: Vec<u8> = Vec::new(); let mut reply: Vec<u8> = Vec::new();
@ -515,8 +516,8 @@ impl Request {
let resv_mem = VirtioIommuProbeResvMem { let resv_mem = VirtioIommuProbeResvMem {
subtype: VIRTIO_IOMMU_RESV_MEM_T_MSI, subtype: VIRTIO_IOMMU_RESV_MEM_T_MSI,
start: MSI_IOVA_START, start: msi_iova_start,
end: MSI_IOVA_END, end: msi_iova_end,
..Default::default() ..Default::default()
}; };
reply.extend_from_slice(resv_mem.as_slice()); reply.extend_from_slice(resv_mem.as_slice());
@ -562,6 +563,7 @@ struct IommuEpollHandler {
mapping: Arc<IommuMapping>, mapping: Arc<IommuMapping>,
ext_mapping: BTreeMap<u32, Arc<dyn ExternalDmaMapping>>, ext_mapping: BTreeMap<u32, Arc<dyn ExternalDmaMapping>>,
ext_domain_mapping: BTreeMap<u32, Arc<dyn ExternalDmaMapping>>, ext_domain_mapping: BTreeMap<u32, Arc<dyn ExternalDmaMapping>>,
msi_iova_space: (u64, u64),
} }
impl IommuEpollHandler { impl IommuEpollHandler {
@ -576,6 +578,7 @@ impl IommuEpollHandler {
&self.mapping, &self.mapping,
&self.ext_mapping, &self.ext_mapping,
&mut self.ext_domain_mapping, &mut self.ext_domain_mapping,
self.msi_iova_space,
) { ) {
Ok(len) => len as u32, Ok(len) => len as u32,
Err(e) => { Err(e) => {
@ -702,6 +705,7 @@ pub struct Iommu {
ext_mapping: BTreeMap<u32, Arc<dyn ExternalDmaMapping>>, ext_mapping: BTreeMap<u32, Arc<dyn ExternalDmaMapping>>,
seccomp_action: SeccompAction, seccomp_action: SeccompAction,
exit_evt: EventFd, exit_evt: EventFd,
msi_iova_space: (u64, u64),
} }
#[derive(Versionize)] #[derive(Versionize)]
@ -719,6 +723,7 @@ impl Iommu {
id: String, id: String,
seccomp_action: SeccompAction, seccomp_action: SeccompAction,
exit_evt: EventFd, exit_evt: EventFd,
msi_iova_space: (u64, u64),
) -> io::Result<(Self, Arc<IommuMapping>)> { ) -> io::Result<(Self, Arc<IommuMapping>)> {
let config = VirtioIommuConfig { let config = VirtioIommuConfig {
page_size_mask: VIRTIO_IOMMU_PAGE_SIZE_MASK, page_size_mask: VIRTIO_IOMMU_PAGE_SIZE_MASK,
@ -748,6 +753,7 @@ impl Iommu {
ext_mapping: BTreeMap::new(), ext_mapping: BTreeMap::new(),
seccomp_action, seccomp_action,
exit_evt, exit_evt,
msi_iova_space,
}, },
mapping, mapping,
)) ))
@ -843,6 +849,7 @@ impl VirtioDevice for Iommu {
mapping: self.mapping.clone(), mapping: self.mapping.clone(),
ext_mapping: self.ext_mapping.clone(), ext_mapping: self.ext_mapping.clone(),
ext_domain_mapping: BTreeMap::new(), ext_domain_mapping: BTreeMap::new(),
msi_iova_space: self.msi_iova_space,
}; };
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();

View File

@ -1135,6 +1135,20 @@ impl DeviceManager {
self.device_id_cnt = state.device_id_cnt; self.device_id_cnt = state.device_id_cnt;
} }
fn get_msi_iova_space(&mut self) -> (u64, u64) {
#[cfg(target_arch = "aarch64")]
{
let vcpus = self.config.lock().unwrap().cpus.boot_vcpus;
let msi_start = arch::layout::GIC_V3_DIST_START
- arch::layout::GIC_V3_REDIST_SIZE * (vcpus as u64)
- arch::layout::GIC_V3_ITS_SIZE;
let msi_end = msi_start + arch::layout::GIC_V3_ITS_SIZE - 1;
(msi_start, msi_end)
}
#[cfg(target_arch = "x86_64")]
(0xfee0_0000, 0xfeef_ffff)
}
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
/// Gets the information of the devices registered up to some point in time. /// Gets the information of the devices registered up to some point in time.
pub fn get_device_info(&self) -> &HashMap<(DeviceType, String), MmioDeviceInfo> { pub fn get_device_info(&self) -> &HashMap<(DeviceType, String), MmioDeviceInfo> {
@ -1161,6 +1175,7 @@ impl DeviceManager {
self.exit_evt self.exit_evt
.try_clone() .try_clone()
.map_err(DeviceManagerError::EventFd)?, .map_err(DeviceManagerError::EventFd)?,
self.get_msi_iova_space(),
) )
.map_err(DeviceManagerError::CreateVirtioIommu)?; .map_err(DeviceManagerError::CreateVirtioIommu)?;
let device = Arc::new(Mutex::new(device)); let device = Arc::new(Mutex::new(device));