[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.