From 27a285257e913778329e9deb1813cd5c2b44d205 Mon Sep 17 00:00:00 2001 From: Henry Wang Date: Fri, 30 Jul 2021 02:50:54 -0400 Subject: [PATCH] vmm: cpu: Add PPTT table for AArch64 The optional Processor Properties Topology Table (PPTT) table is used to describe the topological structure of processors controlled by the OSPM, and their shared resources, such as caches. The table can also describe additional information such as which nodes in the processor topology constitute a physical package. The ACPI PPTT table supports topology descriptions for ACPI guests. Therefore, this commit adds the PPTT table for AArch64 to enable CPU topology feature for ACPI. Signed-off-by: Henry Wang --- vmm/src/acpi.rs | 13 ++++++++ vmm/src/cpu.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index bd8605c9a..551927d42 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -508,6 +508,19 @@ pub fn create_acpi_tables( prev_tbl_len = madt.len() as u64; prev_tbl_off = madt_offset; + // PPTT + #[cfg(target_arch = "aarch64")] + { + let pptt = cpu_manager.lock().unwrap().create_pptt(); + let pptt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); + guest_mem + .write_slice(pptt.as_slice(), pptt_offset) + .expect("Error writing PPTT table"); + tables.push(pptt_offset.0); + prev_tbl_len = pptt.len() as u64; + prev_tbl_off = pptt_offset; + } + // GTDT #[cfg(target_arch = "aarch64")] { diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index d08dbe8f1..0fabab841 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -191,6 +191,19 @@ struct GicIts { pub reserved1: u32, } +#[cfg(all(target_arch = "aarch64", feature = "acpi"))] +#[allow(dead_code)] +#[repr(packed)] +struct ProcessorHierarchyNode { + pub r#type: u8, + pub length: u8, + pub reserved: u16, + pub flags: u32, + pub parent: u32, + pub acpi_processor_id: u32, + pub num_private_resources: u32, +} + #[allow(dead_code)] #[repr(packed)] #[derive(Default)] @@ -1115,6 +1128,81 @@ impl CpuManager { madt } + + #[cfg(all(target_arch = "aarch64", feature = "acpi"))] + pub fn create_pptt(&self) -> Sdt { + let pptt_start = 0; + let mut cpus = 0; + let mut uid = 0; + let threads_per_core = self.get_vcpu_topology().unwrap_or_default().0 as u8; + let cores_per_package = self.get_vcpu_topology().unwrap_or_default().1 as u8; + let packages = self.get_vcpu_topology().unwrap_or_default().2 as u8; + + let mut pptt = Sdt::new(*b"PPTT", 36, 2, *b"CLOUDH", *b"CHPPTT ", 1); + + for cluster_idx in 0..packages { + if cpus < self.config.boot_vcpus as usize { + let cluster_offset = pptt.len() - pptt_start; + let cluster_hierarchy_node = ProcessorHierarchyNode { + r#type: 0, + length: 20, + reserved: 0, + flags: 0x2, + parent: 0, + acpi_processor_id: cluster_idx as u32, + num_private_resources: 0, + }; + pptt.append(cluster_hierarchy_node); + + for core_idx in 0..cores_per_package { + let core_offset = pptt.len() - pptt_start; + + if threads_per_core > 1 { + let core_hierarchy_node = ProcessorHierarchyNode { + r#type: 0, + length: 20, + reserved: 0, + flags: 0x2, + parent: cluster_offset as u32, + acpi_processor_id: core_idx as u32, + num_private_resources: 0, + }; + pptt.append(core_hierarchy_node); + + for _thread_idx in 0..threads_per_core { + let thread_hierarchy_node = ProcessorHierarchyNode { + r#type: 0, + length: 20, + reserved: 0, + flags: 0xE, + parent: core_offset as u32, + acpi_processor_id: uid as u32, + num_private_resources: 0, + }; + pptt.append(thread_hierarchy_node); + uid += 1; + } + } else { + let thread_hierarchy_node = ProcessorHierarchyNode { + r#type: 0, + length: 20, + reserved: 0, + flags: 0xA, + parent: cluster_offset as u32, + acpi_processor_id: uid as u32, + num_private_resources: 0, + }; + pptt.append(thread_hierarchy_node); + uid += 1; + } + } + cpus += (cores_per_package * threads_per_core) as usize; + } + } + + pptt.update_checksum(); + pptt + } } #[cfg(feature = "acpi")]