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