@@ -13,8 +13,13 @@ use vm_memory::GuestMemoryError;
13
13
14
14
use super :: cache_info:: { CacheEntry , read_cache_config} ;
15
15
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
+ } ;
16
20
use crate :: device_manager:: DeviceManager ;
17
21
use crate :: device_manager:: mmio:: MMIODeviceInfo ;
22
+ use crate :: device_manager:: pci_mngr:: PciDevices ;
18
23
use crate :: devices:: acpi:: vmgenid:: { VMGENID_MEM_SIZE , VmGenId } ;
19
24
use crate :: initrd:: InitrdConfig ;
20
25
use crate :: vstate:: memory:: { Address , GuestMemory , GuestMemoryMmap } ;
@@ -90,6 +95,7 @@ pub fn create_fdt(
90
95
create_psci_node ( & mut fdt_writer) ?;
91
96
create_devices_node ( & mut fdt_writer, device_manager) ?;
92
97
create_vmgenid_node ( & mut fdt_writer, & device_manager. acpi_devices . vmgenid ) ?;
98
+ create_pci_nodes ( & mut fdt_writer, & device_manager. pci_devices ) ?;
93
99
94
100
// End Header node.
95
101
fdt_writer. end_node ( root) ?;
@@ -431,6 +437,59 @@ fn create_devices_node(
431
437
Ok ( ( ) )
432
438
}
433
439
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
+
434
493
#[ cfg( test) ]
435
494
mod tests {
436
495
use std:: ffi:: CString ;
0 commit comments