diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index 28edab01b..47748322b 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -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>, @@ -255,6 +289,8 @@ pub fn create_acpi_tables( memory_manager: &Arc>, 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 = 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");