vmm: acpi: Support compiling ACPI code on aarch64

This skeleton commit brings in the support for compiling aarch64 with
the "acpi" feature ready to the ACPI enabling. It builds on the work to
move the ACPI hotplug devices from I/O ports to MMIO and conditionalises
any code that is x86_64 only (i.e. because it uses an I/O port.)

Filling in the aarch64 specific details in tables such as the MADT it
out of the scope.

See: #2178

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2021-01-25 10:48:45 +00:00 committed by Michael
parent 7659055eec
commit 76e15a4240
4 changed files with 96 additions and 61 deletions

View File

@ -6,12 +6,10 @@ use crate::cpu::CpuManager;
use crate::device_manager::DeviceManager; use crate::device_manager::DeviceManager;
use crate::memory_manager::MemoryManager; use crate::memory_manager::MemoryManager;
use crate::vm::NumaNodes; use crate::vm::NumaNodes;
use acpi_tables::{ #[cfg(target_arch = "x86_64")]
aml::Aml, use acpi_tables::sdt::GenericAddress;
rsdp::RSDP, use acpi_tables::{aml::Aml, rsdp::RSDP, sdt::SDT};
sdt::{GenericAddress, SDT},
};
use arch::layout;
use bitflags::bitflags; use bitflags::bitflags;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use vm_memory::GuestRegionMmap; use vm_memory::GuestRegionMmap;
@ -114,8 +112,16 @@ pub fn create_acpi_tables(
memory_manager: &Arc<Mutex<MemoryManager>>, memory_manager: &Arc<Mutex<MemoryManager>>,
numa_nodes: &NumaNodes, numa_nodes: &NumaNodes,
) -> GuestAddress { ) -> GuestAddress {
#[cfg(target_arch = "x86_64")]
// RSDP is at the EBDA // RSDP is at the EBDA
let rsdp_offset = layout::RSDP_POINTER; let rsdp_offset = arch::layout::RSDP_POINTER;
#[cfg(target_arch = "aarch64")]
// TODO: For aarch64 place the ACPI tables in the last MiB of guest RAM
let rsdp_offset = {
use vm_memory::GuestMemory;
guest_mem.last_addr().checked_sub(1 << 20).unwrap()
};
let mut tables: Vec<u64> = Vec::new(); let mut tables: Vec<u64> = Vec::new();
// DSDT // DSDT
@ -130,6 +136,7 @@ pub fn create_acpi_tables(
let mut facp = SDT::new(*b"FACP", 276, 6, *b"CLOUDH", *b"CHFACP ", 1); let mut facp = SDT::new(*b"FACP", 276, 6, *b"CLOUDH", *b"CHFACP ", 1);
// PM_TMR_BLK I/O port // PM_TMR_BLK I/O port
#[cfg(target_arch = "x86_64")]
facp.write(76, 0xb008u32); facp.write(76, 0xb008u32);
// HW_REDUCED_ACPI, RESET_REG_SUP, TMR_VAL_EXT // HW_REDUCED_ACPI, RESET_REG_SUP, TMR_VAL_EXT
@ -137,19 +144,24 @@ pub fn create_acpi_tables(
facp.write(112, fadt_flags); facp.write(112, fadt_flags);
// RESET_REG // RESET_REG
#[cfg(target_arch = "x86_64")]
facp.write(116, GenericAddress::io_port_address::<u8>(0x3c0)); facp.write(116, GenericAddress::io_port_address::<u8>(0x3c0));
// RESET_VALUE // RESET_VALUE
#[cfg(target_arch = "x86_64")]
facp.write(128, 1u8); facp.write(128, 1u8);
facp.write(131, 3u8); // FADT minor version facp.write(131, 3u8); // FADT minor version
facp.write(140, dsdt_offset.0); // X_DSDT facp.write(140, dsdt_offset.0); // X_DSDT
// X_PM_TMR_BLK // X_PM_TMR_BLK
#[cfg(target_arch = "x86_64")]
facp.write(208, GenericAddress::io_port_address::<u32>(0xb008)); facp.write(208, GenericAddress::io_port_address::<u32>(0xb008));
// SLEEP_CONTROL_REG // SLEEP_CONTROL_REG
#[cfg(target_arch = "x86_64")]
facp.write(244, GenericAddress::io_port_address::<u8>(0x3c0)); facp.write(244, GenericAddress::io_port_address::<u8>(0x3c0));
// SLEEP_STATUS_REG // SLEEP_STATUS_REG
#[cfg(target_arch = "x86_64")]
facp.write(256, GenericAddress::io_port_address::<u8>(0x3c0)); facp.write(256, GenericAddress::io_port_address::<u8>(0x3c0));
facp.write(268, b"CLOUDHYP"); // Hypervisor Vendor Identity facp.write(268, b"CLOUDHYP"); // Hypervisor Vendor Identity
@ -177,7 +189,7 @@ pub fn create_acpi_tables(
// 32-bit PCI enhanced configuration mechanism // 32-bit PCI enhanced configuration mechanism
mcfg.append(PCIRangeEntry { mcfg.append(PCIRangeEntry {
base_address: layout::PCI_MMCONFIG_START.0, base_address: arch::layout::PCI_MMCONFIG_START.0,
segment: 0, segment: 0,
start: 0, start: 0,
end: 0, end: 0,

View File

@ -22,8 +22,6 @@ use crate::CPU_MANAGER_SNAPSHOT_ID;
#[cfg(feature = "acpi")] #[cfg(feature = "acpi")]
use acpi_tables::{aml, aml::Aml, sdt::SDT}; use acpi_tables::{aml, aml::Aml, sdt::SDT};
use anyhow::anyhow; use anyhow::anyhow;
#[cfg(feature = "acpi")]
use arch::layout;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use arch::x86_64::SgxEpcSection; use arch::x86_64::SgxEpcSection;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
@ -1031,40 +1029,48 @@ impl CpuManager {
assert!(self.config.boot_vcpus <= self.config.max_vcpus); assert!(self.config.boot_vcpus <= self.config.max_vcpus);
let mut madt = SDT::new(*b"APIC", 44, 5, *b"CLOUDH", *b"CHMADT ", 1); let mut madt = SDT::new(*b"APIC", 44, 5, *b"CLOUDH", *b"CHMADT ", 1);
madt.write(36, layout::APIC_START); #[cfg(target_arch = "x86_64")]
{
madt.write(36, arch::layout::APIC_START);
for cpu in 0..self.config.max_vcpus { for cpu in 0..self.config.max_vcpus {
let lapic = LocalAPIC { let lapic = LocalAPIC {
r#type: 0, r#type: 0,
length: 8, length: 8,
processor_id: cpu, processor_id: cpu,
apic_id: cpu, apic_id: cpu,
flags: if cpu < self.config.boot_vcpus { flags: if cpu < self.config.boot_vcpus {
1 << MADT_CPU_ENABLE_FLAG 1 << MADT_CPU_ENABLE_FLAG
} else { } else {
0 0
}, },
}; };
madt.append(lapic); madt.append(lapic);
}
madt.append(IOAPIC {
r#type: 1,
length: 12,
ioapic_id: 0,
apic_address: arch::layout::IOAPIC_START.0 as u32,
gsi_base: 0,
..Default::default()
});
madt.append(InterruptSourceOverride {
r#type: 2,
length: 10,
bus: 0,
source: 4,
gsi: 4,
flags: 0,
});
} }
madt.append(IOAPIC { #[cfg(target_arch = "aarch64")]
r#type: 1, {
length: 12, madt.update_checksum();
ioapic_id: 0, }
apic_address: layout::IOAPIC_START.0 as u32,
gsi_base: 0,
..Default::default()
});
madt.append(InterruptSourceOverride {
r#type: 2,
length: 10,
bus: 0,
source: 4,
gsi: 4,
flags: 0,
});
madt madt
} }

View File

@ -1201,17 +1201,20 @@ impl DeviceManager {
self.bus_devices self.bus_devices
.push(Arc::clone(&shutdown_device) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&shutdown_device) as Arc<Mutex<dyn BusDevice>>);
self.address_manager #[cfg(target_arch = "x86_64")]
.allocator {
.lock() self.address_manager
.unwrap() .allocator
.allocate_io_addresses(Some(GuestAddress(0x3c0)), 0x8, None) .lock()
.ok_or(DeviceManagerError::AllocateIOPort)?; .unwrap()
.allocate_io_addresses(Some(GuestAddress(0x3c0)), 0x8, None)
.ok_or(DeviceManagerError::AllocateIOPort)?;
self.address_manager self.address_manager
.io_bus .io_bus
.insert(shutdown_device, 0x3c0, 0x4) .insert(shutdown_device, 0x3c0, 0x4)
.map_err(DeviceManagerError::BusError)?; .map_err(DeviceManagerError::BusError)?;
}
let ged_irq = self let ged_irq = self
.address_manager .address_manager
@ -1253,17 +1256,20 @@ impl DeviceManager {
self.bus_devices self.bus_devices
.push(Arc::clone(&pm_timer_device) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&pm_timer_device) as Arc<Mutex<dyn BusDevice>>);
self.address_manager #[cfg(target_arch = "x86_64")]
.allocator {
.lock() self.address_manager
.unwrap() .allocator
.allocate_io_addresses(Some(GuestAddress(0xb008)), 0x4, None) .lock()
.ok_or(DeviceManagerError::AllocateIOPort)?; .unwrap()
.allocate_io_addresses(Some(GuestAddress(0xb008)), 0x4, None)
.ok_or(DeviceManagerError::AllocateIOPort)?;
self.address_manager self.address_manager
.io_bus .io_bus
.insert(pm_timer_device, 0xb008, 0x4) .insert(pm_timer_device, 0xb008, 0x4)
.map_err(DeviceManagerError::BusError)?; .map_err(DeviceManagerError::BusError)?;
}
Ok(Some(ged_device)) Ok(Some(ged_device))
} }

View File

@ -1033,6 +1033,17 @@ impl Vm {
let pci_space = (pci_space_start.0, pci_space_size); let pci_space = (pci_space_start.0, pci_space_size);
#[cfg(feature = "acpi")]
{
let _ = crate::acpi::create_acpi_tables(
&mem,
&self.device_manager,
&self.cpu_manager,
&self.memory_manager,
&self.numa_nodes,
);
}
// Call `configure_system` and pass the GIC devices out, so that // Call `configure_system` and pass the GIC devices out, so that
// we can register the GIC device to the device manager. // we can register the GIC device to the device manager.
let gic_device = arch::configure_system( let gic_device = arch::configure_system(