Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions openvmm/openvmm_core/src/worker/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,25 @@ impl InitializedVm {
#[cfg(not(guest_arch = "aarch64"))]
let smmu_count = 0;

// On aarch64 Linux direct boot, start RAM at 1 GiB to avoid the low GPA
// region (128 MiB–129 MiB) that iommufd reserves for the host MSI
// doorbell in IOVA space. Without this gap, iommufd identity-mapped DMA
// for passthrough devices fails because it cannot allocate IOVAs in
// that range.
//
// FUTURE: this needs to be present for UEFI as well, but UEFI cannot
// only boot from low memory. Either:
Comment thread
jstarks marked this conversation as resolved.
// 1. Fix Linux to allow configuring the reserved IOVA range.
// 2. Fix UEFI to allow booting from >0.
// 3. Install a little bit of low memory, enough for UEFI to get to DXE
// (which can run anywhere.)
let ram_start_address =
if cfg!(guest_arch = "aarch64") && matches!(cfg.load_mode, LoadMode::Linux { .. }) {
1024 * 1024 * 1024 // 1 GiB
} else {
0
};

let resolved_layout = resolve_memory_layout(MemoryLayoutInput {
mem_size: cfg.memory.mem_size,
numa_mem_sizes: cfg.memory.numa_mem_sizes.as_deref(),
Expand All @@ -1011,6 +1030,7 @@ impl InitializedVm {
virtio_mmio_count,
smmu_count,
vtl2_layout,
ram_start_address,
physical_address_size,
})
.context("invalid memory configuration")?;
Expand Down
13 changes: 13 additions & 0 deletions openvmm/openvmm_core/src/worker/memory_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ pub(super) struct MemoryLayoutInput<'a> {
/// Optional IGVM VTL2 private-memory request. This is allocated after all
/// VTL0-visible RAM and MMIO and is carried separately from ordinary RAM.
pub vtl2_layout: Option<Vtl2MemoryLayoutRequest>,
/// Minimum guest physical address for ordinary RAM. When nonzero, the
/// range `0..ram_start_address` is reserved so RAM is placed above it.
/// This is used on aarch64 Linux direct boot to avoid the low GPA region
/// that conflicts with iommufd IOVA reservations.
pub ram_start_address: u64,
/// Host-supported physical address width used only after allocation. The
/// allocator computes the smallest layout it can; host fit is validation.
pub physical_address_size: u8,
Expand Down Expand Up @@ -138,6 +143,13 @@ pub(super) fn resolve_memory_layout(
// least the architectural reserved zone (LAPIC, IOAPIC, TPM, ...) so
// guests can arbitrate fixed-address children like TPM2 against this
// window; the caller-requested size may extend it lower.
// Reserve low addresses so RAM starts above `ram_start_address`. This is
// used on aarch64 Linux direct boot to skip the 128 MiB–129 MiB IOVA
// region that iommufd reserves for the host MSI doorbell.
if input.ram_start_address > 0 {
builder.reserve("low-ram-gap", MemoryRange::new(0..input.ram_start_address));
Comment thread
jstarks marked this conversation as resolved.
}
Comment thread
jstarks marked this conversation as resolved.

let arch_reserved = if cfg!(guest_arch = "x86_64") {
ARCH_RESERVED_X86_64
} else {
Expand Down Expand Up @@ -542,6 +554,7 @@ mod tests {
virtio_mmio_count: 0,
smmu_count: 0,
vtl2_layout,
ram_start_address: 0,
physical_address_size: 46,
}
}
Expand Down
Loading