@@ -25,6 +25,8 @@ use crate::pci_segment::PciSegment;
25
25
use crate :: seccomp_filters:: { get_seccomp_filter, Thread } ;
26
26
use crate :: serial_manager:: { Error as SerialManagerError , SerialManager } ;
27
27
use crate :: sigwinch_listener:: start_sigwinch_listener;
28
+ #[ cfg( target_arch = "aarch64" ) ]
29
+ use crate :: GuestMemoryMmap ;
28
30
use crate :: GuestRegionMmap ;
29
31
use crate :: PciDeviceInfo ;
30
32
use crate :: { device_node, DEVICE_MANAGER_SNAPSHOT_ID } ;
@@ -96,6 +98,8 @@ use vm_device::interrupt::{
96
98
} ;
97
99
use vm_device:: { Bus , BusDevice , Resource } ;
98
100
use vm_memory:: guest_memory:: FileOffset ;
101
+ #[ cfg( target_arch = "aarch64" ) ]
102
+ use vm_memory:: GuestMemoryAtomic ;
99
103
use vm_memory:: GuestMemoryRegion ;
100
104
use vm_memory:: { Address , GuestAddress , GuestUsize , MmapRegion } ;
101
105
#[ cfg( target_arch = "x86_64" ) ]
@@ -473,6 +477,9 @@ pub enum DeviceManagerError {
473
477
474
478
/// Cannot hotplug device behind vIOMMU
475
479
InvalidIommuHotplug ,
480
+
481
+ /// Failed to create UEFI flash
482
+ CreateUefiFlash ( hypervisor:: vm:: HypervisorVmError ) ,
476
483
}
477
484
pub type DeviceManagerResult < T > = result:: Result < T , DeviceManagerError > ;
478
485
@@ -924,6 +931,10 @@ pub struct DeviceManager {
924
931
// GPIO device for AArch64
925
932
gpio_device : Option < Arc < Mutex < devices:: legacy:: Gpio > > > ,
926
933
934
+ #[ cfg( target_arch = "aarch64" ) ]
935
+ // Flash device for UEFI on AArch64
936
+ uefi_flash : Option < GuestMemoryAtomic < GuestMemoryMmap > > ,
937
+
927
938
// Flag to force setting the iommu on virtio devices
928
939
force_iommu : bool ,
929
940
@@ -1067,6 +1078,8 @@ impl DeviceManager {
1067
1078
virtio_mem_devices : Vec :: new ( ) ,
1068
1079
#[ cfg( target_arch = "aarch64" ) ]
1069
1080
gpio_device : None ,
1081
+ #[ cfg( target_arch = "aarch64" ) ]
1082
+ uefi_flash : None ,
1070
1083
force_iommu,
1071
1084
restoring,
1072
1085
io_uring_supported : None ,
@@ -1602,6 +1615,38 @@ impl DeviceManager {
1602
1615
. unwrap ( )
1603
1616
. insert ( id. clone ( ) , device_node ! ( id, gpio_device) ) ;
1604
1617
1618
+ // On AArch64, the UEFI binary requires a flash device at address 0.
1619
+ // 4 MiB memory is mapped to simulate the flash.
1620
+ let uefi_mem_slot = self . memory_manager . lock ( ) . unwrap ( ) . allocate_memory_slot ( ) ;
1621
+ let uefi_region = GuestRegionMmap :: new (
1622
+ MmapRegion :: new ( arch:: layout:: UEFI_SIZE as usize ) . unwrap ( ) ,
1623
+ arch:: layout:: UEFI_START ,
1624
+ )
1625
+ . unwrap ( ) ;
1626
+ let uefi_mem_region = self
1627
+ . memory_manager
1628
+ . lock ( )
1629
+ . unwrap ( )
1630
+ . vm
1631
+ . make_user_memory_region (
1632
+ uefi_mem_slot,
1633
+ uefi_region. start_addr ( ) . raw_value ( ) ,
1634
+ uefi_region. len ( ) as u64 ,
1635
+ uefi_region. as_ptr ( ) as u64 ,
1636
+ false ,
1637
+ false ,
1638
+ ) ;
1639
+ self . memory_manager
1640
+ . lock ( )
1641
+ . unwrap ( )
1642
+ . vm
1643
+ . create_user_memory_region ( uefi_mem_region)
1644
+ . map_err ( DeviceManagerError :: CreateUefiFlash ) ?;
1645
+
1646
+ let uefi_flash =
1647
+ GuestMemoryAtomic :: new ( GuestMemoryMmap :: from_regions ( vec ! [ uefi_region] ) . unwrap ( ) ) ;
1648
+ self . uefi_flash = Some ( uefi_flash) ;
1649
+
1605
1650
Ok ( ( ) )
1606
1651
}
1607
1652
@@ -4141,6 +4186,11 @@ impl DeviceManager {
4141
4186
pub fn iommu_attached_devices ( & self ) -> & Option < ( PciBdf , Vec < PciBdf > ) > {
4142
4187
& self . iommu_attached_devices
4143
4188
}
4189
+
4190
+ #[ cfg( target_arch = "aarch64" ) ]
4191
+ pub fn uefi_flash ( & self ) -> GuestMemoryAtomic < GuestMemoryMmap > {
4192
+ self . uefi_flash . as_ref ( ) . unwrap ( ) . clone ( )
4193
+ }
4144
4194
}
4145
4195
4146
4196
fn numa_node_id_from_memory_zone_id ( numa_nodes : & NumaNodes , memory_zone_id : & str ) -> Option < u32 > {
0 commit comments