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

[Xen-devel] [PATCH 2/2] xen/arm: gicv2: Adding support for GICv2m in Dom0



This patch detect and propagate the gic-v2m-frame devicetree sub-node.
This allows Dom0 kernel to setup and intialize GICv2m MSI frame.

Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@xxxxxxx>
---
 xen/arch/arm/gic-v2.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index 80acc62..0c3352e 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -600,6 +600,171 @@ static void gicv2_irq_set_affinity(struct irq_desc *desc, 
const cpumask_t *cpu_m
     spin_unlock(&gicv2.lock);
 }
 
+/*
+ * Set up gic v2m DT sub-node.
+ *
+ * gic0: interrupt-controller@e1101000 {
+ *          compatible = "arm,gic-400", "arm,cortex-a15-gic";
+ *          interrupt-controller;
+ *          #interrupt-cells = <3>;
+ *          #address-cells = <2>;
+ *          #size-cells = <2>;
+ *          reg = <0x0 0xe1110000 0 0x1000>,
+ *                <0x0 0xe112f000 0 0x2000>,
+ *                <0x0 0xe1140000 0 0x10000>,
+ *                <0x0 0xe1160000 0 0x10000>;
+ *          interrupts = <1 9 0xf04>;
+ *          ranges = <0 0 0 0xe1100000 0 0x100000>;
+ *          v2m0: v2m@e0080000 {
+ *                  compatible = "arm,gic-v2m-frame";
+ *                  msi-controller;
+ *                  arm,msi-base-spi = <64>;
+ *                  arm,msi-num-spis = <256>;
+ *                  reg = <0x0 0x00080000 0 0x1000>;
+ *          };
+ * };
+ */
+static int gicv2m_make_dt_node(const struct domain *d,
+                              const struct dt_device_node *node,
+                              void *fdt)
+{
+    u32 len, base_spi, num_spis;
+    u64 addr, size;
+    int res, i;
+    const void *prop = NULL;
+    struct domain *dom;
+    unsigned long mm_start, mm_nr;
+    const struct dt_device_node *gic = dt_interrupt_controller;
+    const struct dt_device_node *v2m = NULL;
+
+    /* v2m is optional */
+    v2m = dt_find_compatible_node(NULL, NULL, "arm,gic-v2m-frame");
+    if ( !v2m )
+        return 0;
+
+    /* Sub-node requires the ranges property */
+    prop = dt_get_property(gic, "ranges", &len);
+    if ( !prop )
+    {
+        dprintk(XENLOG_ERR, "Can't find ranges property for the gic node\n");
+        return -FDT_ERR_XEN(ENOENT);
+    }
+
+    res = fdt_property(fdt, "ranges", prop, len);
+    if ( res )
+        return res;
+
+    dprintk(XENLOG_DEBUG, "Create v2m node\n");
+
+    res = fdt_begin_node(fdt, "v2m");
+    if ( res )
+        return res;
+
+    res = fdt_property(fdt, "compatible", "arm,gic-v2m-frame", 18);
+    if ( res )
+        goto err_out0;
+
+    res = fdt_property(fdt, "msi-controller", NULL, 0);
+    if ( res )
+        goto err_out0;
+
+    if ( v2m->phandle )
+    {
+        res = fdt_property_cell(fdt, "phandle", v2m->phandle);
+        if ( res )
+            goto err_out0;
+    }
+
+    prop = dt_get_property(v2m, "reg", &len);
+    if ( !prop )
+    {
+        dprintk(XENLOG_ERR, "v2m: Can't find reg property.\n");
+        res = -FDT_ERR_XEN(ENOENT);
+        goto err_out0;
+    }
+
+    len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node));
+    res = fdt_property(fdt, "reg", prop, len);
+    if ( res )
+        goto err_out0;
+
+    /* Mapping MMIO regions for v2m frame */
+    res = dt_device_get_address(v2m, 0, &addr, &size);
+    if ( res )
+        goto err_out0;
+
+    dom = xzalloc_bytes(sizeof(struct domain));
+    if ( !dom )
+    {
+        res = -ENOMEM;
+        goto err_out0;
+    }
+
+    memcpy(dom, d, sizeof(struct domain));
+    mm_start = paddr_to_pfn(addr & PAGE_MASK);
+    mm_nr = DIV_ROUND_UP(size, PAGE_SIZE);
+    res = map_mmio_regions(dom, mm_start, mm_nr, mm_start);
+    if ( res )
+    {
+        dprintk(XENLOG_ERR, "v2m: map_mmio_regions failed.\n");
+        goto err_out1;
+    }
+
+    /* Set up msi-base-spi dt property */
+    prop = dt_get_property(v2m, "arm,msi-base-spi", &len);
+    if ( !prop )
+    {
+        dprintk(XENLOG_ERR, "v2m: Can't find msi-base-spi.\n");
+        goto err_out2;
+    }
+    base_spi = be32_to_cpup(prop);
+    res = fdt_property(fdt, "arm,msi-base-spi", prop, len);
+    if ( res )
+        goto err_out2;
+
+    /* Set up msi-num-spis dt property */
+    prop = dt_get_property(v2m, "arm,msi-num-spis", &len);
+    if ( !prop )
+    {
+        dprintk(XENLOG_ERR, "v2m: Can't find msi-num-spis.\n");
+        goto err_out2;
+    }
+    num_spis = be32_to_cpup(prop);
+    res = fdt_property(fdt, "arm,msi-num-spis", prop, len);
+    if ( res )
+        goto err_out2;
+
+    /*
+     * Currently, we assign all SPIs for MSI to dom0
+     */
+    for (i = base_spi; i < (base_spi + num_spis); i++)
+    {
+        res = irq_set_spi_type(i, DT_IRQ_TYPE_EDGE_RISING);
+        if ( res )
+        {
+            dprintk(XENLOG_ERR, "v2m: Failed to set MSI interrupt type.\n");
+            goto err_out2;
+        }
+
+        res = route_irq_to_guest(dom, i, i, "v2m");
+        if ( res )
+        {
+            dprintk(XENLOG_ERR, "v2m: Failed to route MSI irqs to guest.\n");
+            goto err_out2;
+        }
+    }
+
+    return fdt_end_node(fdt);
+
+err_out2:
+    unmap_mmio_regions(dom, mm_start, mm_nr, mm_start);
+err_out1:
+    xfree(dom);
+err_out0:
+    fdt_end_node(fdt);
+    return res;
+}
+
 static int gicv2_make_dt_node(const struct domain *d,
                               const struct dt_device_node *node, void *fdt)
 {
@@ -636,6 +801,10 @@ static int gicv2_make_dt_node(const struct domain *d,
     len *= 2;
 
     res = fdt_property(fdt, "reg", regs, len);
+    if ( res )
+        return res;
+
+    res = gicv2m_make_dt_node(d, node, fdt);
 
     return res;
 }
-- 
2.1.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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