mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
arch/aarch64: Add virtio-iommu device in FDT
Add a virtio-iommu node into FDT if iommu option is turned on. Now we support only one virtio-iommu device. Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
committed by
Sebastien Boeuf
parent
46f6d9597d
commit
253c06d3ba
+46
-2
@@ -35,9 +35,12 @@ const MSI_PHANDLE: u32 = 2;
|
|||||||
const CLOCK_PHANDLE: u32 = 3;
|
const CLOCK_PHANDLE: u32 = 3;
|
||||||
// This is a value for uniquely identifying the FDT node containing the gpio controller.
|
// This is a value for uniquely identifying the FDT node containing the gpio controller.
|
||||||
const GPIO_PHANDLE: u32 = 4;
|
const GPIO_PHANDLE: u32 = 4;
|
||||||
|
// This is a value for virtio-iommu. Now only one virtio-iommu device is supported.
|
||||||
|
const VIRTIO_IOMMU_PHANDLE: u32 = 5;
|
||||||
|
// NOTE: Keep FIRST_VCPU_PHANDLE the last PHANDLE defined.
|
||||||
// This is a value for uniquely identifying the FDT node containing the first vCPU.
|
// This is a value for uniquely identifying the FDT node containing the first vCPU.
|
||||||
// The last number of vCPU phandle depends on the number of vCPUs.
|
// The last number of vCPU phandle depends on the number of vCPUs.
|
||||||
const FIRST_VCPU_PHANDLE: u32 = 5;
|
const FIRST_VCPU_PHANDLE: u32 = 6;
|
||||||
|
|
||||||
// Read the documentation specified when appending the root node to the FDT.
|
// Read the documentation specified when appending the root node to the FDT.
|
||||||
const ADDRESS_CELLS: u32 = 0x2;
|
const ADDRESS_CELLS: u32 = 0x2;
|
||||||
@@ -87,6 +90,7 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
|
|||||||
initrd: &Option<InitramfsConfig>,
|
initrd: &Option<InitramfsConfig>,
|
||||||
pci_space_address: &(u64, u64),
|
pci_space_address: &(u64, u64),
|
||||||
numa_nodes: &NumaNodes,
|
numa_nodes: &NumaNodes,
|
||||||
|
virtio_iommu_bdf: Option<u32>,
|
||||||
) -> FdtWriterResult<Vec<u8>> {
|
) -> FdtWriterResult<Vec<u8>> {
|
||||||
// Allocate stuff necessary for the holding the blob.
|
// Allocate stuff necessary for the holding the blob.
|
||||||
let mut fdt = FdtWriter::new().unwrap();
|
let mut fdt = FdtWriter::new().unwrap();
|
||||||
@@ -113,7 +117,12 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
|
|||||||
create_clock_node(&mut fdt)?;
|
create_clock_node(&mut fdt)?;
|
||||||
create_psci_node(&mut fdt)?;
|
create_psci_node(&mut fdt)?;
|
||||||
create_devices_node(&mut fdt, device_info)?;
|
create_devices_node(&mut fdt, device_info)?;
|
||||||
create_pci_nodes(&mut fdt, pci_space_address.0, pci_space_address.1)?;
|
create_pci_nodes(
|
||||||
|
&mut fdt,
|
||||||
|
pci_space_address.0,
|
||||||
|
pci_space_address.1,
|
||||||
|
virtio_iommu_bdf,
|
||||||
|
)?;
|
||||||
if numa_nodes.len() > 1 {
|
if numa_nodes.len() > 1 {
|
||||||
create_distance_map_node(&mut fdt, numa_nodes)?;
|
create_distance_map_node(&mut fdt, numa_nodes)?;
|
||||||
}
|
}
|
||||||
@@ -540,6 +549,7 @@ fn create_pci_nodes(
|
|||||||
fdt: &mut FdtWriter,
|
fdt: &mut FdtWriter,
|
||||||
pci_device_base: u64,
|
pci_device_base: u64,
|
||||||
pci_device_size: u64,
|
pci_device_size: u64,
|
||||||
|
virtio_iommu_bdf: Option<u32>,
|
||||||
) -> FdtWriterResult<()> {
|
) -> FdtWriterResult<()> {
|
||||||
// Add node for PCIe controller.
|
// Add node for PCIe controller.
|
||||||
// See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
|
// See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
|
||||||
@@ -603,6 +613,40 @@ fn create_pci_nodes(
|
|||||||
fdt.property_null("interrupt-map-mask")?;
|
fdt.property_null("interrupt-map-mask")?;
|
||||||
fdt.property_null("dma-coherent")?;
|
fdt.property_null("dma-coherent")?;
|
||||||
fdt.property_u32("msi-parent", MSI_PHANDLE)?;
|
fdt.property_u32("msi-parent", MSI_PHANDLE)?;
|
||||||
|
|
||||||
|
if let Some(virtio_iommu_bdf) = virtio_iommu_bdf {
|
||||||
|
// See kernel document Documentation/devicetree/bindings/pci/pci-iommu.txt
|
||||||
|
// for 'iommu-map' attribute setting.
|
||||||
|
let iommu_map = [
|
||||||
|
0_u32,
|
||||||
|
VIRTIO_IOMMU_PHANDLE,
|
||||||
|
0_u32,
|
||||||
|
virtio_iommu_bdf,
|
||||||
|
virtio_iommu_bdf + 1,
|
||||||
|
VIRTIO_IOMMU_PHANDLE,
|
||||||
|
virtio_iommu_bdf + 1,
|
||||||
|
0xffff - virtio_iommu_bdf,
|
||||||
|
];
|
||||||
|
fdt.property_array_u32("iommu-map", &iommu_map)?;
|
||||||
|
|
||||||
|
// See kernel document Documentation/devicetree/bindings/virtio/iommu.txt
|
||||||
|
// for virtio-iommu node settings.
|
||||||
|
let virtio_iommu_node_name = format!("virtio_iommu@{:x}", virtio_iommu_bdf);
|
||||||
|
let virtio_iommu_node = fdt.begin_node(&virtio_iommu_node_name)?;
|
||||||
|
fdt.property_u32("#iommu-cells", 1)?;
|
||||||
|
fdt.property_string("compatible", "virtio,pci-iommu")?;
|
||||||
|
|
||||||
|
// 'reg' is a five-cell address encoded as
|
||||||
|
// (phys.hi phys.mid phys.lo size.hi size.lo). phys.hi should contain the
|
||||||
|
// device's BDF as 0b00000000 bbbbbbbb dddddfff 00000000. The other cells
|
||||||
|
// should be zero.
|
||||||
|
let reg = [virtio_iommu_bdf << 8, 0_u32, 0_u32, 0_u32, 0_u32];
|
||||||
|
fdt.property_array_u32("reg", ®)?;
|
||||||
|
fdt.property_u32("phandle", VIRTIO_IOMMU_PHANDLE)?;
|
||||||
|
|
||||||
|
fdt.end_node(virtio_iommu_node)?;
|
||||||
|
}
|
||||||
|
|
||||||
fdt.end_node(pci_node)?;
|
fdt.end_node(pci_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
|
|||||||
device_info: &HashMap<(DeviceType, String), T, S>,
|
device_info: &HashMap<(DeviceType, String), T, S>,
|
||||||
initrd: &Option<super::InitramfsConfig>,
|
initrd: &Option<super::InitramfsConfig>,
|
||||||
pci_space_address: &(u64, u64),
|
pci_space_address: &(u64, u64),
|
||||||
|
virtio_iommu_bdf: Option<u32>,
|
||||||
gic_device: &dyn GicDevice,
|
gic_device: &dyn GicDevice,
|
||||||
numa_nodes: &NumaNodes,
|
numa_nodes: &NumaNodes,
|
||||||
) -> super::Result<()> {
|
) -> super::Result<()> {
|
||||||
@@ -155,6 +156,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
|
|||||||
initrd,
|
initrd,
|
||||||
pci_space_address,
|
pci_space_address,
|
||||||
numa_nodes,
|
numa_nodes,
|
||||||
|
virtio_iommu_bdf,
|
||||||
)
|
)
|
||||||
.map_err(|_| Error::SetupFdt)?;
|
.map_err(|_| Error::SetupFdt)?;
|
||||||
|
|
||||||
|
|||||||
@@ -1077,6 +1077,14 @@ impl Vm {
|
|||||||
|
|
||||||
let pci_space = (pci_space_start.0, pci_space_size);
|
let pci_space = (pci_space_start.0, pci_space_size);
|
||||||
|
|
||||||
|
let virtio_iommu_bdf = self
|
||||||
|
.device_manager
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iommu_attached_devices()
|
||||||
|
.as_ref()
|
||||||
|
.map(|(v, _)| *v);
|
||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
{
|
{
|
||||||
let _ = crate::acpi::create_acpi_tables(
|
let _ = crate::acpi::create_acpi_tables(
|
||||||
@@ -1104,6 +1112,7 @@ impl Vm {
|
|||||||
device_info,
|
device_info,
|
||||||
&initramfs_config,
|
&initramfs_config,
|
||||||
&pci_space,
|
&pci_space,
|
||||||
|
virtio_iommu_bdf,
|
||||||
&*gic_device,
|
&*gic_device,
|
||||||
&self.numa_nodes,
|
&self.numa_nodes,
|
||||||
)
|
)
|
||||||
@@ -2584,6 +2593,7 @@ mod tests {
|
|||||||
&None,
|
&None,
|
||||||
&(0x1_0000_0000, 0x1_0000),
|
&(0x1_0000_0000, 0x1_0000),
|
||||||
&BTreeMap::new(),
|
&BTreeMap::new(),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.is_ok())
|
.is_ok())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user