@@ -13,8 +13,13 @@ use vm_memory::GuestMemoryError;
1313
1414use super :: cache_info:: { CacheEntry , read_cache_config} ;
1515use 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+ } ;
1620use crate :: device_manager:: DeviceManager ;
1721use crate :: device_manager:: mmio:: MMIODeviceInfo ;
22+ use crate :: device_manager:: pci_mngr:: PciDevices ;
1823use crate :: devices:: acpi:: vmgenid:: { VMGENID_MEM_SIZE , VmGenId } ;
1924use crate :: initrd:: InitrdConfig ;
2025use 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,59 @@ 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+ let ranges = [
450+ // 32bit addresses
451+ 0x200_0000u32 ,
452+ ( MEM_32BIT_DEVICES_START >> 32 ) as u32 , // PCI address
453+ ( MEM_32BIT_DEVICES_START & 0xffff_ffff ) as u32 ,
454+ ( MEM_32BIT_DEVICES_START >> 32 ) as u32 , // CPU address
455+ ( MEM_32BIT_DEVICES_START & 0xffff_ffff ) as u32 ,
456+ ( MEM_32BIT_DEVICES_SIZE >> 32 ) as u32 , // Range size
457+ ( MEM_32BIT_DEVICES_SIZE & 0xffff_ffff ) as u32 ,
458+ // 64bit addresses
459+ 0x300_0000u32 ,
460+ // PCI address
461+ ( MEM_64BIT_DEVICES_START >> 32 ) as u32 , // PCI address
462+ ( MEM_64BIT_DEVICES_START & 0xffff_ffff ) as u32 ,
463+ // CPU address
464+ ( MEM_64BIT_DEVICES_START >> 32 ) as u32 , // CPU address
465+ ( MEM_64BIT_DEVICES_START & 0xffff_ffff ) as u32 ,
466+ // Range size
467+ ( MEM_64BIT_DEVICES_SIZE >> 32 ) as u32 , // Range size
468+ ( ( MEM_64BIT_DEVICES_SIZE & 0xffff_ffff ) >> 32 ) as u32 ,
469+ ] ;
470+ let pci_node = fdt. begin_node ( & pci_node_name) ?;
471+
472+ fdt. property_string ( "compatible" , "pci-host-ecam-generic" ) ?;
473+ fdt. property_string ( "device_type" , "pci" ) ?;
474+ fdt. property_array_u32 ( "ranges" , & ranges) ?;
475+ fdt. property_array_u32 ( "bus-range" , & [ 0 , 0 ] ) ?;
476+ fdt. property_u32 ( "linux,pci-domain" , segment. id . into ( ) ) ?;
477+ fdt. property_u32 ( "#address-cells" , 3 ) ?;
478+ fdt. property_u32 ( "#size-cells" , 2 ) ?;
479+ fdt. property_array_u64 (
480+ "reg" ,
481+ & [
482+ segment. mmio_config_address ,
483+ PCI_MMIO_CONFIG_SIZE_PER_SEGMENT ,
484+ ] ,
485+ ) ?;
486+ fdt. property_u32 ( "#interrupt-cells" , 1 ) ?;
487+ fdt. property_null ( "interrupt-map" ) ?;
488+ fdt. property_null ( "interrupt-map-mask" ) ?;
489+ fdt. property_null ( "dma-coherent" ) ?;
490+ Ok ( fdt. end_node ( pci_node) ?)
491+ }
492+
434493#[ cfg( test) ]
435494mod tests {
436495 use std:: ffi:: CString ;
0 commit comments