mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
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:
parent
5ae04349da
commit
01acea3102
247
vmm/src/acpi.rs
247
vmm/src/acpi.rs
@ -105,6 +105,133 @@ pub fn create_dsdt_table(
|
|||||||
dsdt
|
dsdt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
facp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_mcfg_table() -> Sdt {
|
||||||
|
let mut mcfg = Sdt::new(*b"MCFG", 36, 1, *b"CLOUDH", *b"CHMCFG ", 1);
|
||||||
|
|
||||||
|
// MCFG reserved 8 bytes
|
||||||
|
mcfg.append(0u64);
|
||||||
|
|
||||||
|
// 32-bit PCI enhanced configuration mechanism
|
||||||
|
mcfg.append(PciRangeEntry {
|
||||||
|
base_address: arch::layout::PCI_MMCONFIG_START.0,
|
||||||
|
segment: 0,
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
mcfg
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
|
||||||
|
// Check the MemoryAffinity structure is the right size as expected by
|
||||||
|
// the ACPI specification.
|
||||||
|
assert_eq!(std::mem::size_of::<MemoryAffinity>(), 40);
|
||||||
|
|
||||||
|
for (node_id, node) in numa_nodes.iter() {
|
||||||
|
let proximity_domain = *node_id as u32;
|
||||||
|
|
||||||
|
for region in node.memory_regions() {
|
||||||
|
srat.append(MemoryAffinity::from_region(
|
||||||
|
region,
|
||||||
|
proximity_domain,
|
||||||
|
MemAffinityFlags::ENABLE,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
for region in node.hotplug_regions() {
|
||||||
|
srat.append(MemoryAffinity::from_region(
|
||||||
|
region,
|
||||||
|
proximity_domain,
|
||||||
|
MemAffinityFlags::ENABLE | MemAffinityFlags::HOTPLUGGABLE,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
for cpu in node.cpus() {
|
||||||
|
let x2apic_id = *cpu as u32;
|
||||||
|
|
||||||
|
// Flags
|
||||||
|
// - Enabled = 1 (bit 0)
|
||||||
|
// - Reserved bits 1-31
|
||||||
|
let flags = 1;
|
||||||
|
|
||||||
|
srat.append(ProcessorLocalX2ApicAffinity {
|
||||||
|
type_: 2,
|
||||||
|
length: 24,
|
||||||
|
proximity_domain,
|
||||||
|
x2apic_id,
|
||||||
|
flags,
|
||||||
|
clock_domain: 0,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
srat
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
let existing_nodes: Vec<u32> = numa_nodes.keys().cloned().collect();
|
||||||
|
for (node_id, node) in numa_nodes.iter() {
|
||||||
|
let distances = node.distances();
|
||||||
|
for i in existing_nodes.iter() {
|
||||||
|
let dist: u8 = if *node_id == *i {
|
||||||
|
10
|
||||||
|
} else if let Some(distance) = distances.get(i) {
|
||||||
|
*distance as u8
|
||||||
|
} else {
|
||||||
|
20
|
||||||
|
};
|
||||||
|
|
||||||
|
slit.append(dist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slit
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_acpi_tables(
|
pub fn create_acpi_tables(
|
||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
device_manager: &Arc<Mutex<DeviceManager>>,
|
device_manager: &Arc<Mutex<DeviceManager>>,
|
||||||
@ -123,41 +250,7 @@ pub fn create_acpi_tables(
|
|||||||
.expect("Error writing DSDT table");
|
.expect("Error writing DSDT table");
|
||||||
|
|
||||||
// FACP aka FADT
|
// FACP aka FADT
|
||||||
// Revision 6 of the ACPI FADT table is 276 bytes long
|
let facp = create_facp_table(dsdt_offset);
|
||||||
let mut facp = Sdt::new(*b"FACP", 276, 6, *b"CLOUDH", *b"CHFACP ", 1);
|
|
||||||
|
|
||||||
// PM_TMR_BLK I/O port
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
facp.write(76, 0xb008u32);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
facp.update_checksum();
|
|
||||||
let facp_offset = dsdt_offset.checked_add(dsdt.len() as u64).unwrap();
|
let facp_offset = dsdt_offset.checked_add(dsdt.len() as u64).unwrap();
|
||||||
guest_mem
|
guest_mem
|
||||||
.write_slice(facp.as_slice(), facp_offset)
|
.write_slice(facp.as_slice(), facp_offset)
|
||||||
@ -173,20 +266,7 @@ pub fn create_acpi_tables(
|
|||||||
tables.push(madt_offset.0);
|
tables.push(madt_offset.0);
|
||||||
|
|
||||||
// MCFG
|
// MCFG
|
||||||
let mut mcfg = Sdt::new(*b"MCFG", 36, 1, *b"CLOUDH", *b"CHMCFG ", 1);
|
let mcfg = create_mcfg_table();
|
||||||
|
|
||||||
// MCFG reserved 8 bytes
|
|
||||||
mcfg.append(0u64);
|
|
||||||
|
|
||||||
// 32-bit PCI enhanced configuration mechanism
|
|
||||||
mcfg.append(PciRangeEntry {
|
|
||||||
base_address: arch::layout::PCI_MMCONFIG_START.0,
|
|
||||||
segment: 0,
|
|
||||||
start: 0,
|
|
||||||
end: 0,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
|
|
||||||
let mcfg_offset = madt_offset.checked_add(madt.len() as u64).unwrap();
|
let mcfg_offset = madt_offset.checked_add(madt.len() as u64).unwrap();
|
||||||
guest_mem
|
guest_mem
|
||||||
.write_slice(mcfg.as_slice(), mcfg_offset)
|
.write_slice(mcfg.as_slice(), mcfg_offset)
|
||||||
@ -199,53 +279,7 @@ pub fn create_acpi_tables(
|
|||||||
(mcfg.len(), mcfg_offset)
|
(mcfg.len(), mcfg_offset)
|
||||||
} else {
|
} else {
|
||||||
// SRAT
|
// SRAT
|
||||||
let mut srat = Sdt::new(*b"SRAT", 36, 3, *b"CLOUDH", *b"CHSRAT ", 1);
|
let srat = create_srat_table(numa_nodes);
|
||||||
// SRAT reserved 12 bytes
|
|
||||||
srat.append_slice(&[0u8; 12]);
|
|
||||||
|
|
||||||
// Check the MemoryAffinity structure is the right size as expected by
|
|
||||||
// the ACPI specification.
|
|
||||||
assert_eq!(std::mem::size_of::<MemoryAffinity>(), 40);
|
|
||||||
|
|
||||||
for (node_id, node) in numa_nodes.iter() {
|
|
||||||
let proximity_domain = *node_id as u32;
|
|
||||||
|
|
||||||
for region in node.memory_regions() {
|
|
||||||
srat.append(MemoryAffinity::from_region(
|
|
||||||
region,
|
|
||||||
proximity_domain,
|
|
||||||
MemAffinityFlags::ENABLE,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
for region in node.hotplug_regions() {
|
|
||||||
srat.append(MemoryAffinity::from_region(
|
|
||||||
region,
|
|
||||||
proximity_domain,
|
|
||||||
MemAffinityFlags::ENABLE | MemAffinityFlags::HOTPLUGGABLE,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
for cpu in node.cpus() {
|
|
||||||
let x2apic_id = *cpu as u32;
|
|
||||||
|
|
||||||
// Flags
|
|
||||||
// - Enabled = 1 (bit 0)
|
|
||||||
// - Reserved bits 1-31
|
|
||||||
let flags = 1;
|
|
||||||
|
|
||||||
srat.append(ProcessorLocalX2ApicAffinity {
|
|
||||||
type_: 2,
|
|
||||||
length: 24,
|
|
||||||
proximity_domain,
|
|
||||||
x2apic_id,
|
|
||||||
flags,
|
|
||||||
clock_domain: 0,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let srat_offset = mcfg_offset.checked_add(mcfg.len() as u64).unwrap();
|
let srat_offset = mcfg_offset.checked_add(mcfg.len() as u64).unwrap();
|
||||||
guest_mem
|
guest_mem
|
||||||
.write_slice(srat.as_slice(), srat_offset)
|
.write_slice(srat.as_slice(), srat_offset)
|
||||||
@ -253,26 +287,7 @@ pub fn create_acpi_tables(
|
|||||||
tables.push(srat_offset.0);
|
tables.push(srat_offset.0);
|
||||||
|
|
||||||
// SLIT
|
// SLIT
|
||||||
let mut slit = Sdt::new(*b"SLIT", 36, 1, *b"CLOUDH", *b"CHSLIT ", 1);
|
let slit = create_slit_table(numa_nodes);
|
||||||
// Number of System Localities on 8 bytes.
|
|
||||||
slit.append(numa_nodes.len() as u64);
|
|
||||||
|
|
||||||
let existing_nodes: Vec<u32> = numa_nodes.keys().cloned().collect();
|
|
||||||
for (node_id, node) in numa_nodes.iter() {
|
|
||||||
let distances = node.distances();
|
|
||||||
for i in existing_nodes.iter() {
|
|
||||||
let dist: u8 = if *node_id == *i {
|
|
||||||
10
|
|
||||||
} else if let Some(distance) = distances.get(i) {
|
|
||||||
*distance as u8
|
|
||||||
} else {
|
|
||||||
20
|
|
||||||
};
|
|
||||||
|
|
||||||
slit.append(dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let slit_offset = srat_offset.checked_add(srat.len() as u64).unwrap();
|
let slit_offset = srat_offset.checked_add(srat.len() as u64).unwrap();
|
||||||
guest_mem
|
guest_mem
|
||||||
.write_slice(slit.as_slice(), slit_offset)
|
.write_slice(slit.as_slice(), slit_offset)
|
||||||
|
Loading…
Reference in New Issue
Block a user