acpi: Refactor create_acpi_tables()

Split the code of create_acpi_tables() into multiple functions for
easy extension in future.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2021-05-18 20:43:53 +08:00 committed by Sebastien Boeuf
parent 5ae04349da
commit 01acea3102

View File

@ -105,74 +105,44 @@ pub fn create_dsdt_table(
dsdt
}
pub fn create_acpi_tables(
guest_mem: &GuestMemoryMmap,
device_manager: &Arc<Mutex<DeviceManager>>,
cpu_manager: &Arc<Mutex<CpuManager>>,
memory_manager: &Arc<Mutex<MemoryManager>>,
numa_nodes: &NumaNodes,
) -> GuestAddress {
let rsdp_offset = arch::layout::RSDP_POINTER;
let mut tables: Vec<u64> = Vec::new();
// DSDT
let dsdt = create_dsdt_table(device_manager, cpu_manager, memory_manager);
let dsdt_offset = rsdp_offset.checked_add(Rsdp::len() as u64).unwrap();
guest_mem
.write_slice(dsdt.as_slice(), dsdt_offset)
.expect("Error writing DSDT table");
// FACP aka FADT
fn create_facp_table(dsdt_offset: GuestAddress) -> Sdt {
// Revision 6 of the ACPI FADT table is 276 bytes long
let mut facp = Sdt::new(*b"FACP", 276, 6, *b"CLOUDH", *b"CHFACP ", 1);
// PM_TMR_BLK I/O port
// x86_64 specific fields
#[cfg(target_arch = "x86_64")]
{
// PM_TMR_BLK I/O port
facp.write(76, 0xb008u32);
// RESET_REG
facp.write(116, GenericAddress::io_port_address::<u8>(0x3c0));
// RESET_VALUE
facp.write(128, 1u8);
// X_PM_TMR_BLK
facp.write(208, GenericAddress::io_port_address::<u32>(0xb008));
// SLEEP_CONTROL_REG
facp.write(244, GenericAddress::io_port_address::<u8>(0x3c0));
// SLEEP_STATUS_REG
facp.write(256, GenericAddress::io_port_address::<u8>(0x3c0));
}
// Architecture common fields
// HW_REDUCED_ACPI, RESET_REG_SUP, TMR_VAL_EXT
let fadt_flags: u32 = 1 << 20 | 1 << 10 | 1 << 8;
facp.write(112, fadt_flags);
// RESET_REG
#[cfg(target_arch = "x86_64")]
facp.write(116, GenericAddress::io_port_address::<u8>(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::<u32>(0xb008));
// SLEEP_CONTROL_REG
#[cfg(target_arch = "x86_64")]
facp.write(244, GenericAddress::io_port_address::<u8>(0x3c0));
// SLEEP_STATUS_REG
#[cfg(target_arch = "x86_64")]
facp.write(256, GenericAddress::io_port_address::<u8>(0x3c0));
facp.write(268, b"CLOUDHYP"); // Hypervisor Vendor Identity
// FADT minor version
facp.write(131, 3u8);
// X_DSDT
facp.write(140, dsdt_offset.0);
// Hypervisor Vendor Identity
facp.write(268, b"CLOUDHYP");
facp.update_checksum();
let facp_offset = dsdt_offset.checked_add(dsdt.len() as u64).unwrap();
guest_mem
.write_slice(facp.as_slice(), facp_offset)
.expect("Error writing FACP table");
tables.push(facp_offset.0);
// MADT
let madt = cpu_manager.lock().unwrap().create_madt();
let madt_offset = facp_offset.checked_add(facp.len() as u64).unwrap();
guest_mem
.write_slice(madt.as_slice(), madt_offset)
.expect("Error writing MADT table");
tables.push(madt_offset.0);
facp
}
// MCFG
fn create_mcfg_table() -> Sdt {
let mut mcfg = Sdt::new(*b"MCFG", 36, 1, *b"CLOUDH", *b"CHMCFG ", 1);
// MCFG reserved 8 bytes
@ -186,19 +156,10 @@ pub fn create_acpi_tables(
end: 0,
..Default::default()
});
mcfg
}
let mcfg_offset = madt_offset.checked_add(madt.len() as u64).unwrap();
guest_mem
.write_slice(mcfg.as_slice(), mcfg_offset)
.expect("Error writing MCFG table");
tables.push(mcfg_offset.0);
// SRAT and SLIT
// Only created if the NUMA nodes list is not empty.
let (prev_tbl_len, prev_tbl_off) = if numa_nodes.is_empty() {
(mcfg.len(), mcfg_offset)
} else {
// SRAT
fn create_srat_table(numa_nodes: &NumaNodes) -> Sdt {
let mut srat = Sdt::new(*b"SRAT", 36, 3, *b"CLOUDH", *b"CHSRAT ", 1);
// SRAT reserved 12 bytes
srat.append_slice(&[0u8; 12]);
@ -245,14 +206,10 @@ pub fn create_acpi_tables(
});
}
}
srat
}
let srat_offset = mcfg_offset.checked_add(mcfg.len() as u64).unwrap();
guest_mem
.write_slice(srat.as_slice(), srat_offset)
.expect("Error writing SRAT table");
tables.push(srat_offset.0);
// SLIT
fn create_slit_table(numa_nodes: &NumaNodes) -> Sdt {
let mut slit = Sdt::new(*b"SLIT", 36, 1, *b"CLOUDH", *b"CHSLIT ", 1);
// Number of System Localities on 8 bytes.
slit.append(numa_nodes.len() as u64);
@ -272,7 +229,65 @@ pub fn create_acpi_tables(
slit.append(dist);
}
}
slit
}
pub fn create_acpi_tables(
guest_mem: &GuestMemoryMmap,
device_manager: &Arc<Mutex<DeviceManager>>,
cpu_manager: &Arc<Mutex<CpuManager>>,
memory_manager: &Arc<Mutex<MemoryManager>>,
numa_nodes: &NumaNodes,
) -> GuestAddress {
let rsdp_offset = arch::layout::RSDP_POINTER;
let mut tables: Vec<u64> = Vec::new();
// DSDT
let dsdt = create_dsdt_table(device_manager, cpu_manager, memory_manager);
let dsdt_offset = rsdp_offset.checked_add(Rsdp::len() as u64).unwrap();
guest_mem
.write_slice(dsdt.as_slice(), dsdt_offset)
.expect("Error writing DSDT table");
// FACP aka FADT
let facp = create_facp_table(dsdt_offset);
let facp_offset = dsdt_offset.checked_add(dsdt.len() as u64).unwrap();
guest_mem
.write_slice(facp.as_slice(), facp_offset)
.expect("Error writing FACP table");
tables.push(facp_offset.0);
// MADT
let madt = cpu_manager.lock().unwrap().create_madt();
let madt_offset = facp_offset.checked_add(facp.len() as u64).unwrap();
guest_mem
.write_slice(madt.as_slice(), madt_offset)
.expect("Error writing MADT table");
tables.push(madt_offset.0);
// MCFG
let mcfg = create_mcfg_table();
let mcfg_offset = madt_offset.checked_add(madt.len() as u64).unwrap();
guest_mem
.write_slice(mcfg.as_slice(), mcfg_offset)
.expect("Error writing MCFG table");
tables.push(mcfg_offset.0);
// SRAT and SLIT
// Only created if the NUMA nodes list is not empty.
let (prev_tbl_len, prev_tbl_off) = if numa_nodes.is_empty() {
(mcfg.len(), mcfg_offset)
} else {
// SRAT
let srat = create_srat_table(numa_nodes);
let srat_offset = mcfg_offset.checked_add(mcfg.len() as u64).unwrap();
guest_mem
.write_slice(srat.as_slice(), srat_offset)
.expect("Error writing SRAT table");
tables.push(srat_offset.0);
// SLIT
let slit = create_slit_table(numa_nodes);
let slit_offset = srat_offset.checked_add(srat.len() as u64).unwrap();
guest_mem
.write_slice(slit.as_slice(), slit_offset)