ARM: Virt: ACPI: Build an IORT table with RC and ITS nodes

This patch builds an IORT table that features a root complex node and
an ITS node. This complements the ITS description in the ACPI MADT
table and allows vhost-net on ACPI guest.

Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Message-id: 1476707466-14300-3-git-send-email-eric.auger@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Prem Mallappa 2016-10-24 16:26:54 +01:00 committed by Peter Maydell
parent 16fc326a55
commit e78f122214

View file

@ -383,6 +383,61 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
return rsdp_table;
}
static void
build_iort(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
{
int iort_start = table_data->len;
AcpiIortIdMapping *idmap;
AcpiIortItsGroup *its;
AcpiIortTable *iort;
size_t node_size, iort_length;
AcpiIortRC *rc;
iort = acpi_data_push(table_data, sizeof(*iort));
iort_length = sizeof(*iort);
iort->node_count = cpu_to_le32(2); /* RC and ITS nodes */
iort->node_offset = cpu_to_le32(sizeof(*iort));
/* ITS group node */
node_size = sizeof(*its) + sizeof(uint32_t);
iort_length += node_size;
its = acpi_data_push(table_data, node_size);
its->type = ACPI_IORT_NODE_ITS_GROUP;
its->length = cpu_to_le16(node_size);
its->its_count = cpu_to_le32(1);
its->identifiers[0] = 0; /* MADT translation_id */
/* Root Complex Node */
node_size = sizeof(*rc) + sizeof(*idmap);
iort_length += node_size;
rc = acpi_data_push(table_data, node_size);
rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
rc->length = cpu_to_le16(node_size);
rc->mapping_count = cpu_to_le32(1);
rc->mapping_offset = cpu_to_le32(sizeof(*rc));
/* fully coherent device */
rc->memory_properties.cache_coherency = cpu_to_le32(1);
rc->memory_properties.memory_flags = 0x3; /* CCA = CPM = DCAS = 1 */
rc->pci_segment_number = 0; /* MCFG pci_segment */
/* Identity RID mapping covering the whole input RID range */
idmap = &rc->id_mapping_array[0];
idmap->input_base = 0;
idmap->id_count = cpu_to_le32(0xFFFF);
idmap->output_base = 0;
/* output IORT node is the ITS group node (the first node) */
idmap->output_reference = cpu_to_le32(iort->node_offset);
iort->length = cpu_to_le32(iort_length);
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,17 +722,6 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
ACPI_BUILD_TABLE_FILE, tables_blob,
64, false /* high memory */);
/*
* The ACPI v5.1 tables for Hardware-reduced ACPI platform are:
* RSDP
* RSDT
* FADT
* GTDT
* MADT
* MCFG
* DSDT
*/
/* DSDT is pointed to by FADT */
dsdt = tables_blob->len;
build_dsdt(tables_blob, tables->linker, guest_info);
@ -703,6 +747,11 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
build_srat(tables_blob, tables->linker, guest_info);
}
if (its_class_name() && !guest_info->no_its) {
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);