[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] xen/arm: Preserve host GIC #interrupt-cells for Dom0



Xen copies device interrupt properties from the host device tree to
Dom0, but hardcodes #interrupt-cells to 3 in make_gic_node() and
fdt_property_interrupts(). On GICv3 platforms where the host uses 4
cells, Dom0 parses the copied specifiers as 3 cells each and fails to
set up device interrupts.

Propagate #interrupt-cells from the host GIC node in make_gic_node()
and pad Dom0 interrupt specifiers with trailing zero cells in
fdt_property_interrupts().

Signed-off-by: Kuan-Wei Chiu <visitorckw@xxxxxxxxx>
---
 xen/arch/arm/domain_build.c | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 1ee1f1f6a7..74d2491f9e 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -654,12 +654,30 @@ static int __init fdt_property_interrupts(const struct 
kernel_info *kinfo,
                                           unsigned int num_irq)
 {
     int res;
+    uint32_t intrcells = ARRAY_SIZE(intr[0]);
+    void *val;
+    unsigned int i, stride;
 
-    res = fdt_property(kinfo->fdt, "interrupts",
-                       intr, sizeof(intr[0]) * num_irq);
+    if ( is_hardware_domain(kinfo->bd.d) )
+    {
+        const struct dt_device_node *gic = dt_interrupt_controller;
+
+        if ( !dt_property_read_u32(gic, "#interrupt-cells", &intrcells) )
+            return -FDT_ERR_XEN(ENOENT);
+        if ( intrcells < ARRAY_SIZE(intr[0]) )
+            return -FDT_ERR_XEN(ERANGE);
+    }
+
+    stride = intrcells * sizeof(intr[0][0]);
+    res = fdt_property_placeholder(kinfo->fdt, "interrupts",
+                                   stride * num_irq, &val);
     if ( res )
         return res;
 
+    memset(val, 0, stride * num_irq);
+    for ( i = 0; i < num_irq; i++ )
+        memcpy((uint8_t *)val + i * stride, intr[i], sizeof(intr[0]));
+
     res = fdt_property_cell(kinfo->fdt, "interrupt-parent",
                             kinfo->phandle_intc);
 
@@ -1320,6 +1338,7 @@ static int __init make_gic_node(const struct domain *d, 
void *fdt,
     int res = 0;
     const void *addrcells, *sizecells;
     u32 addrcells_len, sizecells_len;
+    uint32_t intrcells;
     const char *name;
 
     /*
@@ -1370,7 +1389,12 @@ static int __init make_gic_node(const struct domain *d, 
void *fdt,
             return res;
     }
 
-    res = fdt_property_cell(fdt, "#interrupt-cells", 3);
+    if ( !dt_property_read_u32(gic, "#interrupt-cells", &intrcells) )
+        return -FDT_ERR_XEN(ENOENT);
+    if ( intrcells < 3 )
+        return -FDT_ERR_XEN(ERANGE);
+
+    res = fdt_property_cell(fdt, "#interrupt-cells", intrcells);
     if ( res )
         return res;
 
-- 
2.56.0.385.gac671c819a-goog




 


Rackspace

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