Added ACPI IORT tables, was needed for internal project purpose, but posting here for anyone looking for testing ACPI on ARM platforms. (P.S: Linux side IORT patches are WIP)
Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com> --- hw/arm/virt-acpi-build.c | 43 +++++++++++++++++++++++ include/hw/acpi/acpi-defs.h | 84 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 1fa0581..d5fb69e 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -382,6 +382,45 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset) return rsdp_table; } +/* + * TODO: Simple IORT for now, will add ID mappings as we go + * basic idea is to instantiate SMMU from ACPI + */ +static void +build_iort(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) +{ + int iort_start = table_data->len; + AcpiIortTable *iort; + AcpiIortNode *iort_node; + AcpiIortSmmu3 *smmu; + AcpiIortRC *rc; + const MemMapEntry *memmap = guest_info->memmap; + + iort = acpi_data_push(table_data, sizeof(*iort)); + + iort->length = sizeof(*iort); + iort->node_offset = table_data->len - iort_start; + iort->num_nodes++; + + smmu = acpi_data_push(table_data, sizeof(*smmu)); + iort_node = &smmu->iort_node; + iort_node->type = 0x04; /* SMMUv3 */ + iort_node->length = sizeof(*smmu); + smmu->base_addr = cpu_to_le64(memmap[VIRT_SMMU].base); + + iort->num_nodes++; + + rc = acpi_data_push(table_data, sizeof(*rc)); + iort_node = &rc->iort_node; + iort_node->type = 0x02; /* RC */ + iort_node->length = sizeof(*rc); + rc->ats_attr = 1; + rc->pci_seg_num = 0; + + build_header(linker, table_data, (void *)(table_data->data + iort_start), + "IORT", table_data->len - iort_start, 0, NULL, NULL); +} + static void build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) { @@ -667,6 +706,7 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) * MADT * MCFG * DSDT + * IORT = ACPI 6.0 */ /* DSDT is pointed to by FADT */ @@ -694,6 +734,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) build_srat(tables_blob, tables->linker, guest_info); } + acpi_add_table(table_offsets, tables_blob); + build_iort(tables_blob, tables->linker, guest_info); + /* RSDT is pointed to by RSDP */ rsdt = tables_blob->len; build_rsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 850a962..d60f390 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -259,6 +259,90 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1; */ /* + * IORT Table + */ +struct AcpiIortTable +{ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + uint32_t num_nodes; + uint32_t node_offset; + uint32_t reserved; +} QEMU_PACKED; +typedef struct AcpiIortTable AcpiIortTable; + +struct AcpiIortIdMapping +{ + uint32_t input_base; + uint32_t num_ids; + uint32_t output_base; + uint32_t output_ref; + uint32_t flags; +} QEMU_PACKED; +typedef struct AcpiIortIdMapping AcpiIortIdMapping; + +struct AcpiIortNode +{ + uint8_t type; + uint16_t length; + uint8_t revision; + uint32_t reserved1; + uint32_t num_id_maps; + uint32_t id_array_offset; +} QEMU_PACKED; +typedef struct AcpiIortNode AcpiIortNode; + +struct AcpiIortSmmu2 +{ + AcpiIortNode iort_node; + uint64_t base_addr; + uint64_t span; + uint32_t model; + uint32_t flags; + uint32_t gbl_intr_array_off; + uint32_t ctx_intr_cnt; + uint32_t ctx_intr_array_off; + uint32_t pmr_intr_cnt; + uint32_t pmr_intr_array_off; + + // Global interrupt array + uint32_t gintr; + uint32_t gintr_flags; + uint32_t gcfgintr; + uint32_t gcfgintr_flags; + + //AcpiIortIdMapping id_mapping_array[0]; +} QEMU_PACKED; +typedef struct AcpiIortSmmu2 AcpiIortSmmu2; + +struct AcpiIortSmmu3 +{ + AcpiIortNode iort_node; + uint64_t base_addr; + uint32_t flags; + uint32_t reserved2; + uint64_t vatos_addr; + uint32_t model; + uint32_t event_irq; + uint32_t pri_irq; + uint32_t gerr_irq; + uint32_t sync_irq; + + //AcpiIortIdMapping id_mapping_array[0]; +} QEMU_PACKED; +typedef struct AcpiIortSmmu3 AcpiIortSmmu3; + +struct AcpiIortRC +{ + AcpiIortNode iort_node; + uint64_t mem_access_prop; + uint32_t ats_attr; + uint32_t pci_seg_num; + + AcpiIortIdMapping id_mapping_array[0]; +} QEMU_PACKED; +typedef struct AcpiIortRC AcpiIortRC; + +/* * MADT values and structures */ -- 2.9.0