@@ -15,6 +15,7 @@ use vm_memory::GuestMemoryError;
15
15
use super :: super :: { DeviceType , InitrdConfig } ;
16
16
use super :: cache_info:: { CacheEntry , read_cache_config} ;
17
17
use super :: gic:: GICDevice ;
18
+ use crate :: device_manager:: mmio:: MMIODeviceInfo ;
18
19
use crate :: devices:: acpi:: vmgenid:: { VMGENID_MEM_SIZE , VmGenId } ;
19
20
use crate :: vstate:: memory:: { Address , GuestMemory , GuestMemoryMmap } ;
20
21
@@ -42,16 +43,6 @@ const GIC_FDT_IRQ_TYPE_PPI: u32 = 1;
42
43
const IRQ_TYPE_EDGE_RISING : u32 = 1 ;
43
44
const IRQ_TYPE_LEVEL_HI : u32 = 4 ;
44
45
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
-
55
46
/// Errors thrown while configuring the Flattened Device Tree for aarch64.
56
47
#[ derive( Debug , thiserror:: Error , displaydoc:: Display ) ]
57
48
pub enum FdtError {
@@ -64,11 +55,11 @@ pub enum FdtError {
64
55
}
65
56
66
57
/// Creates the flattened device tree for this aarch64 microVM.
67
- pub fn create_fdt < T : DeviceInfoForFDT + Clone + Debug > (
58
+ pub fn create_fdt (
68
59
guest_mem : & GuestMemoryMmap ,
69
60
vcpu_mpidr : Vec < u64 > ,
70
61
cmdline : CString ,
71
- device_info : & HashMap < ( DeviceType , String ) , T > ,
62
+ device_info : & HashMap < ( DeviceType , String ) , MMIODeviceInfo > ,
72
63
gic_device : & GICDevice ,
73
64
vmgenid : & Option < VmGenId > ,
74
65
initrd : & Option < InitrdConfig > ,
@@ -361,69 +352,68 @@ fn create_psci_node(fdt: &mut FdtWriter) -> Result<(), FdtError> {
361
352
Ok ( ( ) )
362
353
}
363
354
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) ) ?;
369
357
370
358
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 ] ) ?;
372
360
fdt. property_array_u32 (
373
361
"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
+ ] ,
375
367
) ?;
376
368
fdt. property_u32 ( "interrupt-parent" , GIC_PHANDLE ) ?;
377
369
fdt. end_node ( virtio_mmio) ?;
378
370
379
371
Ok ( ( ) )
380
372
}
381
373
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) ) ?;
387
376
388
377
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 ] ) ?;
390
379
fdt. property_u32 ( "clocks" , CLOCK_PHANDLE ) ?;
391
380
fdt. property_string ( "clock-names" , "apb_pclk" ) ?;
392
381
fdt. property_array_u32 (
393
382
"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
+ ] ,
395
388
) ?;
396
389
fdt. end_node ( serial) ?;
397
390
398
391
Ok ( ( ) )
399
392
}
400
393
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 > {
405
395
// Driver requirements:
406
396
// https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/rtc/arm,pl031.yaml
407
397
// We do not offer the `interrupt` property because the device
408
398
// does not implement interrupt support.
409
399
let compatible = b"arm,pl031\0 arm,primecell\0 " ;
410
400
411
- let rtc = fdt. begin_node ( & format ! ( "rtc@{:x}" , dev_info. addr( ) ) ) ?;
401
+ let rtc = fdt. begin_node ( & format ! ( "rtc@{:x}" , dev_info. addr) ) ?;
412
402
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 ] ) ?;
414
404
fdt. property_u32 ( "clocks" , CLOCK_PHANDLE ) ?;
415
405
fdt. property_string ( "clock-names" , "apb_pclk" ) ?;
416
406
fdt. end_node ( rtc) ?;
417
407
418
408
Ok ( ( ) )
419
409
}
420
410
421
- fn create_devices_node < T : DeviceInfoForFDT + Clone + Debug , S : std :: hash :: BuildHasher > (
411
+ fn create_devices_node (
422
412
fdt : & mut FdtWriter ,
423
- dev_info : & HashMap < ( DeviceType , String ) , T , S > ,
413
+ dev_info : & HashMap < ( DeviceType , String ) , MMIODeviceInfo > ,
424
414
) -> Result < ( ) , FdtError > {
425
415
// 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 ( ) ;
427
417
428
418
for ( ( device_type, _device_id) , info) in dev_info {
429
419
match device_type {
@@ -437,7 +427,7 @@ fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug, S: std::hash::BuildH
437
427
}
438
428
439
429
// 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 ) ;
441
431
for ordered_device_info in ordered_virtio_device. drain ( ..) {
442
432
create_virtio_node ( fdt, ordered_device_info) ?;
443
433
}
@@ -448,6 +438,7 @@ fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug, S: std::hash::BuildH
448
438
#[ cfg( test) ]
449
439
mod tests {
450
440
use std:: ffi:: CString ;
441
+ use std:: num:: NonZeroU32 ;
451
442
452
443
use kvm_ioctls:: Kvm ;
453
444
@@ -460,23 +451,6 @@ mod tests {
460
451
461
452
const LEN : u64 = 4096 ;
462
453
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
- }
480
454
// The `load` function from the `device_tree` will mistakenly check the actual size
481
455
// of the buffer with the allocated size. This works around that.
482
456
fn set_size ( buf : & mut [ u8 ] , pos : usize , val : u32 ) {
@@ -493,17 +467,26 @@ mod tests {
493
467
let dev_info: HashMap < ( DeviceType , std:: string:: String ) , MMIODeviceInfo > = [
494
468
(
495
469
( 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
+ } ,
497
475
) ,
498
476
(
499
477
( 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
+ } ,
501
483
) ,
502
484
(
503
485
( DeviceType :: Rtc , "rtc" . to_string ( ) ) ,
504
486
MMIODeviceInfo {
505
487
addr : 2 * LEN ,
506
- irq : 3 ,
488
+ irq : NonZeroU32 :: new ( 3 ) ,
489
+ len : LEN ,
507
490
} ,
508
491
) ,
509
492
]
0 commit comments