From d882f8c928c923e6e83fb9700ba387369fb81585 Mon Sep 17 00:00:00 2001 From: Henry Wang Date: Sat, 6 Feb 2021 11:27:15 +0800 Subject: [PATCH] acpi: Implement IORT for AArch64 This commit implements the IO Remapping Table (IORT) for AArch64. The IORT is one of the required ACPI table for AArch64, since it describes the GICv3ITS node. Signed-off-by: Henry Wang --- vmm/src/acpi.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index 1de4010a0..d82b6929d 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -313,6 +313,48 @@ fn create_spcr_table(base_address: u64, gsi: u32) -> Sdt { spcr } +#[cfg(target_arch = "aarch64")] +fn create_iort_table() -> Sdt { + const ACPI_IORT_NODE_ITS_GROUP: u8 = 0x00; + const ACPI_IORT_NODE_PCI_ROOT_COMPLEX: u8 = 0x02; + + // IORT + let mut iort = Sdt::new(*b"IORT", 124, 2, *b"CLOUDH", *b"CHIORT ", 1); + // Nodes: PCI Root Complex, ITS + // Note: We currently do not support SMMU + iort.write(36, (2u32).to_le()); + iort.write(40, (48u32).to_le()); + + // ITS group node + iort.write(48, ACPI_IORT_NODE_ITS_GROUP as u8); + // Length of the ITS group node in bytes + iort.write(49, (24u16).to_le()); + // ITS counts + iort.write(64, (1u32).to_le()); + + // Root Complex Node + iort.write(72, ACPI_IORT_NODE_PCI_ROOT_COMPLEX as u8); + // Length of the root complex node in bytes + iort.write(73, (52u16).to_le()); + // Mapping counts + iort.write(80, (1u32).to_le()); + // Offset from the start of the RC node to the start of its Array of ID mappings + iort.write(84, (32u32).to_le()); + // Fully coherent device + iort.write(88, (1u32).to_le()); + // CCA = CPM = DCAS = 1 + iort.write(95, 3u8); + // Identity RID mapping covering the whole input RID range + iort.write(108, (0xffff_u32).to_le()); + // id_mapping_array_output_reference should be + // the ITS group node (the first node) if no SMMU + iort.write(116, (48u32).to_le()); + + iort.update_checksum(); + + iort +} + pub fn create_acpi_tables( guest_mem: &GuestMemoryMmap, device_manager: &Arc>, @@ -430,14 +472,25 @@ pub fn create_acpi_tables( prev_tbl_off = slit_offset; }; + #[cfg(target_arch = "aarch64")] + { + let iort = create_iort_table(); + let iort_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); + guest_mem + .write_slice(iort.as_slice(), iort_offset) + .expect("Error writing IORT table"); + tables.push(iort_offset.0); + prev_tbl_len = iort.len() as u64; + prev_tbl_off = iort_offset; + } + // XSDT let mut xsdt = Sdt::new(*b"XSDT", 36, 1, *b"CLOUDH", *b"CHXSDT ", 1); for table in tables { xsdt.append(table); } xsdt.update_checksum(); - - let xsdt_offset = prev_tbl_off.checked_add(prev_tbl_len as u64).unwrap(); + let xsdt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); guest_mem .write_slice(xsdt.as_slice(), xsdt_offset) .expect("Error writing XSDT table");