From 76e15a4240586bf796d670cc228a099a0fb9a874 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Mon, 25 Jan 2021 10:48:45 +0000 Subject: [PATCH] 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 --- vmm/src/acpi.rs | 28 ++++++++++----- vmm/src/cpu.rs | 72 +++++++++++++++++++++------------------ vmm/src/device_manager.rs | 46 ++++++++++++++----------- vmm/src/vm.rs | 11 ++++++ 4 files changed, 96 insertions(+), 61 deletions(-) diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index 8f2eb7cb8..7f0a12eba 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -6,12 +6,10 @@ use crate::cpu::CpuManager; use crate::device_manager::DeviceManager; use crate::memory_manager::MemoryManager; use crate::vm::NumaNodes; -use acpi_tables::{ - aml::Aml, - rsdp::RSDP, - sdt::{GenericAddress, SDT}, -}; -use arch::layout; +#[cfg(target_arch = "x86_64")] +use acpi_tables::sdt::GenericAddress; +use acpi_tables::{aml::Aml, rsdp::RSDP, sdt::SDT}; + use bitflags::bitflags; use std::sync::{Arc, Mutex}; use vm_memory::GuestRegionMmap; @@ -114,8 +112,16 @@ pub fn create_acpi_tables( memory_manager: &Arc>, numa_nodes: &NumaNodes, ) -> GuestAddress { + #[cfg(target_arch = "x86_64")] // 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 = Vec::new(); // DSDT @@ -130,6 +136,7 @@ pub fn create_acpi_tables( let mut facp = SDT::new(*b"FACP", 276, 6, *b"CLOUDH", *b"CHFACP ", 1); // PM_TMR_BLK I/O port + #[cfg(target_arch = "x86_64")] facp.write(76, 0xb008u32); // HW_REDUCED_ACPI, RESET_REG_SUP, TMR_VAL_EXT @@ -137,19 +144,24 @@ pub fn create_acpi_tables( facp.write(112, fadt_flags); // RESET_REG + #[cfg(target_arch = "x86_64")] facp.write(116, GenericAddress::io_port_address::(0x3c0)); // RESET_VALUE + #[cfg(target_arch = "x86_64")] facp.write(128, 1u8); facp.write(131, 3u8); // FADT minor version facp.write(140, dsdt_offset.0); // X_DSDT // X_PM_TMR_BLK + #[cfg(target_arch = "x86_64")] facp.write(208, GenericAddress::io_port_address::(0xb008)); // SLEEP_CONTROL_REG + #[cfg(target_arch = "x86_64")] facp.write(244, GenericAddress::io_port_address::(0x3c0)); // SLEEP_STATUS_REG + #[cfg(target_arch = "x86_64")] facp.write(256, GenericAddress::io_port_address::(0x3c0)); facp.write(268, b"CLOUDHYP"); // Hypervisor Vendor Identity @@ -177,7 +189,7 @@ pub fn create_acpi_tables( // 32-bit PCI enhanced configuration mechanism mcfg.append(PCIRangeEntry { - base_address: layout::PCI_MMCONFIG_START.0, + base_address: arch::layout::PCI_MMCONFIG_START.0, segment: 0, start: 0, end: 0, diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 31fbf721c..5a4e053d4 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -22,8 +22,6 @@ use crate::CPU_MANAGER_SNAPSHOT_ID; #[cfg(feature = "acpi")] use acpi_tables::{aml, aml::Aml, sdt::SDT}; use anyhow::anyhow; -#[cfg(feature = "acpi")] -use arch::layout; #[cfg(target_arch = "x86_64")] use arch::x86_64::SgxEpcSection; #[cfg(target_arch = "x86_64")] @@ -1031,40 +1029,48 @@ impl CpuManager { assert!(self.config.boot_vcpus <= self.config.max_vcpus); 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 { - let lapic = LocalAPIC { - r#type: 0, - length: 8, - processor_id: cpu, - apic_id: cpu, - flags: if cpu < self.config.boot_vcpus { - 1 << MADT_CPU_ENABLE_FLAG - } else { - 0 - }, - }; - madt.append(lapic); + for cpu in 0..self.config.max_vcpus { + let lapic = LocalAPIC { + r#type: 0, + length: 8, + processor_id: cpu, + apic_id: cpu, + flags: if cpu < self.config.boot_vcpus { + 1 << MADT_CPU_ENABLE_FLAG + } else { + 0 + }, + }; + 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 { - r#type: 1, - length: 12, - 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, - }); + #[cfg(target_arch = "aarch64")] + { + madt.update_checksum(); + } madt } diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index b54518441..95f9b5cb4 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1201,17 +1201,20 @@ impl DeviceManager { self.bus_devices .push(Arc::clone(&shutdown_device) as Arc>); - self.address_manager - .allocator - .lock() - .unwrap() - .allocate_io_addresses(Some(GuestAddress(0x3c0)), 0x8, None) - .ok_or(DeviceManagerError::AllocateIOPort)?; + #[cfg(target_arch = "x86_64")] + { + self.address_manager + .allocator + .lock() + .unwrap() + .allocate_io_addresses(Some(GuestAddress(0x3c0)), 0x8, None) + .ok_or(DeviceManagerError::AllocateIOPort)?; - self.address_manager - .io_bus - .insert(shutdown_device, 0x3c0, 0x4) - .map_err(DeviceManagerError::BusError)?; + self.address_manager + .io_bus + .insert(shutdown_device, 0x3c0, 0x4) + .map_err(DeviceManagerError::BusError)?; + } let ged_irq = self .address_manager @@ -1253,17 +1256,20 @@ impl DeviceManager { self.bus_devices .push(Arc::clone(&pm_timer_device) as Arc>); - self.address_manager - .allocator - .lock() - .unwrap() - .allocate_io_addresses(Some(GuestAddress(0xb008)), 0x4, None) - .ok_or(DeviceManagerError::AllocateIOPort)?; + #[cfg(target_arch = "x86_64")] + { + self.address_manager + .allocator + .lock() + .unwrap() + .allocate_io_addresses(Some(GuestAddress(0xb008)), 0x4, None) + .ok_or(DeviceManagerError::AllocateIOPort)?; - self.address_manager - .io_bus - .insert(pm_timer_device, 0xb008, 0x4) - .map_err(DeviceManagerError::BusError)?; + self.address_manager + .io_bus + .insert(pm_timer_device, 0xb008, 0x4) + .map_err(DeviceManagerError::BusError)?; + } Ok(Some(ged_device)) } diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index a2df724ba..1a0b89657 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -1033,6 +1033,17 @@ impl Vm { 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 // we can register the GIC device to the device manager. let gic_device = arch::configure_system(