xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [RFC] [PATCH] arm-acpi: Hide SMMU from IORT for hardware domain
@ 2017-06-08 12:38 Manish Jaggi
  2017-06-08 13:09 ` Julien Grall
  0 siblings, 1 reply; 6+ messages in thread
From: Manish Jaggi @ 2017-06-08 12:38 UTC (permalink / raw)
  To: xen-devel, Julien Grall
  Cc: Stefano Stabellini, Steve Capper, Andre Przywara, Jiandi An,
	Punit Agrawal, Goel, Sameer, nd, Charles Garcia-Tobin


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@cavium.com>
---
  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@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-06-09 10:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-08 12:38 [RFC] [PATCH] arm-acpi: Hide SMMU from IORT for hardware domain Manish Jaggi
2017-06-08 13:09 ` Julien Grall
2017-06-09  7:13   ` Manish Jaggi
2017-06-09  9:23     ` Julien Grall
2017-06-09 10:02       ` Manish Jaggi
2017-06-09 10:43         ` Julien Grall

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).