diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index 4abd7f3bf..5d314a4a4 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -105,6 +105,133 @@ pub fn create_dsdt_table( 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::(0x3c0)); + // RESET_VALUE + facp.write(128, 1u8); + // X_PM_TMR_BLK + facp.write(208, GenericAddress::io_port_address::(0xb008)); + // SLEEP_CONTROL_REG + facp.write(244, GenericAddress::io_port_address::(0x3c0)); + // SLEEP_STATUS_REG + facp.write(256, GenericAddress::io_port_address::(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::(), 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 = 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( guest_mem: &GuestMemoryMmap, device_manager: &Arc>, @@ -123,41 +250,7 @@ pub fn create_acpi_tables( .expect("Error writing DSDT table"); // FACP aka FADT - // 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 - #[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::(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::(0xb008)); - - // SLEEP_CONTROL_REG - #[cfg(target_arch = "x86_64")] - facp.write(244, GenericAddress::io_port_address::(0x3c0)); - // SLEEP_STATUS_REG - #[cfg(target_arch = "x86_64")] - facp.write(256, GenericAddress::io_port_address::(0x3c0)); - - facp.write(268, b"CLOUDHYP"); // Hypervisor Vendor Identity - - facp.update_checksum(); + 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) @@ -173,20 +266,7 @@ pub fn create_acpi_tables( tables.push(madt_offset.0); // MCFG - 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() - }); - + 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) @@ -199,53 +279,7 @@ pub fn create_acpi_tables( (mcfg.len(), mcfg_offset) } else { // SRAT - 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::(), 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 = 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) @@ -253,26 +287,7 @@ pub fn create_acpi_tables( tables.push(srat_offset.0); // SLIT - 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 = 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 = 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)