mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 17:44:10 +00:00
pstore: reserve ramoops region in system allocator
Remove the ramoops region from high_mmio when constructing the system allocator. This means the aarch64 code no longer needs to manually adjust high_mmio when determining the pci regions. BUG=b:181736020 TEST=Check arcvm pstore still works Change-Id: I81ca398a1984f0efb30c0a4d4b620bd50fe9df85 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3516667 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: David Stevens <stevensd@chromium.org>
This commit is contained in:
parent
00ab01e920
commit
e4db417895
11 changed files with 176 additions and 151 deletions
|
@ -407,26 +407,16 @@ impl arch::LinuxArch for AArch64 {
|
|||
cmdline.insert_str(¶m).map_err(Error::Cmdline)?;
|
||||
}
|
||||
|
||||
if let Some(ramoops_region) = ramoops_region {
|
||||
arch::pstore::add_ramoops_kernel_cmdline(&mut cmdline, &ramoops_region)
|
||||
.map_err(Error::Cmdline)?;
|
||||
}
|
||||
|
||||
let psci_version = vcpus[0].get_psci_version().map_err(Error::GetPsciVersion)?;
|
||||
|
||||
// Use the entire high MMIO except the ramoops region for PCI.
|
||||
// Note: This assumes that the ramoops region is the first thing allocated from the high
|
||||
// MMIO region.
|
||||
let high_mmio_alloc = system_allocator.mmio_allocator(MmioType::High);
|
||||
let high_mmio_base = *high_mmio_alloc.pool().start();
|
||||
let high_mmio_size = high_mmio_alloc.pool().end() - high_mmio_base + 1;
|
||||
let (pci_device_base, pci_device_size) = match &ramoops_region {
|
||||
Some(r) => {
|
||||
if r.address != high_mmio_base {
|
||||
return Err(Error::RamoopsAddress(r.address, high_mmio_base));
|
||||
}
|
||||
arch::pstore::add_ramoops_kernel_cmdline(&mut cmdline, r)
|
||||
.map_err(Error::Cmdline)?;
|
||||
let base = r.address + r.size as u64;
|
||||
(base, high_mmio_size - (base - high_mmio_base))
|
||||
}
|
||||
None => (high_mmio_base, high_mmio_size),
|
||||
};
|
||||
|
||||
let pci_cfg = fdt::PciConfigRegion {
|
||||
base: AARCH64_PCI_CFG_BASE,
|
||||
|
@ -443,9 +433,9 @@ impl arch::LinuxArch for AArch64 {
|
|||
},
|
||||
fdt::PciRange {
|
||||
space: fdt::PciAddressSpace::Memory64,
|
||||
bus_address: pci_device_base,
|
||||
cpu_physical_address: pci_device_base,
|
||||
size: pci_device_size,
|
||||
bus_address: high_mmio_base,
|
||||
cpu_physical_address: high_mmio_base,
|
||||
size: high_mmio_size,
|
||||
prefetchable: false,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -10,6 +10,7 @@ gdb = ["gdbstub_arch"]
|
|||
|
||||
[dependencies]
|
||||
acpi_tables = { path = "../acpi_tables" }
|
||||
anyhow = "*"
|
||||
base = { path = "../base" }
|
||||
devices = { path = "../devices" }
|
||||
gdbstub_arch = { version = "0.1.0", optional = true }
|
||||
|
|
|
@ -3,33 +3,14 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
use std::fs::OpenOptions;
|
||||
use std::io;
|
||||
|
||||
use crate::Pstore;
|
||||
use anyhow::{bail, Context, Result};
|
||||
use base::MemoryMappingBuilder;
|
||||
use hypervisor::Vm;
|
||||
use remain::sorted;
|
||||
use resources::SystemAllocator;
|
||||
use resources::{Alloc, MmioType};
|
||||
use thiserror::Error;
|
||||
use resources::MemRegion;
|
||||
use vm_memory::GuestAddress;
|
||||
|
||||
/// Error for pstore.
|
||||
#[sorted]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("failed to create pstore backend file: {0}")]
|
||||
IoError(io::Error),
|
||||
#[error("failed to get file mapped address: {0}")]
|
||||
MmapError(base::MmapError),
|
||||
#[error("failed to allocate pstore region: {0}")]
|
||||
ResourcesError(resources::Error),
|
||||
#[error("file to add pstore region to mmio: {0}")]
|
||||
SysUtilError(base::Error),
|
||||
}
|
||||
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
pub struct RamoopsRegion {
|
||||
pub address: u64,
|
||||
pub size: u32,
|
||||
|
@ -38,37 +19,37 @@ pub struct RamoopsRegion {
|
|||
/// Creates a mmio memory region for pstore.
|
||||
pub fn create_memory_region(
|
||||
vm: &mut impl Vm,
|
||||
resources: &mut SystemAllocator,
|
||||
region: &MemRegion,
|
||||
pstore: &Pstore,
|
||||
) -> Result<RamoopsRegion> {
|
||||
if region.size < pstore.size.into() {
|
||||
bail!("insufficient space for pstore {:?} {}", region, pstore.size);
|
||||
}
|
||||
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(&pstore.path)
|
||||
.map_err(Error::IoError)?;
|
||||
file.set_len(pstore.size as u64).map_err(Error::IoError)?;
|
||||
|
||||
let address = resources
|
||||
.mmio_allocator(MmioType::High)
|
||||
.allocate(pstore.size as u64, Alloc::Pstore, "pstore".to_owned())
|
||||
.map_err(Error::ResourcesError)?;
|
||||
.context("failed to open pstore")?;
|
||||
file.set_len(pstore.size as u64)
|
||||
.context("failed to set pstore length")?;
|
||||
|
||||
let memory_mapping = MemoryMappingBuilder::new(pstore.size as usize)
|
||||
.from_file(&file)
|
||||
.build()
|
||||
.map_err(Error::MmapError)?;
|
||||
.context("failed to mmap pstore")?;
|
||||
|
||||
vm.add_memory_region(
|
||||
GuestAddress(address),
|
||||
GuestAddress(region.base),
|
||||
Box::new(memory_mapping),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.map_err(Error::SysUtilError)?;
|
||||
.context("failed to add pstore region")?;
|
||||
|
||||
Ok(RamoopsRegion {
|
||||
address,
|
||||
address: region.base,
|
||||
size: pstore.size,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -926,22 +926,25 @@ mod tests {
|
|||
|
||||
let mmio_bus = Bus::new();
|
||||
let io_bus = Bus::new();
|
||||
let mut resources = SystemAllocator::new(SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0xc000,
|
||||
size: 0x4000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0,
|
||||
size: 2048,
|
||||
let mut resources = SystemAllocator::new(
|
||||
SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0xc000,
|
||||
size: 0x4000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0,
|
||||
size: 2048,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1_0000_0000,
|
||||
size: 0x2_0000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1_0000_0000,
|
||||
size: 0x2_0000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
})
|
||||
None,
|
||||
)
|
||||
.expect("failed to create SystemAllocator");
|
||||
|
||||
// setup an event and a resample event for irq line 1
|
||||
|
@ -1055,22 +1058,25 @@ mod tests {
|
|||
|
||||
let mmio_bus = Bus::new();
|
||||
let io_bus = Bus::new();
|
||||
let mut resources = SystemAllocator::new(SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0xc000,
|
||||
size: 0x4000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0,
|
||||
size: 2048,
|
||||
let mut resources = SystemAllocator::new(
|
||||
SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0xc000,
|
||||
size: 0x4000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0,
|
||||
size: 2048,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1_0000_0000,
|
||||
size: 0x2_0000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1_0000_0000,
|
||||
size: 0x2_0000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
})
|
||||
None,
|
||||
)
|
||||
.expect("failed to create SystemAllocator");
|
||||
|
||||
// setup an event and a resample event for irq line 1
|
||||
|
|
|
@ -455,22 +455,25 @@ mod tests {
|
|||
let mem = GuestMemory::new(&[(GuestAddress(0u64), 4 * 1024 * 1024)]).unwrap();
|
||||
let mut ac97_dev =
|
||||
Ac97Dev::new(mem, Ac97Backend::NULL, Box::new(MockShmStreamSource::new()));
|
||||
let mut allocator = SystemAllocator::new(SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0xc000,
|
||||
size: 0x4000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0x2000_0000,
|
||||
size: 0x1000_0000,
|
||||
let mut allocator = SystemAllocator::new(
|
||||
SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0xc000,
|
||||
size: 0x4000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0x2000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x3000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x3000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
})
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(ac97_dev.allocate_address(&mut allocator).is_ok());
|
||||
assert!(ac97_dev.allocate_io_bars(&mut allocator).is_ok());
|
||||
|
|
|
@ -192,22 +192,25 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn pvpanic_read_write() {
|
||||
let mut allocator = SystemAllocator::new(SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0x1000,
|
||||
size: 0x2000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0x2000_0000,
|
||||
size: 0x1000_0000,
|
||||
let mut allocator = SystemAllocator::new(
|
||||
SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0x1000,
|
||||
size: 0x2000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0x2000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1_0000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1_0000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
})
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (evt_rdtube, evt_wrtube) = Tube::pair().unwrap();
|
||||
|
|
|
@ -156,22 +156,25 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn address_allocation() {
|
||||
let mut allocator = SystemAllocator::new(SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0x1000,
|
||||
size: 0x2000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0x2000_0000,
|
||||
size: 0x1000_0000,
|
||||
let mut allocator = SystemAllocator::new(
|
||||
SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0x1000,
|
||||
size: 0x2000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0x2000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1_0000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1_0000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
})
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
let mut device = StubPciDevice::new(&CONFIG);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ pub enum MmioType {
|
|||
}
|
||||
|
||||
/// Region of memory.
|
||||
#[derive(Debug)]
|
||||
pub struct MemRegion {
|
||||
pub base: u64,
|
||||
pub size: u64,
|
||||
|
@ -55,6 +56,8 @@ pub struct SystemAllocator {
|
|||
mmio_address_spaces: [AddressAllocator; 2],
|
||||
mmio_platform_address_spaces: Option<AddressAllocator>,
|
||||
|
||||
reserved_region: Option<MemRegion>,
|
||||
|
||||
// Each bus number has a AddressAllocator
|
||||
pci_allocator: BTreeMap<u8, AddressAllocator>,
|
||||
irq_allocator: AddressAllocator,
|
||||
|
@ -73,9 +76,30 @@ impl SystemAllocator {
|
|||
/// Will return an error if `base` + `size` overflows u64 (or allowed
|
||||
/// maximum for the specific type), or if alignment isn't a power of two.
|
||||
///
|
||||
pub fn new(config: SystemAllocatorConfig) -> Result<Self> {
|
||||
/// If `reserve_region_size` is not None, then a region is reserved from
|
||||
/// the start of `config.high_mmio` before the mmio allocator is created.
|
||||
pub fn new(config: SystemAllocatorConfig, reserve_region_size: Option<u64>) -> Result<Self> {
|
||||
let page_size = pagesize() as u64;
|
||||
|
||||
let (high_mmio, reserved_region) = match reserve_region_size {
|
||||
Some(len) => {
|
||||
if len > config.high_mmio.size {
|
||||
return Err(Error::PoolSizeZero);
|
||||
}
|
||||
(
|
||||
MemRegion {
|
||||
base: config.high_mmio.base + len,
|
||||
size: config.high_mmio.size - len,
|
||||
},
|
||||
Some(MemRegion {
|
||||
base: config.high_mmio.base,
|
||||
size: len,
|
||||
}),
|
||||
)
|
||||
}
|
||||
None => (config.high_mmio, None),
|
||||
};
|
||||
|
||||
Ok(SystemAllocator {
|
||||
io_address_space: if let Some(io) = config.io {
|
||||
// TODO make sure we don't overlap with existing well known
|
||||
|
@ -100,7 +124,7 @@ impl SystemAllocator {
|
|||
)?,
|
||||
// MmioType::High
|
||||
AddressAllocator::new(
|
||||
to_range_inclusive(config.high_mmio.base, config.high_mmio.size)?,
|
||||
to_range_inclusive(high_mmio.base, high_mmio.size)?,
|
||||
Some(page_size),
|
||||
None,
|
||||
)?,
|
||||
|
@ -118,6 +142,8 @@ impl SystemAllocator {
|
|||
None
|
||||
},
|
||||
|
||||
reserved_region,
|
||||
|
||||
irq_allocator: AddressAllocator::new(
|
||||
RangeInclusive::new(config.first_irq as u64, 1023),
|
||||
Some(1),
|
||||
|
@ -247,6 +273,11 @@ impl SystemAllocator {
|
|||
AddressAllocatorSet::new(&mut self.mmio_address_spaces)
|
||||
}
|
||||
|
||||
/// Gets the reserved address space region.
|
||||
pub fn reserved_region(&self) -> Option<&MemRegion> {
|
||||
self.reserved_region.as_ref()
|
||||
}
|
||||
|
||||
/// Gets a unique anonymous allocation
|
||||
pub fn get_anon_alloc(&mut self) -> Alloc {
|
||||
self.next_anon_id += 1;
|
||||
|
@ -260,22 +291,25 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn example() {
|
||||
let mut a = SystemAllocator::new(SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0x1000,
|
||||
size: 0xf000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0x3000_0000,
|
||||
size: 0x1_0000,
|
||||
let mut a = SystemAllocator::new(
|
||||
SystemAllocatorConfig {
|
||||
io: Some(MemRegion {
|
||||
base: 0x1000,
|
||||
size: 0xf000,
|
||||
}),
|
||||
low_mmio: MemRegion {
|
||||
base: 0x3000_0000,
|
||||
size: 0x1_0000,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
},
|
||||
high_mmio: MemRegion {
|
||||
base: 0x1000_0000,
|
||||
size: 0x1000_0000,
|
||||
},
|
||||
platform_mmio: None,
|
||||
first_irq: 5,
|
||||
})
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(a.allocate_irq(), Some(5));
|
||||
|
|
|
@ -1156,14 +1156,20 @@ where
|
|||
let reset_evt = Event::new().context("failed to create event")?;
|
||||
let crash_evt = Event::new().context("failed to create event")?;
|
||||
let (panic_rdtube, panic_wrtube) = Tube::pair().context("failed to create tube")?;
|
||||
let mut sys_allocator = SystemAllocator::new(Arch::get_system_allocator_config(&vm))
|
||||
.context("failed to create system allocator")?;
|
||||
|
||||
// Allocate the ramoops region first. AArch64::build_vm() assumes this.
|
||||
let pstore_size = components.pstore.as_ref().map(|pstore| pstore.size as u64);
|
||||
let mut sys_allocator =
|
||||
SystemAllocator::new(Arch::get_system_allocator_config(&vm), pstore_size)
|
||||
.context("failed to create system allocator")?;
|
||||
|
||||
let ramoops_region = match &components.pstore {
|
||||
Some(pstore) => Some(
|
||||
arch::pstore::create_memory_region(&mut vm, &mut sys_allocator, pstore)
|
||||
.context("failed to allocate pstore region")?,
|
||||
arch::pstore::create_memory_region(
|
||||
&mut vm,
|
||||
sys_allocator.reserved_region().unwrap(),
|
||||
pstore,
|
||||
)
|
||||
.context("failed to allocate pstore region")?,
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
|
|
|
@ -137,8 +137,6 @@ pub enum Error {
|
|||
LoadKernel(kernel_loader::Error),
|
||||
#[error("error translating address: Page not present")]
|
||||
PageNotPresent,
|
||||
#[error("failed to allocate pstore region: {0}")]
|
||||
Pstore(arch::pstore::Error),
|
||||
#[error("error reading guest memory {0}")]
|
||||
ReadingGuestMemory(vm_memory::GuestMemoryError),
|
||||
#[error("error reading CPU registers {0}")]
|
||||
|
|
|
@ -103,7 +103,7 @@ where
|
|||
let guest_mem = GuestMemory::new(&arch_mem_regions).unwrap();
|
||||
|
||||
let (hyp, mut vm) = create_vm(guest_mem.clone());
|
||||
let mut resources = SystemAllocator::new(X8664arch::get_system_allocator_config(&vm))
|
||||
let mut resources = SystemAllocator::new(X8664arch::get_system_allocator_config(&vm), None)
|
||||
.expect("failed to create system allocator");
|
||||
let (irqchip_tube, device_tube) = Tube::pair().expect("failed to create irq tube");
|
||||
|
||||
|
|
Loading…
Reference in a new issue