mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-20 15:01:16 +00:00
arch: x86_64: Create MP table after SMBIOS table if space
In order to speed up the Linux boot (so as to avoid it having to scan a large number of pages) place the MP table directly after the SMBIOS table if there is sufficient room. The start address of the SMBIOS table is one of the three (and the largest) location that the MP table can also be located at. Before: [ 0.000399] x86/PAT: Configuration [0-7]: WB WC UC- UC WB WP UC- WT [ 0.014945] check: Scanning 1 areas for low memory corruption After: [ 0.000284] x86/PAT: Configuration [0-7]: WB WC UC- UC WB WP UC- WT [ 0.000421] found SMP MP-table at [mem 0x000f0090-0x000f009f] Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
7e130a65ba
commit
f762bc7573
@ -10,7 +10,6 @@ use std::sync::Arc;
|
|||||||
mod gdt;
|
mod gdt;
|
||||||
pub mod interrupts;
|
pub mod interrupts;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
#[cfg(not(feature = "acpi"))]
|
|
||||||
mod mptable;
|
mod mptable;
|
||||||
pub mod regs;
|
pub mod regs;
|
||||||
use crate::InitramfsConfig;
|
use crate::InitramfsConfig;
|
||||||
@ -141,7 +140,7 @@ unsafe impl ByteValued for BootParamsWrapper {}
|
|||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Invalid e820 setup params.
|
/// Invalid e820 setup params.
|
||||||
E820Configuration,
|
E820Configuration,
|
||||||
#[cfg(not(feature = "acpi"))]
|
|
||||||
/// Error writing MP table to memory.
|
/// Error writing MP table to memory.
|
||||||
MpTableSetup(mptable::Error),
|
MpTableSetup(mptable::Error),
|
||||||
|
|
||||||
@ -487,11 +486,12 @@ pub fn configure_system(
|
|||||||
boot_prot: BootProtocol,
|
boot_prot: BootProtocol,
|
||||||
sgx_epc_region: Option<SgxEpcRegion>,
|
sgx_epc_region: Option<SgxEpcRegion>,
|
||||||
) -> super::Result<()> {
|
) -> 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
|
// Place the MP table after the SMIOS table aligned to 16 bytes
|
||||||
#[cfg(not(feature = "acpi"))]
|
let offset = GuestAddress(layout::SMBIOS_START).unchecked_add(size);
|
||||||
mptable::setup_mptable(guest_mem, _num_cpus).map_err(Error::MpTableSetup)?;
|
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
|
// Check that the RAM is not smaller than the RSDP start address
|
||||||
if let Some(rsdp_addr) = rsdp_addr {
|
if let Some(rsdp_addr) = rsdp_addr {
|
||||||
|
@ -13,8 +13,10 @@ use std::slice;
|
|||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
|
|
||||||
use arch_gen::x86::mpspec;
|
use arch_gen::x86::mpspec;
|
||||||
use layout::{APIC_START, IOAPIC_START, MPTABLE_START};
|
use layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
|
||||||
use vm_memory::{Address, ByteValued, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
|
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
|
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
|
||||||
// trait (in this case `ByteValued`) where:
|
// 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`.
|
/// 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 {
|
if num_cpus as u32 > MAX_SUPPORTED_CPUS {
|
||||||
return Err(Error::TooManyCpus);
|
return Err(Error::TooManyCpus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to keep track of the next base pointer into the MP table.
|
// 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);
|
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 mut checksum: u8 = 0;
|
||||||
let ioapicid: u8 = num_cpus + 1;
|
let ioapicid: u8 = num_cpus + 1;
|
||||||
|
|
||||||
@ -280,6 +287,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use layout::MPTABLE_START;
|
||||||
use vm_memory::{GuestAddress, GuestUsize};
|
use vm_memory::{GuestAddress, GuestUsize};
|
||||||
|
|
||||||
fn table_entry_size(type_: u8) -> usize {
|
fn table_entry_size(type_: u8) -> usize {
|
||||||
@ -299,7 +307,7 @@ mod tests {
|
|||||||
let mem =
|
let mem =
|
||||||
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
|
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]
|
#[test]
|
||||||
@ -308,7 +316,7 @@ mod tests {
|
|||||||
let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus) - 1)])
|
let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus) - 1)])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert!(setup_mptable(&mem, num_cpus).is_err());
|
assert!(setup_mptable(MPTABLE_START, &mem, num_cpus).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -317,7 +325,7 @@ mod tests {
|
|||||||
let mem =
|
let mem =
|
||||||
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
|
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 mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
|
||||||
|
|
||||||
@ -333,7 +341,7 @@ mod tests {
|
|||||||
let mem =
|
let mem =
|
||||||
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
|
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 mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
|
||||||
let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize);
|
let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize);
|
||||||
@ -367,7 +375,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for i in 0..MAX_SUPPORTED_CPUS as u8 {
|
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 mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
|
||||||
let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize);
|
let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize);
|
||||||
@ -400,7 +408,7 @@ mod tests {
|
|||||||
let mem =
|
let mem =
|
||||||
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus as u8))]).unwrap();
|
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());
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ fn write_string(
|
|||||||
Ok(curptr)
|
Ok(curptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result<()> {
|
pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result<u64> {
|
||||||
let physptr = GuestAddress(SMBIOS_START)
|
let physptr = GuestAddress(SMBIOS_START)
|
||||||
.checked_add(mem::size_of::<Smbios30Entrypoint>() as u64)
|
.checked_add(mem::size_of::<Smbios30Entrypoint>() as u64)
|
||||||
.ok_or(Error::NotEnoughMemory)?;
|
.ok_or(Error::NotEnoughMemory)?;
|
||||||
@ -224,7 +224,7 @@ pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result<()> {
|
|||||||
.map_err(|_| Error::WriteSmbiosEp)?;
|
.map_err(|_| Error::WriteSmbiosEp)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(curptr.unchecked_offset_from(physptr))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Loading…
Reference in New Issue
Block a user