aarch64: limit high MMIO addresses to VM phys addr range
The high MMIO region of the system allocator was previously set up with the upper limit of 2**64 - 1, but physical addresses on actual systems are not that large. Now that pmem allocates from the upper end of the high MMIO region, the size of the allocator actually matters. Limit the aarch64 high MMIO allocator to the VM's physical address size so that addresses at the end of the allocation range are usable and pmem devices can be created on aarch64. BUG=b:210727578 TEST=Boot with pmem device on aarch64 Change-Id: I67962c2b03f0f265349ae889c988eb69ef526f4a Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3366858 Reviewed-by: Dmitry Torokhov <dtor@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Andrew Walbran <qwandor@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
3c2abaf838
commit
891ea3e88a
8 changed files with 24 additions and 11 deletions
|
|
@ -246,7 +246,7 @@ impl arch::LinuxArch for AArch64 {
|
|||
}
|
||||
|
||||
fn create_system_allocator<V: Vm>(vm: &V) -> SystemAllocator {
|
||||
Self::get_resource_allocator(vm.get_memory().memory_size())
|
||||
Self::get_resource_allocator(vm.get_memory().memory_size(), vm.get_guest_phys_addr_bits())
|
||||
}
|
||||
|
||||
fn build_vm<V, Vcpu>(
|
||||
|
|
@ -539,13 +539,26 @@ impl AArch64 {
|
|||
}
|
||||
|
||||
/// Returns a system resource allocator.
|
||||
fn get_resource_allocator(mem_size: u64) -> SystemAllocator {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `mem_size` - Size of guest memory (RAM) in bytes.
|
||||
/// * `guest_phys_addr_bits` - Size of guest physical addresses (IPA) in bits.
|
||||
fn get_resource_allocator(mem_size: u64, guest_phys_addr_bits: u8) -> SystemAllocator {
|
||||
let guest_phys_end = 1u64 << guest_phys_addr_bits;
|
||||
// The platform MMIO region is immediately past the end of RAM.
|
||||
let plat_mmio_base = AARCH64_PHYS_MEM_START + mem_size;
|
||||
let plat_mmio_size = AARCH64_PLATFORM_MMIO_SIZE;
|
||||
// The high MMIO region is the rest of the address space after the platform MMIO region.
|
||||
let high_mmio_base = plat_mmio_base + plat_mmio_size;
|
||||
let high_mmio_size = u64::max_value() - high_mmio_base;
|
||||
let high_mmio_size = guest_phys_end
|
||||
.checked_sub(high_mmio_base)
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"guest_phys_end {:#x} < high_mmio_base {:#x}",
|
||||
guest_phys_end, high_mmio_base,
|
||||
);
|
||||
});
|
||||
SystemAllocator::builder()
|
||||
.add_low_mmio_addresses(AARCH64_MMIO_BASE, AARCH64_MMIO_SIZE)
|
||||
.add_platform_mmio_addresses(plat_mmio_base, plat_mmio_size)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ impl Kvm {
|
|||
}
|
||||
|
||||
/// Get the size of guest physical addresses (IPA) in bits.
|
||||
pub fn get_guest_phys_addr_size(&self) -> u8 {
|
||||
pub fn get_guest_phys_addr_bits(&self) -> u8 {
|
||||
// Safe because we know self is a real kvm fd
|
||||
let vm_ipa_size = match unsafe {
|
||||
ioctl_with_val(self, KVM_CHECK_EXTENSION(), KVM_CAP_ARM_VM_IPA_SIZE.into())
|
||||
|
|
|
|||
|
|
@ -453,8 +453,8 @@ impl Vm for KvmVm {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_guest_phys_addr_size(&self) -> u8 {
|
||||
self.kvm.get_guest_phys_addr_size()
|
||||
fn get_guest_phys_addr_bits(&self) -> u8 {
|
||||
self.kvm.get_guest_phys_addr_bits()
|
||||
}
|
||||
|
||||
fn get_memory(&self) -> &GuestMemory {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ impl Kvm {
|
|||
}
|
||||
|
||||
/// Get the size of guest physical addresses in bits.
|
||||
pub fn get_guest_phys_addr_size(&self) -> u8 {
|
||||
pub fn get_guest_phys_addr_bits(&self) -> u8 {
|
||||
// Get host cpu max physical address bits.
|
||||
// Assume the guest physical address size is the same as the host.
|
||||
let highest_ext_function = unsafe { __cpuid(0x80000000) };
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pub trait Vm: Send {
|
|||
fn check_capability(&self, c: VmCap) -> bool;
|
||||
|
||||
/// Get the guest physical address size in bits.
|
||||
fn get_guest_phys_addr_size(&self) -> u8;
|
||||
fn get_guest_phys_addr_bits(&self) -> u8;
|
||||
|
||||
/// Gets the guest-mapped memory for the Vm.
|
||||
fn get_memory(&self) -> &GuestMemory;
|
||||
|
|
|
|||
|
|
@ -2789,7 +2789,7 @@ where
|
|||
None => None,
|
||||
};
|
||||
|
||||
let phys_max_addr = (1u64 << vm.get_guest_phys_addr_size()) - 1;
|
||||
let phys_max_addr = (1u64 << vm.get_guest_phys_addr_bits()) - 1;
|
||||
let mut devices = create_devices(
|
||||
&cfg,
|
||||
&mut vm,
|
||||
|
|
|
|||
|
|
@ -1115,7 +1115,7 @@ impl X8664arch {
|
|||
///
|
||||
/// * `vm`: The virtual machine
|
||||
fn get_high_mmio_size<V: Vm>(vm: &V) -> u64 {
|
||||
let phys_mem_end = 1u64 << vm.get_guest_phys_addr_size();
|
||||
let phys_mem_end = 1u64 << vm.get_guest_phys_addr_bits();
|
||||
let high_mmio_end = std::cmp::min(phys_mem_end, HIGH_MMIO_MAX_END);
|
||||
high_mmio_end - Self::get_high_mmio_base(vm.get_memory())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ fn append_mtrr_entries(
|
|||
return;
|
||||
}
|
||||
|
||||
let phys_mask: u64 = (1 << vm.get_guest_phys_addr_size()) - 1;
|
||||
let phys_mask: u64 = (1 << vm.get_guest_phys_addr_bits()) - 1;
|
||||
for (idx, (base, len)) in vecs.iter().enumerate() {
|
||||
let reg_idx = idx as u32 * 2;
|
||||
entries.push(Register {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue