[Xen-devel,v3,8/9] xen/arm: acpi: route all unused IRQs to DOM0

Message ID 1469627910-3902-9-git-send-email-julien.grall@arm.com
State New
Headers show

Commit Message

Julien Grall July 27, 2016, 1:58 p.m.
It is not possible to know which IRQs will be used by DOM0 when ACPI is
inuse. The approach implemented by this patch, will route all unused
IRQs to DOM0 before it has booted.

The number of IRQs routed is based on the maximum SPIs supported by the
hardware (up to ~1000). However, some of them might not be wired. So we
would allocate resource for nothing.

For each IRQ routed, Xen is allocating memory for irqaction (40 bytes)
and irq_guest (16 bytes). So in the worst case scenario ~54KB of memory
will be allocated. Given that ACPI will mostly be used by server, I
think it is a small drawback.

map_irq_to_domain is slightly reworked to remove the dependency on
device-tree. So the function can be also be used for ACPI and will
avoid code duplication.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Tested-by: Shanker Donthineni <shankerd@codeaurora.org>

---
    Changes in v3:
        - Add Stefano's reviewed-by
        - Tested by Shanker on QDF2XXX server

    Changes in v2:
        - Rename acpi_permit_spi_access to acpi_route_spis
        - Update the comment in the function acpi_route_spis
---
 xen/arch/arm/domain_build.c | 28 ++++++++++++----------------
 1 file changed, 12 insertions(+), 16 deletions(-)

Patch

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 60db9e4..5b2f8ad 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -903,11 +903,10 @@  static int make_timer_node(const struct domain *d, void *fdt,
     return res;
 }
 
-static int map_irq_to_domain(const struct dt_device_node *dev,
-                             struct domain *d, unsigned int irq)
+static int map_irq_to_domain(struct domain *d, unsigned int irq,
+                             bool_t need_mapping, const char *devname)
 
 {
-    bool_t need_mapping = !dt_device_for_passthrough(dev);
     int res;
 
     res = irq_permit_access(d, irq);
@@ -927,7 +926,7 @@  static int map_irq_to_domain(const struct dt_device_node *dev,
          */
         vgic_reserve_virq(d, irq);
 
-        res = route_irq_to_guest(d, irq, irq, dt_node_name(dev));
+        res = route_irq_to_guest(d, irq, irq, devname);
         if ( res < 0 )
         {
             printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
@@ -947,6 +946,7 @@  static int map_dt_irq_to_domain(const struct dt_device_node *dev,
     struct domain *d = data;
     unsigned int irq = dt_irq->irq;
     int res;
+    bool_t need_mapping = !dt_device_for_passthrough(dev);
 
     if ( irq < NR_LOCAL_IRQS )
     {
@@ -965,7 +965,7 @@  static int map_dt_irq_to_domain(const struct dt_device_node *dev,
         return res;
     }
 
-    res = map_irq_to_domain(dev, d, irq);
+    res = map_irq_to_domain(d, irq, need_mapping, dt_node_name(dev));
 
     return 0;
 }
@@ -1103,7 +1103,7 @@  static int handle_device(struct domain *d, struct dt_device_node *dev)
             return res;
         }
 
-        res = map_irq_to_domain(dev, d, res);
+        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
         if ( res )
             return res;
     }
@@ -1343,15 +1343,14 @@  static int acpi_iomem_deny_access(struct domain *d)
     return gic_iomem_deny_access(d);
 }
 
-static int acpi_permit_spi_access(struct domain *d)
+static int acpi_route_spis(struct domain *d)
 {
     int i, res;
     struct irq_desc *desc;
 
     /*
-     * Here just permit Dom0 to access the SPIs which Xen doesn't use. Then when
-     * Dom0 configures the interrupt, set the interrupt type and route it to
-     * Dom0.
+     * Route the IRQ to hardware domain and permit the access.
+     * The interrupt type will be set by set by the hardware domain.
      */
     for( i = NR_LOCAL_IRQS; i < vgic_num_irqs(d); i++ )
     {
@@ -1362,13 +1361,10 @@  static int acpi_permit_spi_access(struct domain *d)
         if ( desc->action != NULL)
             continue;
 
-        res = irq_permit_access(d, i);
+        /* XXX: Shall we use a proper devname? */
+        res = map_irq_to_domain(d, i, true, "ACPI");
         if ( res )
-        {
-            printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
-                   d->domain_id, i);
             return res;
-        }
     }
 
     return 0;
@@ -1902,7 +1898,7 @@  static int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
     if ( rc != 0 )
         return rc;
 
-    rc = acpi_permit_spi_access(d);
+    rc = acpi_route_spis(d);
     if ( rc != 0 )
         return rc;