acpi: Implement GTDT on AArch64

This commit implements an AArch64-specific ACPI table: Generic
Timer Description Table (GTDT). The GTDT provides OSPM with
information about a system’s Generic Timers configuration.

The Generic Timer (GT) is a standard timer interface implemented
on ARM processor-based systems.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
This commit is contained in:
Henry Wang 2021-01-31 11:39:32 +08:00 committed by Sebastien Boeuf
parent 7bfb51489b
commit 9c5528490e

View File

@ -248,6 +248,40 @@ fn create_slit_table(numa_nodes: &NumaNodes) -> Sdt {
slit
}
#[cfg(target_arch = "aarch64")]
fn create_gtdt_table() -> Sdt {
const ARCH_TIMER_NS_EL2_IRQ: u32 = 10;
const ARCH_TIMER_VIRT_IRQ: u32 = 11;
const ARCH_TIMER_S_EL1_IRQ: u32 = 13;
const ARCH_TIMER_NS_EL1_IRQ: u32 = 14;
const ACPI_GTDT_INTERRUPT_MODE_LEVEL: u32 = 0;
const ACPI_GTDT_CAP_ALWAYS_ON: u32 = 1 << 2;
let irqflags: u32 = ACPI_GTDT_INTERRUPT_MODE_LEVEL;
// GTDT
let mut gtdt = Sdt::new(*b"GTDT", 104, 2, *b"CLOUDH", *b"CHGTDT ", 1);
// Secure EL1 Timer GSIV
gtdt.write(48, (ARCH_TIMER_S_EL1_IRQ + 16) as u32);
// Secure EL1 Timer Flags
gtdt.write(52, irqflags);
// Non-Secure EL1 Timer GSIV
gtdt.write(56, (ARCH_TIMER_NS_EL1_IRQ + 16) as u32);
// Non-Secure EL1 Timer Flags
gtdt.write(60, (irqflags | ACPI_GTDT_CAP_ALWAYS_ON) as u32);
// Virtual EL1 Timer GSIV
gtdt.write(64, (ARCH_TIMER_VIRT_IRQ + 16) as u32);
// Virtual EL1 Timer Flags
gtdt.write(68, irqflags);
// EL2 Timer GSIV
gtdt.write(72, (ARCH_TIMER_NS_EL2_IRQ + 16) as u32);
// EL2 Timer Flags
gtdt.write(76, irqflags);
gtdt.update_checksum();
gtdt
}
pub fn create_acpi_tables(
guest_mem: &GuestMemoryMmap,
device_manager: &Arc<Mutex<DeviceManager>>,
@ -255,6 +289,8 @@ pub fn create_acpi_tables(
memory_manager: &Arc<Mutex<MemoryManager>>,
numa_nodes: &NumaNodes,
) -> GuestAddress {
let mut prev_tbl_len: u64;
let mut prev_tbl_off: GuestAddress;
let rsdp_offset = arch::layout::RSDP_POINTER;
let mut tables: Vec<u64> = Vec::new();
@ -280,10 +316,25 @@ pub fn create_acpi_tables(
.write_slice(madt.as_slice(), madt_offset)
.expect("Error writing MADT table");
tables.push(madt_offset.0);
prev_tbl_len = madt.len() as u64;
prev_tbl_off = madt_offset;
// GTDT
#[cfg(target_arch = "aarch64")]
{
let gtdt = create_gtdt_table();
let gtdt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap();
guest_mem
.write_slice(gtdt.as_slice(), gtdt_offset)
.expect("Error writing GTDT table");
tables.push(gtdt_offset.0);
prev_tbl_len = gtdt.len() as u64;
prev_tbl_off = gtdt_offset;
}
// MCFG
let mcfg = create_mcfg_table();
let mcfg_offset = madt_offset.checked_add(madt.len() as u64).unwrap();
let mcfg_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap();
guest_mem
.write_slice(mcfg.as_slice(), mcfg_offset)
.expect("Error writing MCFG table");