mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-11-04 19:11:11 +00:00
arch: acpi: Set the upper device range based on RAM levels
After the 32-bit gap the memory is shared between the devices and the RAM. Ensure that the ACPI tables correctly indicate where the RAM ends and the device area starts by patching the precompiled tables. We get the following valid output now from the PCI bus probing (8GiB guest) [ 0.317757] pci_bus 0000:00: resource 4 [io 0x0000-0x0cf7 window] [ 0.319035] pci_bus 0000:00: resource 5 [io 0x0d00-0xffff window] [ 0.320215] pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff window] [ 0.321431] pci_bus 0000:00: resource 7 [mem 0xc0000000-0xfebfffff window] [ 0.322613] pci_bus 0000:00: resource 8 [mem 0x240000000-0xfffffffff window] Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
f9b0875a60
commit
f0360c92d9
@ -51,7 +51,11 @@ struct PCIRangeEntry {
|
||||
_reserved: u32,
|
||||
}
|
||||
|
||||
pub fn create_dsdt_table(serial_enabled: bool) -> SDT {
|
||||
pub fn create_dsdt_table(
|
||||
serial_enabled: bool,
|
||||
start_of_device_area: GuestAddress,
|
||||
end_of_device_area: GuestAddress,
|
||||
) -> SDT {
|
||||
/*
|
||||
The hex tables in this file are generated from the ASL below with:
|
||||
"iasl -tc <dsdt.asl>"
|
||||
@ -126,7 +130,7 @@ pub fn create_dsdt_table(serial_enabled: bool) -> SDT {
|
||||
})
|
||||
}
|
||||
*/
|
||||
let pci_dsdt_data = [
|
||||
let mut pci_dsdt_data = [
|
||||
0x5Bu8, 0x82, 0x36, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x50, 0x43, 0x49, 0x30, 0x08, 0x5F, 0x48,
|
||||
0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x08, 0x08, 0x5F, 0x43, 0x49, 0x44, 0x0C, 0x41, 0xD0,
|
||||
0x0A, 0x03, 0x08, 0x5F, 0x41, 0x44, 0x52, 0x00, 0x08, 0x5F, 0x53, 0x45, 0x47, 0x00, 0x08,
|
||||
@ -145,6 +149,13 @@ pub fn create_dsdt_table(serial_enabled: bool) -> SDT {
|
||||
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x79, 0x00,
|
||||
];
|
||||
|
||||
// Patch the Range Minimum/Range Maximum/Length for the the 64-bit device area
|
||||
pci_dsdt_data[200..208].copy_from_slice(&(start_of_device_area.0).to_le_bytes());
|
||||
pci_dsdt_data[208..216].copy_from_slice(&end_of_device_area.0.to_le_bytes());
|
||||
pci_dsdt_data[224..232].copy_from_slice(
|
||||
&(end_of_device_area.unchecked_offset_from(start_of_device_area)).to_le_bytes(),
|
||||
);
|
||||
|
||||
/*
|
||||
Device (_SB.COM1)
|
||||
{
|
||||
@ -194,13 +205,15 @@ pub fn create_acpi_tables(
|
||||
guest_mem: &GuestMemoryMmap,
|
||||
num_cpus: u8,
|
||||
serial_enabled: bool,
|
||||
start_of_device_area: GuestAddress,
|
||||
end_of_device_area: GuestAddress,
|
||||
) -> GuestAddress {
|
||||
// RSDP is at the EBDA
|
||||
let rsdp_offset = super::EBDA_START;
|
||||
let mut tables: Vec<u64> = Vec::new();
|
||||
|
||||
// DSDT
|
||||
let dsdt = create_dsdt_table(serial_enabled);
|
||||
let dsdt = create_dsdt_table(serial_enabled, start_of_device_area, end_of_device_area);
|
||||
let dsdt_offset = rsdp_offset.checked_add(RSDP::len() as u64).unwrap();
|
||||
guest_mem
|
||||
.write_slice(dsdt.as_slice(), dsdt_offset)
|
||||
|
@ -130,6 +130,7 @@ pub fn configure_system(
|
||||
num_cpus: u8,
|
||||
setup_hdr: Option<setup_header>,
|
||||
_serial_enabled: bool,
|
||||
_end_of_range: GuestAddress,
|
||||
) -> super::Result<()> {
|
||||
const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
|
||||
const KERNEL_HDR_MAGIC: u32 = 0x53726448;
|
||||
@ -187,7 +188,18 @@ pub fn configure_system(
|
||||
|
||||
#[cfg(feature = "acpi")]
|
||||
{
|
||||
let rsdp_addr = acpi::create_acpi_tables(guest_mem, num_cpus, _serial_enabled);
|
||||
let start_of_device_area = if mem_end < end_32bit_gap_start {
|
||||
first_addr_past_32bits
|
||||
} else {
|
||||
guest_mem.end_addr().unchecked_add(1)
|
||||
};
|
||||
let rsdp_addr = acpi::create_acpi_tables(
|
||||
guest_mem,
|
||||
num_cpus,
|
||||
_serial_enabled,
|
||||
start_of_device_area,
|
||||
_end_of_range,
|
||||
);
|
||||
params.0.acpi_rsdp_addr = rsdp_addr.0;
|
||||
}
|
||||
|
||||
@ -257,7 +269,15 @@ mod tests {
|
||||
fn test_system_configuration() {
|
||||
let no_vcpus = 4;
|
||||
let gm = GuestMemoryMmap::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();
|
||||
let config_err = configure_system(&gm, GuestAddress(0), 0, 1, None, false);
|
||||
let config_err = configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
0,
|
||||
1,
|
||||
None,
|
||||
false,
|
||||
GuestAddress((1 << 36) - 1),
|
||||
);
|
||||
assert!(config_err.is_err());
|
||||
assert_eq!(
|
||||
config_err.unwrap_err(),
|
||||
@ -275,7 +295,16 @@ mod tests {
|
||||
.map(|r| (r.0, r.1))
|
||||
.collect();
|
||||
let gm = GuestMemoryMmap::new(&ram_regions).unwrap();
|
||||
configure_system(&gm, GuestAddress(0), 0, no_vcpus, None, false).unwrap();
|
||||
configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
0,
|
||||
no_vcpus,
|
||||
None,
|
||||
false,
|
||||
GuestAddress((1 << 36) - 1),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
||||
let mem_size = 3328 << 20;
|
||||
@ -286,7 +315,16 @@ mod tests {
|
||||
.map(|r| (r.0, r.1))
|
||||
.collect();
|
||||
let gm = GuestMemoryMmap::new(&ram_regions).unwrap();
|
||||
configure_system(&gm, GuestAddress(0), 0, no_vcpus, None, false).unwrap();
|
||||
configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
0,
|
||||
no_vcpus,
|
||||
None,
|
||||
false,
|
||||
GuestAddress((1 << 36) - 1),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Now assigning some memory that falls after the 32bit memory hole.
|
||||
let mem_size = 3330 << 20;
|
||||
@ -297,7 +335,16 @@ mod tests {
|
||||
.map(|r| (r.0, r.1))
|
||||
.collect();
|
||||
let gm = GuestMemoryMmap::new(&ram_regions).unwrap();
|
||||
configure_system(&gm, GuestAddress(0), 0, no_vcpus, None, false).unwrap();
|
||||
configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
0,
|
||||
no_vcpus,
|
||||
None,
|
||||
false,
|
||||
GuestAddress((1 << 36) - 1),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -787,7 +787,7 @@ impl<'a> Vm<'a> {
|
||||
.map_err(|_| Error::CmdLine)?;
|
||||
|
||||
let vcpu_count = u8::from(&self.config.cpus);
|
||||
|
||||
let end_of_range = GuestAddress((1 << 36) - 1);
|
||||
match entry_addr.setup_header {
|
||||
Some(hdr) => {
|
||||
arch::configure_system(
|
||||
@ -797,6 +797,7 @@ impl<'a> Vm<'a> {
|
||||
vcpu_count,
|
||||
Some(hdr),
|
||||
self.config.serial.mode != ConsoleOutputMode::Off,
|
||||
end_of_range,
|
||||
)
|
||||
.map_err(|_| Error::CmdLine)?;
|
||||
|
||||
@ -816,6 +817,7 @@ impl<'a> Vm<'a> {
|
||||
vcpu_count,
|
||||
None,
|
||||
self.config.serial.mode != ConsoleOutputMode::Off,
|
||||
end_of_range,
|
||||
)
|
||||
.map_err(|_| Error::CmdLine)?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user