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 <Henry.Wang@arm.com>
This commit is contained in:
Henry Wang 2021-07-30 02:50:54 -04:00 committed by Michael
parent 447c986916
commit 27a285257e
2 changed files with 101 additions and 0 deletions

View File

@ -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")]
{

View File

@ -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")]