Skip to content

Commit 1271802

Browse files
committed
pci: define PCI segment in FDT
Write the PCI root bridge in FDT when PCI is enabled. Signed-off-by: Babis Chalios <[email protected]>
1 parent 79aab27 commit 1271802

File tree

1 file changed

+63
-0
lines changed
  • src/vmm/src/arch/aarch64

1 file changed

+63
-0
lines changed

src/vmm/src/arch/aarch64/fdt.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@ use vm_memory::GuestMemoryError;
1313

1414
use super::cache_info::{CacheEntry, read_cache_config};
1515
use super::gic::GICDevice;
16+
use crate::arch::{
17+
MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_64BIT_DEVICES_SIZE,
18+
MEM_64BIT_DEVICES_START, PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
19+
};
1620
use crate::device_manager::DeviceManager;
1721
use crate::device_manager::mmio::MMIODeviceInfo;
22+
use crate::device_manager::pci_mngr::PciDevices;
1823
use crate::devices::acpi::vmgenid::{VMGENID_MEM_SIZE, VmGenId};
1924
use crate::initrd::InitrdConfig;
2025
use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap};
@@ -90,6 +95,7 @@ pub fn create_fdt(
9095
create_psci_node(&mut fdt_writer)?;
9196
create_devices_node(&mut fdt_writer, device_manager)?;
9297
create_vmgenid_node(&mut fdt_writer, &device_manager.acpi_devices.vmgenid)?;
98+
create_pci_nodes(&mut fdt_writer, &device_manager.pci_devices)?;
9399

94100
// End Header node.
95101
fdt_writer.end_node(root)?;
@@ -431,6 +437,63 @@ fn create_devices_node(
431437
Ok(())
432438
}
433439

440+
fn create_pci_nodes(fdt: &mut FdtWriter, pci_devices: &PciDevices) -> Result<(), FdtError> {
441+
if pci_devices.pci_segment.is_none() {
442+
return Ok(());
443+
}
444+
445+
// Fine to unwrap here, we just checked it's not `None`.
446+
let segment = pci_devices.pci_segment.as_ref().unwrap();
447+
448+
let pci_node_name = format!("pci@{:x}", segment.mmio_config_address);
449+
// Each range here is a thruple of `(PCI address, CPU address, PCI size)`.
450+
//
451+
// More info about the format can be found here:
452+
// https://elinux.org/Device_Tree_Usage#PCI_Address_Translation
453+
let ranges = [
454+
// 32bit addresses
455+
0x200_0000u32,
456+
(MEM_32BIT_DEVICES_START >> 32) as u32, // PCI address
457+
(MEM_32BIT_DEVICES_START & 0xffff_ffff) as u32,
458+
(MEM_32BIT_DEVICES_START >> 32) as u32, // CPU address
459+
(MEM_32BIT_DEVICES_START & 0xffff_ffff) as u32,
460+
(MEM_32BIT_DEVICES_SIZE >> 32) as u32, // Range size
461+
(MEM_32BIT_DEVICES_SIZE & 0xffff_ffff) as u32,
462+
// 64bit addresses
463+
0x300_0000u32,
464+
// PCI address
465+
(MEM_64BIT_DEVICES_START >> 32) as u32, // PCI address
466+
(MEM_64BIT_DEVICES_START & 0xffff_ffff) as u32,
467+
// CPU address
468+
(MEM_64BIT_DEVICES_START >> 32) as u32, // CPU address
469+
(MEM_64BIT_DEVICES_START & 0xffff_ffff) as u32,
470+
// Range size
471+
(MEM_64BIT_DEVICES_SIZE >> 32) as u32, // Range size
472+
((MEM_64BIT_DEVICES_SIZE & 0xffff_ffff) >> 32) as u32,
473+
];
474+
let pci_node = fdt.begin_node(&pci_node_name)?;
475+
476+
fdt.property_string("compatible", "pci-host-ecam-generic")?;
477+
fdt.property_string("device_type", "pci")?;
478+
fdt.property_array_u32("ranges", &ranges)?;
479+
fdt.property_array_u32("bus-range", &[0, 0])?;
480+
fdt.property_u32("linux,pci-domain", segment.id.into())?;
481+
fdt.property_u32("#address-cells", 3)?;
482+
fdt.property_u32("#size-cells", 2)?;
483+
fdt.property_array_u64(
484+
"reg",
485+
&[
486+
segment.mmio_config_address,
487+
PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
488+
],
489+
)?;
490+
fdt.property_u32("#interrupt-cells", 1)?;
491+
fdt.property_null("interrupt-map")?;
492+
fdt.property_null("interrupt-map-mask")?;
493+
fdt.property_null("dma-coherent")?;
494+
Ok(fdt.end_node(pci_node)?)
495+
}
496+
434497
#[cfg(test)]
435498
mod tests {
436499
use std::ffi::CString;

0 commit comments

Comments
 (0)