use alloc::vec::Vec;
use axdevice::AxVmDevices;
use axdevice_base::Resource;
use super::super::{AxVM, AxVMResources, VM_ASPACE_BASE, VM_ASPACE_SIZE};
use crate::{
AxVmError, AxVmResult,
layout::{GuestOwnedRegion, VmRegionKind, build_address_layout},
};
pub(crate) fn map_guest_address_space(
vm: &AxVM,
resources: &mut AxVMResources,
devices: &AxVmDevices,
owned_regions: &[GuestOwnedRegion],
) -> AxVmResult {
let emulated_resources = devices
.devices()
.flat_map(|device| device.resources().iter().cloned())
.collect::<Vec<Resource>>();
let address_layout = build_address_layout(
resources.config.address_space_policy(),
VM_ASPACE_BASE,
VM_ASPACE_SIZE,
resources.config.pass_through_devices(),
resources.config.pass_through_addresses(),
owned_regions,
&emulated_resources,
)?;
for mapping in address_layout.mappings() {
debug!(
"VM[{}] stage2 {:?}: [{:#x}, {:#x}) -> [{:#x}, {:#x}) {:?}",
vm.id(),
mapping.kind,
mapping.gpa.as_usize(),
mapping.gpa.as_usize() + mapping.size,
mapping.hpa.as_usize(),
mapping.hpa.as_usize() + mapping.size,
mapping.flags
);
resources
.address_space
.map_linear(mapping.gpa, mapping.hpa, mapping.size, mapping.flags)
.map_err(|error| AxVmError::from_addrspace("map guest address space", error))?;
}
resources.address_layout = Some(address_layout);
Ok(())
}
pub(crate) fn guest_owned_regions(resources: &AxVMResources) -> Vec<GuestOwnedRegion> {
let mut regions = resources
.memory_regions
.iter()
.map(|region| {
GuestOwnedRegion::new(region.gpa.as_usize(), region.size(), VmRegionKind::Memory)
})
.collect::<Vec<_>>();
regions.extend(
resources
.boot_description
.occupied_ranges()
.map(|(base, length)| {
GuestOwnedRegion::new(base, length, VmRegionKind::BootDescription)
}),
);
regions.extend(
resources
.config
.reserved_address_ranges()
.iter()
.map(|range| {
GuestOwnedRegion::new(range.base_gpa, range.length, VmRegionKind::Reserved)
}),
);
regions
}