mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 05:35:20 +00:00
aarch64: Add a memory-simulated flash for UEFI
EDK2 execution requires a flash device at address 0. The new added device is not a fully functional flash. It doesn't implement any spec of a flash device. Instead, a piece of memory is used to simulate the flash simply. Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
parent
9dd107bb03
commit
d1b2a3fca9
@ -42,11 +42,11 @@
|
||||
// | Legacy devices space |
|
||||
// | |
|
||||
// 144 M +---------------------------------------------------------------|
|
||||
// | |
|
||||
// | Reserved (now GIC is here) |
|
||||
// 64 M +---------------------------------------------------------------+
|
||||
// | |
|
||||
// | UEFI space |
|
||||
// | |
|
||||
// 4 M +---------------------------------------------------------------+
|
||||
// | UEFI flash |
|
||||
// 0GB +---------------------------------------------------------------+
|
||||
//
|
||||
//
|
||||
|
@ -25,6 +25,8 @@ use crate::pci_segment::PciSegment;
|
||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||
use crate::serial_manager::{Error as SerialManagerError, SerialManager};
|
||||
use crate::sigwinch_listener::start_sigwinch_listener;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::GuestRegionMmap;
|
||||
use crate::PciDeviceInfo;
|
||||
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
|
||||
@ -96,6 +98,8 @@ use vm_device::interrupt::{
|
||||
};
|
||||
use vm_device::{Bus, BusDevice, Resource};
|
||||
use vm_memory::guest_memory::FileOffset;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use vm_memory::GuestMemoryAtomic;
|
||||
use vm_memory::GuestMemoryRegion;
|
||||
use vm_memory::{Address, GuestAddress, GuestUsize, MmapRegion};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@ -473,6 +477,9 @@ pub enum DeviceManagerError {
|
||||
|
||||
/// Cannot hotplug device behind vIOMMU
|
||||
InvalidIommuHotplug,
|
||||
|
||||
/// Failed to create UEFI flash
|
||||
CreateUefiFlash(hypervisor::vm::HypervisorVmError),
|
||||
}
|
||||
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
|
||||
|
||||
@ -924,6 +931,10 @@ pub struct DeviceManager {
|
||||
// GPIO device for AArch64
|
||||
gpio_device: Option<Arc<Mutex<devices::legacy::Gpio>>>,
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
// Flash device for UEFI on AArch64
|
||||
uefi_flash: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
|
||||
// Flag to force setting the iommu on virtio devices
|
||||
force_iommu: bool,
|
||||
|
||||
@ -1067,6 +1078,8 @@ impl DeviceManager {
|
||||
virtio_mem_devices: Vec::new(),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
gpio_device: None,
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
uefi_flash: None,
|
||||
force_iommu,
|
||||
restoring,
|
||||
io_uring_supported: None,
|
||||
@ -1602,6 +1615,38 @@ impl DeviceManager {
|
||||
.unwrap()
|
||||
.insert(id.clone(), device_node!(id, gpio_device));
|
||||
|
||||
// On AArch64, the UEFI binary requires a flash device at address 0.
|
||||
// 4 MiB memory is mapped to simulate the flash.
|
||||
let uefi_mem_slot = self.memory_manager.lock().unwrap().allocate_memory_slot();
|
||||
let uefi_region = GuestRegionMmap::new(
|
||||
MmapRegion::new(arch::layout::UEFI_SIZE as usize).unwrap(),
|
||||
arch::layout::UEFI_START,
|
||||
)
|
||||
.unwrap();
|
||||
let uefi_mem_region = self
|
||||
.memory_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.vm
|
||||
.make_user_memory_region(
|
||||
uefi_mem_slot,
|
||||
uefi_region.start_addr().raw_value(),
|
||||
uefi_region.len() as u64,
|
||||
uefi_region.as_ptr() as u64,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
self.memory_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.vm
|
||||
.create_user_memory_region(uefi_mem_region)
|
||||
.map_err(DeviceManagerError::CreateUefiFlash)?;
|
||||
|
||||
let uefi_flash =
|
||||
GuestMemoryAtomic::new(GuestMemoryMmap::from_regions(vec![uefi_region]).unwrap());
|
||||
self.uefi_flash = Some(uefi_flash);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -4141,6 +4186,11 @@ impl DeviceManager {
|
||||
pub fn iommu_attached_devices(&self) -> &Option<(PciBdf, Vec<PciBdf>)> {
|
||||
&self.iommu_attached_devices
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub fn uefi_flash(&self) -> GuestMemoryAtomic<GuestMemoryMmap> {
|
||||
self.uefi_flash.as_ref().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn numa_node_id_from_memory_zone_id(numa_nodes: &NumaNodes, memory_zone_id: &str) -> Option<u32> {
|
||||
|
@ -1001,8 +1001,11 @@ impl Vm {
|
||||
// If failed, retry to load it as UEFI binary.
|
||||
// As the UEFI binary is formatless, it must be the last option to try.
|
||||
Err(linux_loader::loader::Error::Pe(InvalidImageMagicNumber)) => {
|
||||
let uefi_flash = self.device_manager.lock().as_ref().unwrap().uefi_flash();
|
||||
let mem = uefi_flash.memory();
|
||||
arch::aarch64::uefi::load_uefi(mem.deref(), arch::layout::UEFI_START, &mut kernel)
|
||||
.map_err(Error::UefiLoad)?;
|
||||
|
||||
// The entry point offset in UEFI image is always 0.
|
||||
return Ok(EntryPoint {
|
||||
entry_addr: arch::layout::UEFI_START,
|
||||
|
Loading…
Reference in New Issue
Block a user