@@ -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