@@ -15,6 +15,7 @@ use vm_memory::GuestMemoryError;
1515use  super :: super :: { DeviceType ,  InitrdConfig } ; 
1616use  super :: cache_info:: { CacheEntry ,  read_cache_config} ; 
1717use  super :: gic:: GICDevice ; 
18+ use  crate :: device_manager:: mmio:: MMIODeviceInfo ; 
1819use  crate :: devices:: acpi:: vmgenid:: { VMGENID_MEM_SIZE ,  VmGenId } ; 
1920use  crate :: vstate:: memory:: { Address ,  GuestMemory ,  GuestMemoryMmap } ; 
2021
@@ -42,16 +43,6 @@ const GIC_FDT_IRQ_TYPE_PPI: u32 = 1;
4243const  IRQ_TYPE_EDGE_RISING :  u32  = 1 ; 
4344const  IRQ_TYPE_LEVEL_HI :  u32  = 4 ; 
4445
45- /// Trait for devices to be added to the Flattened Device Tree. 
46- pub  trait  DeviceInfoForFDT  { 
47-     /// Returns the address where this device will be loaded. 
48- fn  addr ( & self )  -> u64 ; 
49-     /// Returns the associated interrupt for this device. 
50- fn  irq ( & self )  -> u32 ; 
51-     /// Returns the amount of memory that needs to be reserved for this device. 
52- fn  length ( & self )  -> u64 ; 
53- } 
54- 
5546/// Errors thrown while configuring the Flattened Device Tree for aarch64. 
5647#[ derive( Debug ,  thiserror:: Error ,  displaydoc:: Display ) ]  
5748pub  enum  FdtError  { 
@@ -64,11 +55,11 @@ pub enum FdtError {
6455} 
6556
6657/// Creates the flattened device tree for this aarch64 microVM. 
67- pub  fn  create_fdt < T :   DeviceInfoForFDT  +  Clone  +  Debug > ( 
58+ pub  fn  create_fdt ( 
6859    guest_mem :  & GuestMemoryMmap , 
6960    vcpu_mpidr :  Vec < u64 > , 
7061    cmdline :  CString , 
71-     device_info :  & HashMap < ( DeviceType ,  String ) ,  T > , 
62+     device_info :  & HashMap < ( DeviceType ,  String ) ,  MMIODeviceInfo > , 
7263    gic_device :  & GICDevice , 
7364    vmgenid :  & Option < VmGenId > , 
7465    initrd :  & Option < InitrdConfig > , 
@@ -361,69 +352,68 @@ fn create_psci_node(fdt: &mut FdtWriter) -> Result<(), FdtError> {
361352    Ok ( ( ) ) 
362353} 
363354
364- fn  create_virtio_node < T :  DeviceInfoForFDT  + Clone  + Debug > ( 
365-     fdt :  & mut  FdtWriter , 
366-     dev_info :  & T , 
367- )  -> Result < ( ) ,  FdtError >  { 
368-     let  virtio_mmio = fdt. begin_node ( & format ! ( "virtio_mmio@{:x}" ,  dev_info. addr( ) ) ) ?; 
355+ fn  create_virtio_node ( fdt :  & mut  FdtWriter ,  dev_info :  & MMIODeviceInfo )  -> Result < ( ) ,  FdtError >  { 
356+     let  virtio_mmio = fdt. begin_node ( & format ! ( "virtio_mmio@{:x}" ,  dev_info. addr) ) ?; 
369357
370358    fdt. property_string ( "compatible" ,  "virtio,mmio" ) ?; 
371-     fdt. property_array_u64 ( "reg" ,  & [ dev_info. addr ( ) ,  dev_info. length ( ) ] ) ?; 
359+     fdt. property_array_u64 ( "reg" ,  & [ dev_info. addr ,  dev_info. len ] ) ?; 
372360    fdt. property_array_u32 ( 
373361        "interrupts" , 
374-         & [ GIC_FDT_IRQ_TYPE_SPI ,  dev_info. irq ( ) ,  IRQ_TYPE_EDGE_RISING ] , 
362+         & [ 
363+             GIC_FDT_IRQ_TYPE_SPI , 
364+             dev_info. irq . unwrap ( ) . into ( ) , 
365+             IRQ_TYPE_EDGE_RISING , 
366+         ] , 
375367    ) ?; 
376368    fdt. property_u32 ( "interrupt-parent" ,  GIC_PHANDLE ) ?; 
377369    fdt. end_node ( virtio_mmio) ?; 
378370
379371    Ok ( ( ) ) 
380372} 
381373
382- fn  create_serial_node < T :  DeviceInfoForFDT  + Clone  + Debug > ( 
383-     fdt :  & mut  FdtWriter , 
384-     dev_info :  & T , 
385- )  -> Result < ( ) ,  FdtError >  { 
386-     let  serial = fdt. begin_node ( & format ! ( "uart@{:x}" ,  dev_info. addr( ) ) ) ?; 
374+ fn  create_serial_node ( fdt :  & mut  FdtWriter ,  dev_info :  & MMIODeviceInfo )  -> Result < ( ) ,  FdtError >  { 
375+     let  serial = fdt. begin_node ( & format ! ( "uart@{:x}" ,  dev_info. addr) ) ?; 
387376
388377    fdt. property_string ( "compatible" ,  "ns16550a" ) ?; 
389-     fdt. property_array_u64 ( "reg" ,  & [ dev_info. addr ( ) ,  dev_info. length ( ) ] ) ?; 
378+     fdt. property_array_u64 ( "reg" ,  & [ dev_info. addr ,  dev_info. len ] ) ?; 
390379    fdt. property_u32 ( "clocks" ,  CLOCK_PHANDLE ) ?; 
391380    fdt. property_string ( "clock-names" ,  "apb_pclk" ) ?; 
392381    fdt. property_array_u32 ( 
393382        "interrupts" , 
394-         & [ GIC_FDT_IRQ_TYPE_SPI ,  dev_info. irq ( ) ,  IRQ_TYPE_EDGE_RISING ] , 
383+         & [ 
384+             GIC_FDT_IRQ_TYPE_SPI , 
385+             dev_info. irq . unwrap ( ) . into ( ) , 
386+             IRQ_TYPE_EDGE_RISING , 
387+         ] , 
395388    ) ?; 
396389    fdt. end_node ( serial) ?; 
397390
398391    Ok ( ( ) ) 
399392} 
400393
401- fn  create_rtc_node < T :  DeviceInfoForFDT  + Clone  + Debug > ( 
402-     fdt :  & mut  FdtWriter , 
403-     dev_info :  & T , 
404- )  -> Result < ( ) ,  FdtError >  { 
394+ fn  create_rtc_node ( fdt :  & mut  FdtWriter ,  dev_info :  & MMIODeviceInfo )  -> Result < ( ) ,  FdtError >  { 
405395    // Driver requirements: 
406396    // https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/rtc/arm,pl031.yaml 
407397    // We do not offer the `interrupt` property because the device 
408398    // does not implement interrupt support. 
409399    let  compatible = b"arm,pl031\0 arm,primecell\0 " ; 
410400
411-     let  rtc = fdt. begin_node ( & format ! ( "rtc@{:x}" ,  dev_info. addr( ) ) ) ?; 
401+     let  rtc = fdt. begin_node ( & format ! ( "rtc@{:x}" ,  dev_info. addr) ) ?; 
412402    fdt. property ( "compatible" ,  compatible) ?; 
413-     fdt. property_array_u64 ( "reg" ,  & [ dev_info. addr ( ) ,  dev_info. length ( ) ] ) ?; 
403+     fdt. property_array_u64 ( "reg" ,  & [ dev_info. addr ,  dev_info. len ] ) ?; 
414404    fdt. property_u32 ( "clocks" ,  CLOCK_PHANDLE ) ?; 
415405    fdt. property_string ( "clock-names" ,  "apb_pclk" ) ?; 
416406    fdt. end_node ( rtc) ?; 
417407
418408    Ok ( ( ) ) 
419409} 
420410
421- fn  create_devices_node < T :   DeviceInfoForFDT  +  Clone  +  Debug ,   S :  std :: hash :: BuildHasher > ( 
411+ fn  create_devices_node ( 
422412    fdt :  & mut  FdtWriter , 
423-     dev_info :  & HashMap < ( DeviceType ,  String ) ,  T ,   S > , 
413+     dev_info :  & HashMap < ( DeviceType ,  String ) ,  MMIODeviceInfo > , 
424414)  -> Result < ( ) ,  FdtError >  { 
425415    // Create one temp Vec to store all virtio devices 
426-     let  mut  ordered_virtio_device:  Vec < & T >  = Vec :: new ( ) ; 
416+     let  mut  ordered_virtio_device:  Vec < & MMIODeviceInfo >  = Vec :: new ( ) ; 
427417
428418    for  ( ( device_type,  _device_id) ,  info)  in  dev_info { 
429419        match  device_type { 
@@ -437,7 +427,7 @@ fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug, S: std::hash::BuildH
437427    } 
438428
439429    // Sort out virtio devices by address from low to high and insert them into fdt table. 
440-     ordered_virtio_device. sort_by_key ( |& a| a. addr ( ) ) ; 
430+     ordered_virtio_device. sort_by_key ( |a| a. addr ) ; 
441431    for  ordered_device_info in  ordered_virtio_device. drain ( ..)  { 
442432        create_virtio_node ( fdt,  ordered_device_info) ?; 
443433    } 
@@ -448,6 +438,7 @@ fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug, S: std::hash::BuildH
448438#[ cfg( test) ]  
449439mod  tests { 
450440    use  std:: ffi:: CString ; 
441+     use  std:: num:: NonZeroU32 ; 
451442
452443    use  kvm_ioctls:: Kvm ; 
453444
@@ -460,23 +451,6 @@ mod tests {
460451
461452    const  LEN :  u64  = 4096 ; 
462453
463-     #[ derive( Clone ,  Debug ) ]  
464-     pub  struct  MMIODeviceInfo  { 
465-         addr :  u64 , 
466-         irq :  u32 , 
467-     } 
468- 
469-     impl  DeviceInfoForFDT  for  MMIODeviceInfo  { 
470-         fn  addr ( & self )  -> u64  { 
471-             self . addr 
472-         } 
473-         fn  irq ( & self )  -> u32  { 
474-             self . irq 
475-         } 
476-         fn  length ( & self )  -> u64  { 
477-             LEN 
478-         } 
479-     } 
480454    // The `load` function from the `device_tree` will mistakenly check the actual size 
481455    // of the buffer with the allocated size. This works around that. 
482456    fn  set_size ( buf :  & mut  [ u8 ] ,  pos :  usize ,  val :  u32 )  { 
@@ -493,17 +467,26 @@ mod tests {
493467        let  dev_info:  HashMap < ( DeviceType ,  std:: string:: String ) ,  MMIODeviceInfo >  = [ 
494468            ( 
495469                ( DeviceType :: Serial ,  DeviceType :: Serial . to_string ( ) ) , 
496-                 MMIODeviceInfo  {  addr :  0x00 ,  irq :  1  } , 
470+                 MMIODeviceInfo  { 
471+                     addr :  0x00 , 
472+                     irq :  NonZeroU32 :: new ( 1 ) , 
473+                     len :  LEN , 
474+                 } , 
497475            ) , 
498476            ( 
499477                ( DeviceType :: Virtio ( 1 ) ,  "virtio" . to_string ( ) ) , 
500-                 MMIODeviceInfo  {  addr :  LEN ,  irq :  2  } , 
478+                 MMIODeviceInfo  { 
479+                     addr :  LEN , 
480+                     irq :  NonZeroU32 :: new ( 2 ) , 
481+                     len :  LEN , 
482+                 } , 
501483            ) , 
502484            ( 
503485                ( DeviceType :: Rtc ,  "rtc" . to_string ( ) ) , 
504486                MMIODeviceInfo  { 
505487                    addr :  2  *  LEN , 
506-                     irq :  3 , 
488+                     irq :  NonZeroU32 :: new ( 3 ) , 
489+                     len :  LEN , 
507490                } , 
508491            ) , 
509492        ] 
0 commit comments