From b0d245be70014abd40d1aeea76db1d8da418be91 Mon Sep 17 00:00:00 2001 From: Michael Zhao Date: Thu, 18 Nov 2021 12:57:38 +0800 Subject: [PATCH] vmm: Add ID mappings in IORT Root Complex Nodes Signed-off-by: Michael Zhao --- vmm/src/acpi.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index 80f64cb61..078cf51ba 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -407,12 +407,12 @@ fn create_iort_table(pci_segments: &[PciSegment]) -> Sdt { const ACPI_IORT_NODE_ITS_GROUP: u8 = 0x00; const ACPI_IORT_NODE_PCI_ROOT_COMPLEX: u8 = 0x02; const ACPI_IORT_NODE_ROOT_COMPLEX_OFFSET: usize = 72; - const ACPI_IORT_NODE_ROOT_COMPLEX_SIZE: usize = 52; + const ACPI_IORT_NODE_ROOT_COMPLEX_SIZE: usize = 60; // The IORT table containes: // - Header (size = 40) // - 1 x ITS Group Node (size = 24) - // - N x Root Complex Node (N = number of pci segments, size = 52 x N) + // - N x Root Complex Node (N = number of pci segments, size = 60 x N) let iort_table_size: u32 = (ACPI_IORT_NODE_ROOT_COMPLEX_OFFSET + ACPI_IORT_NODE_ROOT_COMPLEX_SIZE * pci_segments.len()) as u32; @@ -442,18 +442,31 @@ fn create_iort_table(pci_segments: &[PciSegment]) -> Sdt { // Mapping counts iort.write(node_offset + 8, (1u32).to_le()); // Offset from the start of the RC node to the start of its Array of ID mappings - iort.write(node_offset + 12, (32u32).to_le()); + iort.write(node_offset + 12, (36u32).to_le()); // Fully coherent device iort.write(node_offset + 16, (1u32).to_le()); // CCA = CPM = DCAS = 1 iort.write(node_offset + 24, 3u8); // PCI segment number iort.write(node_offset + 28, (segment.id as u32).to_le()); - // Identity RID mapping covering the whole input RID range - iort.write(node_offset + 36, (0xffff_u32).to_le()); + + // From offset 32 onward is the space for ID mappings Array. + // Now we have only one mapping. + let mapping_offset: usize = node_offset + 36; + // The lowest value in the input range + iort.write(mapping_offset, (0u32).to_le()); + // The number of IDs in the range minus one: + // This should cover all the devices of a segment: + // 1 (bus) x 32 (devices) x 8 (functions) = 256 + // Note: Currently only 1 bus is supported in a segment. + iort.write(mapping_offset + 4, (255_u32).to_le()); + // The lowest value in the output range + iort.write(mapping_offset + 8, ((256 * segment.id) as u32).to_le()); // id_mapping_array_output_reference should be // the ITS group node (the first node) if no SMMU - iort.write(node_offset + 44, (48u32).to_le()); + iort.write(mapping_offset + 12, (48u32).to_le()); + // Flags + iort.write(mapping_offset + 16, (0u32).to_le()); } iort.update_checksum();