[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC] [PATCH] arm-acpi: Hide SMMU from IORT for hardware domain
This patch disables the smmu node in IORT table for hardware domain. Also patches the output_base of pci_rc id_array with output_base of smmu node id_array. Signed-off-by: Manish Jaggi <mjaggi@xxxxxxxxxx> ---xen/arch/arm/domain_build.c | 142 +++++++++++++++++++++++++++++++++++++++++++- xen/include/acpi/actbl2.h | 3 +- xen/include/asm-arm/acpi.h | 1 + 3 files changed, 144 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index d6d6c94..9f41d0e 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -32,6 +32,7 @@ integer_param("dom0_max_vcpus", opt_dom0_max_vcpus); int dom0_11_mapping = 1; static u64 __initdata dom0_mem; +static u8 *iort_base_ptr; static void __init parse_dom0_mem(const char *s) {@@ -1336,6 +1337,96 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo) #ifdef CONFIG_ACPI #define ACPI_DOM0_FDT_MIN_SIZE 4096 +static void patch_output_ref(struct acpi_iort_id_mapping *pci_idmap, + struct acpi_iort_node *smmu_node) +{ + struct acpi_iort_id_mapping *idmap = NULL; + int i; + for (i=0; i < smmu_node->mapping_count; i++) { + if(!idmap) + idmap = (struct acpi_iort_id_mapping*)((u8*)smmu_node + + smmu_node->mapping_offset); + else + idmap++; + + if (pci_idmap->output_base == idmap->input_base) { + pci_idmap->output_base = idmap->output_base; + pci_idmap->output_reference = idmap->output_reference; + } + } +} + +static void fixup_pcirc_node(struct acpi_iort_node *node) +{ + struct acpi_iort_id_mapping *idmap = NULL; + struct acpi_iort_node *onode; + int i=0; + + for (i=0; i < node->mapping_count; i++) { + if(!idmap) + idmap = (struct acpi_iort_id_mapping*)((u8*)node + + + node->mapping_offset); + else + idmap++; + + onode = (struct acpi_iort_node*)(iort_base_ptr + + idmap->output_reference); + switch (onode->type) + { + case ACPI_IORT_NODE_ITS_GROUP: + continue; + case ACPI_IORT_NODE_SMMU: + case ACPI_IORT_NODE_SMMU_V3: + patch_output_ref(idmap, onode); + break; + } + } +} + +static int hide_smmu_iort(void) +{ + u32 i; + u32 node_offset = 0; + struct acpi_table_iort *iort_table; + struct acpi_iort_node *node = NULL; + + iort_table = (struct acpi_table_iort *)iort_base_ptr; + + for (i=0; i < iort_table->node_count; i++) { + if (!node){ + node = (struct acpi_iort_node *)(iort_base_ptr + + iort_table->node_offset); + node_offset = iort_table->node_offset; + } else { + node = (struct acpi_iort_node *)(iort_base_ptr + + node_offset); + } + + node_offset += node->length; + if (node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) + fixup_pcirc_node(node); + } + + node_offset = 0; + node = NULL; + for (i=0; i < iort_table->node_count; i++) { + if (!node){ + node = (struct acpi_iort_node *)(iort_base_ptr + + iort_table->node_offset); + node_offset = iort_table->node_offset; + } else { + node = (struct acpi_iort_node *)(iort_base_ptr + + node_offset); + } + node_offset += node->length; + if ((node->type == ACPI_IORT_NODE_SMMU) || + (node->type == ACPI_IORT_NODE_SMMU_V3)) + node->type = ACPI_IORT_NODE_RESERVED; + } + + return 0; +} + static int acpi_iomem_deny_access(struct domain *d) { acpi_status status; @@ -1348,7 +1439,12 @@ static int acpi_iomem_deny_access(struct domain *d) if ( rc ) return rc; - /* TODO: Deny MMIO access for SMMU, GIC ITS */ + /* Hide SMMU from IORT */ + rc = hide_smmu_iort(); + if (rc) + return rc; + + /* Deny MMIO access for GIC ITS */ status = acpi_get_table(ACPI_SIG_SPCR, 0, (struct acpi_table_header **)&spcr);@@ -1646,6 +1742,8 @@ static int acpi_create_xsdt(struct domain *d, struct membank tbl_add[]) ACPI_SIG_FADT, tbl_add[TBL_FADT].start); acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count, ACPI_SIG_MADT, tbl_add[TBL_MADT].start); + acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count, + ACPI_SIG_IORT, tbl_add[TBL_IORT].start); xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start; xsdt->header.length = table_size;@@ -1794,11 +1892,23 @@ static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo) { size_t efi_size, acpi_size, madt_size; u64 addr; + acpi_status status; struct acpi_table_rsdp *rsdp_tbl; struct acpi_table_header *table; + struct acpi_table_header *iort_table; efi_size = estimate_efi_size(kinfo->mem.nr_banks); + status = acpi_get_table(ACPI_SIG_IORT, 0, &iort_table); + + if ( ACPI_FAILURE(status) ) + { + const char *msg = acpi_format_exception(status); + + printk("Failed to get IORT table, %s\n", msg); + return -EINVAL; + } + acpi_size = ROUNDUP(sizeof(struct acpi_table_fadt), 8); acpi_size += ROUNDUP(sizeof(struct acpi_table_stao), 8);@@ -1839,6 +1949,8 @@ static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo) acpi_size += ROUNDUP(table->length + sizeof(u64), 8); acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + /* Add size of iort */ + acpi_size += iort_table->length; acpi_size += ROUNDUP(sizeof(struct acpi_table_rsdp), 8); d->arch.efi_acpi_len = PAGE_ALIGN(ROUNDUP(efi_size, 8) + ROUNDUP(acpi_size, 8));@@ -1846,6 +1958,30 @@ static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo) return 0; } +static int acpi_create_iort(struct domain *d, struct membank tbl_add[]) +{ + struct acpi_table_header *table; + acpi_status status; + + status = acpi_get_table(ACPI_SIG_IORT, 0, + (struct acpi_table_header **)&table); + if ( ACPI_FAILURE(status) ) + { + printk("Failed to get IORT table\n"); + return -EINVAL; + } + + iort_base_ptr = d->arch.efi_acpi_table + + acpi_get_table_offset(tbl_add, TBL_IORT); + ACPI_MEMCPY(iort_base_ptr, table, table->length); + + tbl_add[TBL_IORT].start = d->arch.efi_acpi_gpa + + acpi_get_table_offset(tbl_add, TBL_IORT); + tbl_add[TBL_IORT].size = table->length; + + return 0; +} + static int prepare_acpi(struct domain *d, struct kernel_info *kinfo) { int rc = 0;@@ -1889,6 +2025,10 @@ static int prepare_acpi(struct domain *d, struct kernel_info *kinfo) if ( rc != 0 ) return rc; + rc = acpi_create_iort(d, tbl_add); + if ( rc != 0 ) + return rc; + rc = acpi_create_xsdt(d, tbl_add); if ( rc != 0 ) return rc; diff --git a/xen/include/acpi/actbl2.h b/xen/include/acpi/actbl2.h index 42beac4..f180ea5 100644 --- a/xen/include/acpi/actbl2.h +++ b/xen/include/acpi/actbl2.h @@ -591,7 +591,8 @@ enum acpi_iort_node_type { ACPI_IORT_NODE_NAMED_COMPONENT = 0x01, ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02, ACPI_IORT_NODE_SMMU = 0x03, - ACPI_IORT_NODE_SMMU_V3 = 0x04 + ACPI_IORT_NODE_SMMU_V3 = 0x04, + ACPI_IORT_NODE_RESERVED = 0xff }; struct acpi_iort_id_mapping { diff --git a/xen/include/asm-arm/acpi.h b/xen/include/asm-arm/acpi.h index 9f954d3..1cc0167 100644 --- a/xen/include/asm-arm/acpi.h +++ b/xen/include/asm-arm/acpi.h @@ -36,6 +36,7 @@ typedef enum { TBL_FADT, TBL_MADT, TBL_STAO, + TBL_IORT, TBL_XSDT, TBL_RSDP, TBL_EFIT, -- 2.7.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |