From mboxrd@z Thu Jan 1 00:00:00 1970 From: Manish Jaggi Subject: [RFC v2] [PATCH] arm64-its: Add ITS support for ACPI dom0 Date: Thu, 8 Jun 2017 17:40:56 +0530 Message-ID: <874e9db7-63bb-8cad-ed69-793d4f08f19d@caviumnetworks.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============5229546472150650745==" Return-path: Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dIwHX-0003ve-OI for xen-devel@lists.xenproject.org; Thu, 08 Jun 2017 12:11:20 +0000 List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: "xen-devel@lists.xenproject.org" , Julien Grall , Andre Przywara List-Id: xen-devel@lists.xenproject.org This is a multi-part message in MIME format. --===============5229546472150650745== Content-Type: multipart/alternative; boundary="------------981E190AD8FF54D8220C713F" This is a multi-part message in MIME format. --------------981E190AD8FF54D8220C713F Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit This patch supports ITS in hardware domain, supports ITS in Xen when booting with ACPI. Signed-off-by: Manish Jaggi --- Changes since v1: - Moved its specific code to gic-v3-its.c - fixed macros xen/arch/arm/domain_build.c | 6 ++-- xen/arch/arm/gic-v3-its.c | 75 +++++++++++++++++++++++++++++++++++++++- xen/arch/arm/gic-v3.c | 10 ++++-- xen/include/asm-arm/gic_v3_its.h | 6 ++++ 4 files changed, 91 insertions(+), 6 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 3abacc0..d6d6c94 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -20,7 +20,7 @@ #include #include #include - +#include #include #include #include @@ -1804,7 +1804,9 @@ static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo) madt_size = sizeof(struct acpi_table_madt) + sizeof(struct acpi_madt_generic_interrupt) * d->max_vcpus - + sizeof(struct acpi_madt_generic_distributor); + + sizeof(struct acpi_madt_generic_distributor) + + gicv3_its_madt_generic_translator_size(); + if ( d->arch.vgic.version == GIC_V3 ) madt_size += sizeof(struct acpi_madt_generic_redistributor) * d->arch.vgic.nr_regions; diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index 1fb06ca..937b970 100644 --- a/xen/arch/arm/gic-v3-its.c +++ b/xen/arch/arm/gic-v3-its.c @@ -25,14 +25,18 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include #define ITS_CMD_QUEUE_SZ SZ_1M - +#define ACPI_GICV3_ITS_MEM_SIZE (SZ_64K) /* * No lock here, as this list gets only populated upon boot while scanning * firmware tables for all host ITSes, and only gets iterated afterwards. @@ -920,6 +924,55 @@ int gicv3_lpi_change_vcpu(struct domain *d, paddr_t vdoorbell, return 0; } +int gicv3_its_deny_access(const struct domain *d) +{ + int rc = 0; + unsigned long mfn, nr; + const struct host_its *its_data; + + list_for_each_entry(its_data, &host_its_list, entry) + { + mfn = paddr_to_pfn(its_data->addr); + nr = PFN_UP(ACPI_GICV3_ITS_MEM_SIZE); + rc = iomem_deny_access(d, mfn, mfn + nr); + if ( rc ) + goto end; + } +end: + return rc; +} + +u32 gicv3_its_madt_generic_translator_size(void) +{ + const struct host_its *its_data; + u32 size = 0; + + list_for_each_entry(its_data, &host_its_list, entry) + { + size += sizeof(struct acpi_madt_generic_translator); + } + return size; +} + +u32 gicv3_its_make_hwdom_madt(u8 *base_ptr, u32 offset) +{ + struct acpi_madt_generic_translator *gic_its; + const struct host_its *its_data; + u32 table_len = offset, size; + + /* Update GIC ITS information in hardware domain's MADT */ + list_for_each_entry(its_data, &host_its_list, entry) + { + size = sizeof(struct acpi_madt_generic_translator); + gic_its = (struct acpi_madt_generic_translator *)(base_ptr + table_len); + gic_its->header.type = ACPI_MADT_TYPE_GENERIC_TRANSLATOR; + gic_its->header.length = size; + gic_its->base_address = its_data->addr; + table_len += size; + } + return table_len; +} + /* * Create the respective guest DT nodes from a list of host ITSes. * This copies the reg property, so the guest sees the ITS at the same address @@ -992,6 +1045,26 @@ int gicv3_its_make_hwdom_dt_nodes(const struct domain *d, return res; } +int gicv3_its_acpi_init(struct acpi_subtable_header *header, const unsigned long end) +{ + struct acpi_madt_generic_translator *its_entry; + struct host_its *its_data; + + its_data = xzalloc(struct host_its); + if (!its_data) + return -1; + + its_entry = (struct acpi_madt_generic_translator *)header; + its_data->addr = its_entry->base_address; + its_data->size = ACPI_GICV3_ITS_MEM_SIZE; + + spin_lock_init(&its_data->cmd_lock); + + printk("GICv3: Found ITS @0x%lx\n", its_data->addr); + + list_add_tail(&its_data->entry, &host_its_list); + return 0; +} /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */ void gicv3_its_dt_init(const struct dt_device_node *node) { diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index c927306..f0f6d12 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -1333,9 +1333,8 @@ static int gicv3_iomem_deny_access(const struct domain *d) return iomem_deny_access(d, mfn, mfn + nr); } - return 0; + return gicv3_its_deny_access(d); } - #ifdef CONFIG_ACPI static void __init gic_acpi_add_rdist_region(paddr_t base, paddr_t size, bool single_rdist) @@ -1374,6 +1373,7 @@ static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset) for ( i = 0; i < d->max_vcpus; i++ ) { gicc = (struct acpi_madt_generic_interrupt *)(base_ptr + table_len); + ACPI_MEMCPY(gicc, host_gicc, size); gicc->cpu_interface_number = i; gicc->uid = i; @@ -1399,7 +1399,7 @@ static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset) gicr->length = d->arch.vgic.rdist_regions[i].size; table_len += size; } - + table_len = gicv3_its_make_hwdom_madt(base_ptr, table_len); return table_len; } @@ -1567,6 +1567,9 @@ static void __init gicv3_acpi_init(void) gicv3.rdist_stride = 0; + acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR, + gicv3_its_acpi_init, 0); + /* * In ACPI, 0 is considered as the invalid address. However the rest * of the initialization rely on the invalid address to be @@ -1585,6 +1588,7 @@ static void __init gicv3_acpi_init(void) else vsize = GUEST_GICC_SIZE; + } #else static void __init gicv3_acpi_init(void) { } diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h index d2a3e53..b72aec2 100644 --- a/xen/include/asm-arm/gic_v3_its.h +++ b/xen/include/asm-arm/gic_v3_its.h @@ -105,6 +105,7 @@ #include #include +#include #define HOST_ITS_FLUSH_CMD_QUEUE (1U << 0) #define HOST_ITS_USES_PTA (1U << 1) @@ -134,6 +135,7 @@ extern struct list_head host_its_list; /* Parse the host DT and pick up all host ITSes. */ void gicv3_its_dt_init(const struct dt_device_node *node); +int gicv3_its_acpi_init(struct acpi_subtable_header *header, const unsigned long end); bool gicv3_its_host_has_its(void); @@ -167,6 +169,10 @@ int gicv3_its_make_hwdom_dt_nodes(const struct domain *d, const struct dt_device_node *gic, void *fdt); +u32 gicv3_its_make_hwdom_madt(u8 *base_ptr, u32 offset); +u32 gicv3_its_madt_generic_translator_size(void); +/* Deny iomem access for its */ +int gicv3_its_deny_access(const struct domain *d); /* * Map a device on the host by allocating an ITT on the host (ITS). * "nr_event" specifies how many events (interrupts) this device will need. -- 2.7.4 --------------981E190AD8FF54D8220C713F Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 7bit

This patch supports ITS in hardware domain, supports ITS in Xen
when booting with ACPI.

Signed-off-by: Manish Jaggi <mjaggi@cavium.com>
---
Changes since v1:
- Moved its specific code to gic-v3-its.c
- fixed macros

 xen/arch/arm/domain_build.c      |  6 ++--
 xen/arch/arm/gic-v3-its.c        | 75 +++++++++++++++++++++++++++++++++++++++-
 xen/arch/arm/gic-v3.c            | 10 ++++--
 xen/include/asm-arm/gic_v3_its.h |  6 ++++
 4 files changed, 91 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 3abacc0..d6d6c94 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -20,7 +20,7 @@
 #include <asm/psci.h>
 #include <asm/setup.h>
 #include <asm/cpufeature.h>
-
+#include <asm-arm/gic_v3_its.h>
 #include <asm/gic.h>
 #include <xen/irq.h>
 #include <xen/grant_table.h>
@@ -1804,7 +1804,9 @@ static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo)
 
     madt_size = sizeof(struct acpi_table_madt)
                 + sizeof(struct acpi_madt_generic_interrupt) * d->max_vcpus
-                + sizeof(struct acpi_madt_generic_distributor);
+                + sizeof(struct acpi_madt_generic_distributor)
+                + gicv3_its_madt_generic_translator_size();
+
     if ( d->arch.vgic.version == GIC_V3 )
         madt_size += sizeof(struct acpi_madt_generic_redistributor)
                      * d->arch.vgic.nr_regions;
diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 1fb06ca..937b970 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -25,14 +25,18 @@
 #include <xen/rbtree.h>
 #include <xen/sched.h>
 #include <xen/sizes.h>
+#include <xen/iocap.h>
 #include <asm/gic.h>
 #include <asm/gic_v3_defs.h>
 #include <asm/gic_v3_its.h>
 #include <asm/io.h>
 #include <asm/page.h>
+#include <xen/acpi.h>
+#include <acpi/actables.h>
+#include <xen/pfn.h>
 
 #define ITS_CMD_QUEUE_SZ                SZ_1M
-
+#define ACPI_GICV3_ITS_MEM_SIZE (SZ_64K)
 /*
  * No lock here, as this list gets only populated upon boot while scanning
  * firmware tables for all host ITSes, and only gets iterated afterwards.
@@ -920,6 +924,55 @@ int gicv3_lpi_change_vcpu(struct domain *d, paddr_t vdoorbell,
     return 0;
 }
 
+int gicv3_its_deny_access(const struct domain *d)
+{
+    int rc = 0;
+    unsigned long mfn, nr;
+    const struct host_its *its_data;
+
+    list_for_each_entry(its_data, &host_its_list, entry)
+    {
+        mfn = paddr_to_pfn(its_data->addr);
+        nr = PFN_UP(ACPI_GICV3_ITS_MEM_SIZE);
+        rc = iomem_deny_access(d, mfn, mfn + nr);
+        if ( rc )
+            goto end;
+    }
+end:
+    return rc;
+}
+
+u32 gicv3_its_madt_generic_translator_size(void)
+{
+    const struct host_its *its_data;
+    u32 size = 0;
+
+    list_for_each_entry(its_data, &host_its_list, entry)
+    {
+        size += sizeof(struct acpi_madt_generic_translator);
+    }
+    return size;
+}
+
+u32 gicv3_its_make_hwdom_madt(u8 *base_ptr, u32 offset)
+{
+    struct acpi_madt_generic_translator *gic_its;
+    const struct host_its *its_data;
+    u32 table_len = offset, size;
+
+    /* Update GIC ITS information in hardware domain's MADT */
+    list_for_each_entry(its_data, &host_its_list, entry)
+    {
+        size = sizeof(struct acpi_madt_generic_translator);
+        gic_its = (struct acpi_madt_generic_translator *)(base_ptr + table_len);
+        gic_its->header.type = ACPI_MADT_TYPE_GENERIC_TRANSLATOR;
+        gic_its->header.length = size;
+        gic_its->base_address = its_data->addr;
+        table_len +=  size;
+    }
+    return table_len;
+}
+
 /*
  * Create the respective guest DT nodes from a list of host ITSes.
  * This copies the reg property, so the guest sees the ITS at the same address
@@ -992,6 +1045,26 @@ int gicv3_its_make_hwdom_dt_nodes(const struct domain *d,
     return res;
 }
 
+int gicv3_its_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
+{
+    struct acpi_madt_generic_translator *its_entry;
+    struct host_its *its_data;
+
+    its_data = xzalloc(struct host_its);
+    if (!its_data)
+        return -1;
+
+    its_entry = (struct acpi_madt_generic_translator *)header;
+    its_data->addr  = its_entry->base_address;
+    its_data->size = ACPI_GICV3_ITS_MEM_SIZE;
+
+    spin_lock_init(&its_data->cmd_lock);
+
+    printk("GICv3: Found ITS @0x%lx\n", its_data->addr);
+
+    list_add_tail(&its_data->entry, &host_its_list);
+    return 0;
+}
 /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */
 void gicv3_its_dt_init(const struct dt_device_node *node)
 {
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index c927306..f0f6d12 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1333,9 +1333,8 @@ static int gicv3_iomem_deny_access(const struct domain *d)
         return iomem_deny_access(d, mfn, mfn + nr);
     }
 
-    return 0;
+    return gicv3_its_deny_access(d);
 }
-
 #ifdef CONFIG_ACPI
 static void __init
 gic_acpi_add_rdist_region(paddr_t base, paddr_t size, bool single_rdist)
@@ -1374,6 +1373,7 @@ static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
     for ( i = 0; i < d->max_vcpus; i++ )
     {
         gicc = (struct acpi_madt_generic_interrupt *)(base_ptr + table_len);
+
         ACPI_MEMCPY(gicc, host_gicc, size);
         gicc->cpu_interface_number = i;
         gicc->uid = i;
@@ -1399,7 +1399,7 @@ static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
         gicr->length = d->arch.vgic.rdist_regions[i].size;
         table_len += size;
     }
-
+    table_len = gicv3_its_make_hwdom_madt(base_ptr, table_len);
     return table_len;
 }
 
@@ -1567,6 +1567,9 @@ static void __init gicv3_acpi_init(void)
 
     gicv3.rdist_stride = 0;
 
+    acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
+                          gicv3_its_acpi_init, 0);
+
     /*
      * In ACPI, 0 is considered as the invalid address. However the rest
      * of the initialization rely on the invalid address to be
@@ -1585,6 +1588,7 @@ static void __init gicv3_acpi_init(void)
     else
         vsize = GUEST_GICC_SIZE;
 
+
 }
 #else
 static void __init gicv3_acpi_init(void) { }
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
index d2a3e53..b72aec2 100644
--- a/xen/include/asm-arm/gic_v3_its.h
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -105,6 +105,7 @@
 
 #include <xen/device_tree.h>
 #include <xen/rbtree.h>
+#include <xen/acpi.h>
 
 #define HOST_ITS_FLUSH_CMD_QUEUE        (1U << 0)
 #define HOST_ITS_USES_PTA               (1U << 1)
@@ -134,6 +135,7 @@ extern struct list_head host_its_list;
 
 /* Parse the host DT and pick up all host ITSes. */
 void gicv3_its_dt_init(const struct dt_device_node *node);
+int  gicv3_its_acpi_init(struct acpi_subtable_header *header, const unsigned long end);
 
 bool gicv3_its_host_has_its(void);
 
@@ -167,6 +169,10 @@ int gicv3_its_make_hwdom_dt_nodes(const struct domain *d,
                                   const struct dt_device_node *gic,
                                   void *fdt);
 
+u32 gicv3_its_make_hwdom_madt(u8 *base_ptr, u32 offset);
+u32 gicv3_its_madt_generic_translator_size(void);
+/* Deny iomem access for its */
+int gicv3_its_deny_access(const struct domain *d);
 /*
  * Map a device on the host by allocating an ITT on the host (ITS).
  * "nr_event" specifies how many events (interrupts) this device will need.
-- 
2.7.4


--------------981E190AD8FF54D8220C713F-- --===============5229546472150650745== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczovL2xpc3RzLnhlbi5v cmcveGVuLWRldmVsCg== --===============5229546472150650745==--