diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index 168420e35..8e862579a 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -10,7 +10,6 @@ use std::sync::Arc; mod gdt; pub mod interrupts; pub mod layout; -#[cfg(not(feature = "acpi"))] mod mptable; pub mod regs; use crate::InitramfsConfig; @@ -141,7 +140,7 @@ unsafe impl ByteValued for BootParamsWrapper {} pub enum Error { /// Invalid e820 setup params. E820Configuration, - #[cfg(not(feature = "acpi"))] + /// Error writing MP table to memory. MpTableSetup(mptable::Error), @@ -487,11 +486,12 @@ pub fn configure_system( boot_prot: BootProtocol, sgx_epc_region: Option, ) -> super::Result<()> { - smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?; + let size = smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?; - // Note that this puts the mptable at the last 1k of Linux's 640k base RAM - #[cfg(not(feature = "acpi"))] - mptable::setup_mptable(guest_mem, _num_cpus).map_err(Error::MpTableSetup)?; + // Place the MP table after the SMIOS table aligned to 16 bytes + let offset = GuestAddress(layout::SMBIOS_START).unchecked_add(size); + let offset = GuestAddress((offset.0 + 16) & !0xf); + mptable::setup_mptable(offset, guest_mem, _num_cpus).map_err(Error::MpTableSetup)?; // Check that the RAM is not smaller than the RSDP start address if let Some(rsdp_addr) = rsdp_addr { diff --git a/arch/src/x86_64/mptable.rs b/arch/src/x86_64/mptable.rs index aaa44109c..289a0c121 100644 --- a/arch/src/x86_64/mptable.rs +++ b/arch/src/x86_64/mptable.rs @@ -13,8 +13,10 @@ use std::slice; use libc::c_char; use arch_gen::x86::mpspec; -use layout::{APIC_START, IOAPIC_START, MPTABLE_START}; -use vm_memory::{Address, ByteValued, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap}; +use layout::{APIC_START, HIGH_RAM_START, IOAPIC_START}; +use vm_memory::{ + Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap, +}; // This is a workaround to the Rust enforcement specifying that any implementation of a foreign // trait (in this case `ByteValued`) where: @@ -121,16 +123,21 @@ fn compute_mp_size(num_cpus: u8) -> usize { } /// Performs setup of the MP table for the given `num_cpus`. -pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> { +pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> { if num_cpus as u32 > MAX_SUPPORTED_CPUS { return Err(Error::TooManyCpus); } // Used to keep track of the next base pointer into the MP table. - let mut base_mp = MPTABLE_START; + let mut base_mp = offset; let mp_size = compute_mp_size(num_cpus); + if offset.unchecked_add(mp_size as u64) >= HIGH_RAM_START { + warn!("Skipping mptable creation due to insufficient space"); + return Ok(()); + } + let mut checksum: u8 = 0; let ioapicid: u8 = num_cpus + 1; @@ -280,6 +287,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> { #[cfg(test)] mod tests { use super::*; + use layout::MPTABLE_START; use vm_memory::{GuestAddress, GuestUsize}; fn table_entry_size(type_: u8) -> usize { @@ -299,7 +307,7 @@ mod tests { let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap(); - setup_mptable(&mem, num_cpus).unwrap(); + setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap(); } #[test] @@ -308,7 +316,7 @@ mod tests { let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus) - 1)]) .unwrap(); - assert!(setup_mptable(&mem, num_cpus).is_err()); + assert!(setup_mptable(MPTABLE_START, &mem, num_cpus).is_err()); } #[test] @@ -317,7 +325,7 @@ mod tests { let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap(); - setup_mptable(&mem, num_cpus).unwrap(); + setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap(); let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap(); @@ -333,7 +341,7 @@ mod tests { let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap(); - setup_mptable(&mem, num_cpus).unwrap(); + setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap(); let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap(); let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize); @@ -367,7 +375,7 @@ mod tests { .unwrap(); for i in 0..MAX_SUPPORTED_CPUS as u8 { - setup_mptable(&mem, i).unwrap(); + setup_mptable(MPTABLE_START, &mem, i).unwrap(); let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap(); let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize); @@ -400,7 +408,7 @@ mod tests { let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus as u8))]).unwrap(); - let result = setup_mptable(&mem, cpus as u8); + let result = setup_mptable(MPTABLE_START, &mem, cpus as u8); assert!(result.is_err()); } } diff --git a/arch/src/x86_64/smbios.rs b/arch/src/x86_64/smbios.rs index c18dba95d..ff5dd13aa 100644 --- a/arch/src/x86_64/smbios.rs +++ b/arch/src/x86_64/smbios.rs @@ -161,7 +161,7 @@ fn write_string( Ok(curptr) } -pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result<()> { +pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result { let physptr = GuestAddress(SMBIOS_START) .checked_add(mem::size_of::() as u64) .ok_or(Error::NotEnoughMemory)?; @@ -224,7 +224,7 @@ pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result<()> { .map_err(|_| Error::WriteSmbiosEp)?; } - Ok(()) + Ok(curptr.unchecked_offset_from(physptr)) } #[cfg(test)]