diff options
Diffstat (limited to 'x86_64')
-rw-r--r-- | x86_64/src/acpi.rs | 61 | ||||
-rw-r--r-- | x86_64/src/lib.rs | 17 | ||||
-rw-r--r-- | x86_64/src/mptable.rs | 3 |
3 files changed, 50 insertions, 31 deletions
diff --git a/x86_64/src/acpi.rs b/x86_64/src/acpi.rs index c1d92ee..e6fc15a 100644 --- a/x86_64/src/acpi.rs +++ b/x86_64/src/acpi.rs @@ -8,6 +8,8 @@ use sys_util::{GuestAddress, GuestMemory}; pub struct ACPIDevResource { pub amls: Vec<u8>, pub pm_iobase: u64, + /// Additional system descriptor tables. + pub sdts: Vec<SDT>, } #[repr(C)] @@ -102,17 +104,35 @@ pub fn create_acpi_tables( num_cpus: u8, sci_irq: u32, acpi_dev_resource: ACPIDevResource, -) -> GuestAddress { +) -> Option<GuestAddress> { // RSDP is at the HI RSDP WINDOW let rsdp_offset = GuestAddress(super::ACPI_HI_RSDP_WINDOW_BASE); + let mut offset = rsdp_offset.checked_add(RSDP::len() as u64)?; let mut tables: Vec<u64> = Vec::new(); + let mut dsdt_offset: Option<GuestAddress> = None; + + // User supplied System Description Tables, e.g. SSDT. + for sdt in acpi_dev_resource.sdts.iter() { + guest_mem.write_at_addr(sdt.as_slice(), offset).ok()?; + if sdt.is_signature(b"DSDT") { + dsdt_offset = Some(offset); + } else { + tables.push(offset.0); + } + offset = offset.checked_add(sdt.len() as u64)?; + } // DSDT - let dsdt = create_dsdt_table(acpi_dev_resource.amls); - let dsdt_offset = rsdp_offset.checked_add(RSDP::len() as u64).unwrap(); - guest_mem - .write_at_addr(dsdt.as_slice(), dsdt_offset) - .expect("Error writing DSDT table"); + let dsdt_offset = match dsdt_offset { + Some(dsdt_offset) => dsdt_offset, + None => { + let dsdt_offset = offset; + let dsdt = create_dsdt_table(acpi_dev_resource.amls); + guest_mem.write_at_addr(dsdt.as_slice(), offset).ok()?; + offset = offset.checked_add(dsdt.len() as u64)?; + dsdt_offset + } + }; // FACP aka FADT // Revision 6 of the ACPI FADT table is 276 bytes long @@ -160,11 +180,9 @@ pub fn create_acpi_tables( facp.write(FADT_FIELD_HYPERVISOR_ID, *b"CROSVM"); // Hypervisor Vendor Identity - let facp_offset = dsdt_offset.checked_add(dsdt.len() as u64).unwrap(); - guest_mem - .write_at_addr(facp.as_slice(), facp_offset) - .expect("Error writing FACP table"); - tables.push(facp_offset.0); + guest_mem.write_at_addr(facp.as_slice(), offset).ok()?; + tables.push(offset.0); + offset = offset.checked_add(facp.len() as u64)?; // MADT let mut madt = SDT::new( @@ -198,11 +216,9 @@ pub fn create_acpi_tables( ..Default::default() }); - let madt_offset = facp_offset.checked_add(facp.len() as u64).unwrap(); - guest_mem - .write_at_addr(madt.as_slice(), madt_offset) - .expect("Error writing MADT table"); - tables.push(madt_offset.0); + guest_mem.write_at_addr(madt.as_slice(), offset).ok()?; + tables.push(offset.0); + offset = offset.checked_add(madt.len() as u64)?; // XSDT let mut xsdt = SDT::new( @@ -217,16 +233,11 @@ pub fn create_acpi_tables( xsdt.append(table); } - let xsdt_offset = madt_offset.checked_add(madt.len() as u64).unwrap(); - guest_mem - .write_at_addr(xsdt.as_slice(), xsdt_offset) - .expect("Error writing XSDT table"); + guest_mem.write_at_addr(xsdt.as_slice(), offset).ok()?; // RSDP - let rsdp = RSDP::new(*b"CROSVM", xsdt_offset.0); - guest_mem - .write_at_addr(rsdp.as_slice(), rsdp_offset) - .expect("Error writing RSDP"); + let rsdp = RSDP::new(*b"CROSVM", offset.0); + guest_mem.write_at_addr(rsdp.as_slice(), rsdp_offset).ok()?; - rsdp_offset + Some(rsdp_offset) } diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs index b4c4aa7..9714638 100644 --- a/x86_64/src/lib.rs +++ b/x86_64/src/lib.rs @@ -55,6 +55,7 @@ use std::sync::Arc; use crate::bootparam::boot_params; use acpi_tables::aml::Aml; +use acpi_tables::sdt::SDT; use arch::{ get_serial_cmdline, GetSerialCmdlineError, RunnableLinuxVm, SerialHardware, SerialParameters, VmComponents, VmImage, @@ -283,9 +284,11 @@ fn configure_system( .write_obj_at_addr(params, zero_page_addr) .map_err(|_| Error::ZeroPageSetup)?; - let rsdp_addr = - acpi::create_acpi_tables(guest_mem, num_cpus, X86_64_SCI_IRQ, acpi_dev_resource); - params.acpi_rsdp_addr = rsdp_addr.0; + if let Some(rsdp_addr) = + acpi::create_acpi_tables(guest_mem, num_cpus, X86_64_SCI_IRQ, acpi_dev_resource) + { + params.acpi_rsdp_addr = rsdp_addr.0; + } Ok(()) } @@ -442,6 +445,7 @@ impl arch::LinuxArch for X8664arch { &mut io_bus, &mut resources, suspend_evt.try_clone().map_err(Error::CloneEventFd)?, + components.acpi_sdts, )?; let ramoops_region = match components.pstore { @@ -853,6 +857,7 @@ impl X8664arch { io_bus: &mut devices::Bus, resources: &mut SystemAllocator, suspend_evt: EventFd, + sdts: Vec<SDT>, ) -> Result<acpi::ACPIDevResource> { // The AML data for the acpi devices let mut amls = Vec::new(); @@ -883,7 +888,11 @@ impl X8664arch { .unwrap(); io_bus.notify_on_resume(pm); - Ok(acpi::ACPIDevResource { amls, pm_iobase }) + Ok(acpi::ACPIDevResource { + amls, + pm_iobase, + sdts, + }) } /// Sets up the serial devices for this platform. Returns the serial port number and serial diff --git a/x86_64/src/mptable.rs b/x86_64/src/mptable.rs index 218f561..de489f2 100644 --- a/x86_64/src/mptable.rs +++ b/x86_64/src/mptable.rs @@ -10,7 +10,6 @@ use std::slice; use libc::c_char; -use data_model::VolatileMemory; use devices::{PciAddress, PciInterruptPin}; use sys_util::{GuestAddress, GuestMemory}; @@ -140,7 +139,7 @@ pub fn setup_mptable( return Err(Error::AddressOverflow); } - mem.get_slice(base_mp.0, mp_size as u64) + mem.get_slice_at_addr(base_mp, mp_size) .map_err(|_| Error::Clear)? .write_bytes(0); |