diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index 8d7c773c7..61e686bb9 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -12,7 +12,7 @@ use acpi_tables::{aml, aml::Aml}; use anyhow::anyhow; #[cfg(target_arch = "x86_64")] use arch::x86_64::{SgxEpcRegion, SgxEpcSection}; -use arch::{get_host_cpu_phys_bits, layout, RegionType}; +use arch::{layout, RegionType}; #[cfg(target_arch = "x86_64")] use devices::ioapic; #[cfg(target_arch = "x86_64")] @@ -256,8 +256,8 @@ const SELECTION_OFFSET: u64 = 0; // The MMIO address space size is subtracted with the size of a 4k page. This // is done on purpose to workaround a Linux bug when the VMM allocates devices // at the end of the addressable space. -fn mmio_address_space_size() -> u64 { - (1 << get_host_cpu_phys_bits()) - 0x1000 +fn mmio_address_space_size(phys_bits: u8) -> u64 { + (1 << phys_bits) - 0x1000 } impl BusDevice for MemoryManager { @@ -448,6 +448,7 @@ impl MemoryManager { config: &MemoryConfig, ext_regions: Option>, prefault: bool, + phys_bits: u8, ) -> Result>, Error> { let user_provided_zones = config.size == 0; let mut allow_mem_hotplug: bool = false; @@ -585,7 +586,8 @@ impl MemoryManager { let boot_guest_memory = guest_memory.clone(); - let end_of_device_area = GuestAddress(mmio_address_space_size() - 1); + let mmio_address_space_size = mmio_address_space_size(phys_bits); + let end_of_device_area = GuestAddress(mmio_address_space_size - 1); let mut start_of_device_area = MemoryManager::start_addr(guest_memory.last_addr(), allow_mem_hotplug)?; @@ -656,7 +658,7 @@ impl MemoryManager { #[cfg(target_arch = "x86_64")] (1 << 16 as GuestUsize), GuestAddress(0), - mmio_address_space_size(), + mmio_address_space_size, layout::MEM_32BIT_DEVICES_START, layout::MEM_32BIT_DEVICES_SIZE, #[cfg(target_arch = "x86_64")] @@ -740,6 +742,7 @@ impl MemoryManager { config: &MemoryConfig, source_url: &str, prefault: bool, + phys_bits: u8, ) -> Result>, Error> { let url = Url::parse(source_url).unwrap(); /* url must be valid dir which is verified in recv_vm_snapshot() */ @@ -777,7 +780,7 @@ impl MemoryManager { } } - MemoryManager::new(vm, config, Some(ext_regions), prefault) + MemoryManager::new(vm, config, Some(ext_regions), prefault, phys_bits) } else { Err(Error::Restore(MigratableError::Restore(anyhow!( "Could not find {}-section from snapshot", diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 93a904d7b..7bd0d527f 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -38,6 +38,7 @@ use crate::{ PciDeviceInfo, CPU_MANAGER_SNAPSHOT_ID, DEVICE_MANAGER_SNAPSHOT_ID, MEMORY_MANAGER_SNAPSHOT_ID, }; use anyhow::anyhow; +use arch::get_host_cpu_phys_bits; #[cfg(target_arch = "x86_64")] use arch::BootProtocol; use arch::EntryPoint; @@ -51,6 +52,7 @@ use linux_loader::loader::elf::PvhBootCapability::PvhEntryPresent; use linux_loader::loader::KernelLoader; use seccomp::{SeccompAction, SeccompFilter}; use signal_hook::{iterator::Signals, SIGINT, SIGTERM, SIGWINCH}; +use std::cmp; use std::collections::{BTreeMap, HashMap}; use std::convert::TryInto; use std::ffi::CString; @@ -431,6 +433,11 @@ impl VmmOps for VmOps { } } +fn physical_bits(max_phys_bits: Option) -> u8 { + let host_phys_bits = get_host_cpu_phys_bits(); + cmp::min(host_phys_bits, max_phys_bits.unwrap_or(host_phys_bits)) +} + pub struct Vm { kernel: File, initramfs: Option, @@ -629,11 +636,13 @@ impl Vm { let vm = hypervisor.create_vm().unwrap(); #[cfg(target_arch = "x86_64")] vm.enable_split_irq().unwrap(); + let phys_bits = physical_bits(config.lock().unwrap().cpus.max_phys_bits); let memory_manager = MemoryManager::new( vm.clone(), &config.lock().unwrap().memory.clone(), None, false, + phys_bits, ) .map_err(Error::MemoryManager)?; @@ -697,12 +706,14 @@ impl Vm { let memory_manager = if let Some(memory_manager_snapshot) = snapshot.snapshots.get(MEMORY_MANAGER_SNAPSHOT_ID) { + let phys_bits = physical_bits(config.lock().unwrap().cpus.max_phys_bits); MemoryManager::new_from_snapshot( memory_manager_snapshot, vm.clone(), &config.lock().unwrap().memory.clone(), source_url, prefault, + phys_bits, ) .map_err(Error::MemoryManager)? } else {