mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
devices: Add acpi tables to fw_cfg
The acpi tables are created in the same place the acpi tables would be created for the regular bootflow, except here we add them to the fw_cfg device to be measured by the fw and then the fw will put the acpi tables into memory. Signed-off-by: Alex Orozco <alexorozco@google.com>
This commit is contained in:
@@ -192,6 +192,8 @@ pub fn create_dsdt_table(
|
||||
dsdt
|
||||
}
|
||||
|
||||
const FACP_DSDT_OFFSET: usize = 140;
|
||||
|
||||
fn create_facp_table(dsdt_offset: GuestAddress, device_manager: &Arc<Mutex<DeviceManager>>) -> Sdt {
|
||||
trace_scoped!("create_facp_table");
|
||||
|
||||
@@ -241,7 +243,7 @@ fn create_facp_table(dsdt_offset: GuestAddress, device_manager: &Arc<Mutex<Devic
|
||||
// FADT minor version
|
||||
facp.write(131, 3u8);
|
||||
// X_DSDT
|
||||
facp.write(140, dsdt_offset.0);
|
||||
facp.write(FACP_DSDT_OFFSET, dsdt_offset.0);
|
||||
// Hypervisor Vendor Identity
|
||||
facp.write_bytes(268, b"CLOUDHYP");
|
||||
|
||||
@@ -807,6 +809,65 @@ fn create_acpi_tables_internal(
|
||||
(rsdp, tables_bytes, xsdt_table_pointers)
|
||||
}
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
pub fn create_acpi_tables_for_fw_cfg(
|
||||
device_manager: &Arc<Mutex<DeviceManager>>,
|
||||
cpu_manager: &Arc<Mutex<CpuManager>>,
|
||||
memory_manager: &Arc<Mutex<MemoryManager>>,
|
||||
numa_nodes: &NumaNodes,
|
||||
tpm_enabled: bool,
|
||||
) -> Result<(), crate::vm::Error> {
|
||||
let dsdt_offset = GuestAddress(0);
|
||||
let (rsdp, table_bytes, xsdt_table_pointers) = create_acpi_tables_internal(
|
||||
dsdt_offset,
|
||||
device_manager,
|
||||
cpu_manager,
|
||||
memory_manager,
|
||||
numa_nodes,
|
||||
tpm_enabled,
|
||||
);
|
||||
let mut pointer_offsets: Vec<usize> = vec![];
|
||||
let mut checksums: Vec<(usize, usize)> = vec![];
|
||||
|
||||
let xsdt_addr = rsdp.xsdt_addr.get() as usize;
|
||||
let xsdt_checksum = (xsdt_addr, table_bytes.len() - xsdt_addr);
|
||||
|
||||
// create pointer offsets (use location of pointers in XSDT table)
|
||||
// XSDT doesn't have a pointer to DSDT so we use FACP's pointer to DSDT
|
||||
let facp_offset = xsdt_table_pointers[0] as usize;
|
||||
pointer_offsets.push(facp_offset + FACP_DSDT_OFFSET);
|
||||
let mut current_offset = xsdt_addr + 36;
|
||||
for _ in 0..xsdt_table_pointers.len() {
|
||||
pointer_offsets.push(current_offset);
|
||||
current_offset += 8;
|
||||
}
|
||||
|
||||
// create (offset, len) pairs for firmware to calculate
|
||||
// table checksums and verify ACPI tables
|
||||
let mut i = 0;
|
||||
while i < xsdt_table_pointers.len() - 1 {
|
||||
let current_table_offset = xsdt_table_pointers[i];
|
||||
let current_table_length = xsdt_table_pointers[i + 1] - current_table_offset;
|
||||
checksums.push((current_table_offset as usize, current_table_length as usize));
|
||||
i += 1;
|
||||
}
|
||||
checksums.push((
|
||||
xsdt_table_pointers[xsdt_table_pointers.len() - 1] as usize,
|
||||
0,
|
||||
));
|
||||
checksums.push(xsdt_checksum);
|
||||
|
||||
device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.fw_cfg()
|
||||
.expect("fw_cfg must be present")
|
||||
.lock()
|
||||
.unwrap()
|
||||
.add_acpi(rsdp, table_bytes, checksums, pointer_offsets)
|
||||
.map_err(crate::vm::Error::CreatingAcpiTables)
|
||||
}
|
||||
|
||||
pub fn create_acpi_tables(
|
||||
guest_mem: &GuestMemoryMmap,
|
||||
device_manager: &Arc<Mutex<DeviceManager>>,
|
||||
|
||||
@@ -355,6 +355,10 @@ pub enum Error {
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
#[error("Error creating e820 map")]
|
||||
CreatingE820Map(#[source] io::Error),
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
#[error("Error creating acpi tables")]
|
||||
CreatingAcpiTables(#[source] io::Error),
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
@@ -2361,10 +2365,21 @@ impl Vm {
|
||||
} else {
|
||||
VmState::Running
|
||||
};
|
||||
|
||||
current_state.valid_transition(new_state)?;
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
Self::populate_fw_cfg(&self.device_manager, &self.config)?;
|
||||
{
|
||||
Self::populate_fw_cfg(&self.device_manager, &self.config)?;
|
||||
let tpm_enabled = self.config.lock().unwrap().tpm.is_some();
|
||||
crate::acpi::create_acpi_tables_for_fw_cfg(
|
||||
&self.device_manager,
|
||||
&self.cpu_manager,
|
||||
&self.memory_manager,
|
||||
&self.numa_nodes,
|
||||
tpm_enabled,
|
||||
)?
|
||||
}
|
||||
|
||||
// Do earlier to parallelise with loading kernel
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
||||
Reference in New Issue
Block a user