vmm:AArch64: move uefi_flash to memory manager

uefi_flash is used when load firmware, that is load payload depends on
device manager. move uefi_flash to memory manager can eliminate the
dependency.

Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2022-08-30 20:01:09 +08:00 committed by Rob Bradford
parent 9b1452f258
commit b65639fad3
3 changed files with 51 additions and 52 deletions

View File

@ -21,8 +21,6 @@ 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};
@ -51,7 +49,7 @@ use devices::legacy::Serial;
use devices::{
interrupt_controller, interrupt_controller::InterruptController, AcpiNotificationFlags,
};
use hypervisor::{HypervisorType, HypervisorVmError, IoEventAddress};
use hypervisor::{HypervisorType, IoEventAddress};
use libc::{
cfmakeraw, isatty, tcgetattr, tcsetattr, termios, MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED,
O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW,
@ -92,8 +90,6 @@ 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")]
@ -464,9 +460,6 @@ pub enum DeviceManagerError {
/// Cannot hotplug device behind vIOMMU
InvalidIommuHotplug,
/// Failed to create UEFI flash
CreateUefiFlash(HypervisorVmError),
/// Invalid identifier as it is not unique.
IdentifierNotUnique(String),
@ -929,10 +922,6 @@ 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,
@ -1089,8 +1078,6 @@ 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,
@ -1685,38 +1672,6 @@ 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(())
}
@ -4162,11 +4117,6 @@ impl DeviceManager {
&self.iommu_attached_devices
}
#[cfg(target_arch = "aarch64")]
pub fn uefi_flash(&self) -> GuestMemoryAtomic<GuestMemoryMmap> {
self.uefi_flash.as_ref().unwrap().clone()
}
fn validate_identifier(&self, id: &Option<String>) -> DeviceManagerResult<()> {
if let Some(id) = id {
if id.starts_with("__") {

View File

@ -19,6 +19,8 @@ use arch::x86_64::{SgxEpcRegion, SgxEpcSection};
use arch::{layout, RegionType};
#[cfg(target_arch = "x86_64")]
use devices::ioapic;
#[cfg(target_arch = "aarch64")]
use hypervisor::HypervisorVmError;
#[cfg(target_arch = "x86_64")]
use libc::{MAP_NORESERVE, MAP_POPULATE, MAP_SHARED, PROT_READ, PROT_WRITE};
use serde::{Deserialize, Serialize};
@ -185,6 +187,8 @@ pub struct MemoryManager {
guest_ram_mappings: Vec<GuestRamMapping>,
pub acpi_address: Option<GuestAddress>,
#[cfg(target_arch = "aarch64")]
uefi_flash: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
}
#[derive(Debug)]
@ -314,6 +318,10 @@ pub enum Error {
/// Failed to allocate MMIO address
AllocateMmioAddress,
#[cfg(target_arch = "aarch64")]
/// Failed to create UEFI flash
CreateUefiFlash(HypervisorVmError),
}
const ENABLE_FLAG: usize = 0;
@ -825,6 +833,36 @@ impl MemoryManager {
Ok(())
}
#[cfg(target_arch = "aarch64")]
fn add_uefi_flash(&mut self) -> Result<(), Error> {
// 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.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.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.vm
.create_user_memory_region(uefi_mem_region)
.map_err(Error::CreateUefiFlash)?;
let uefi_flash =
GuestMemoryAtomic::new(GuestMemoryMmap::from_regions(vec![uefi_region]).unwrap());
self.uefi_flash = Some(uefi_flash);
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn new(
vm: Arc<dyn hypervisor::Vm>,
@ -1081,9 +1119,15 @@ impl MemoryManager {
arch_mem_regions,
ram_allocator,
dynamic,
#[cfg(target_arch = "aarch64")]
uefi_flash: None,
};
memory_manager.allocate_address_space()?;
#[cfg(target_arch = "aarch64")]
memory_manager.add_uefi_flash()?;
#[cfg(target_arch = "x86_64")]
if let Some(sgx_epc_config) = sgx_epc_config {
memory_manager.setup_sgx(sgx_epc_config)?;
@ -1857,6 +1901,11 @@ impl MemoryManager {
self.guest_ram_mappings.len() as u32
}
#[cfg(target_arch = "aarch64")]
pub fn uefi_flash(&self) -> GuestMemoryAtomic<GuestMemoryMmap> {
self.uefi_flash.as_ref().unwrap().clone()
}
#[cfg(feature = "guest_debug")]
pub fn coredump_memory_regions(&self, mem_offset: u64) -> CoredumpMemoryRegions {
let mut mapping_sorted_by_gpa = self.guest_ram_mappings.clone();

View File

@ -953,7 +953,7 @@ impl Vm {
#[cfg(target_arch = "aarch64")]
fn load_firmware(&self, mut firmware: &File) -> Result<()> {
let uefi_flash = self.device_manager.lock().as_ref().unwrap().uefi_flash();
let uefi_flash = self.memory_manager.lock().as_ref().unwrap().uefi_flash();
let mem = uefi_flash.memory();
arch::aarch64::uefi::load_uefi(mem.deref(), arch::layout::UEFI_START, &mut firmware)
.map_err(Error::UefiLoad)?;