]> xenbits.xensource.com Git - people/gdunlap/xen.git/commitdiff
xen/arm: Handle translated addresses for hardware domains in GICv2
authorFrediano Ziglio <frediano.ziglio@huawei.com>
Fri, 27 Feb 2015 14:08:06 +0000 (14:08 +0000)
committerIan Campbell <ian.campbell@citrix.com>
Mon, 2 Mar 2015 14:07:39 +0000 (14:07 +0000)
Translated addresses (in d->arch.vgic.{c,d}base) are bus addresses
which are not always correct in the context of a subnode in the DTB
exposed to domain 0 since they would then be subject to retranslation.

Copy the original addresses from DT directly to get the original
untranslated reg property which will give same d->arch.vgic.{c,d}base
values once translated again by the guest.

Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
[ ijc -- attempt to clarify the commit message ]

xen/arch/arm/gic-v2.c

index e551549125ae8a88e282bbde85748e47bcca67a4..3e141c462434d3c9b7417d43bc1a0e4897d42575 100644 (file)
@@ -604,7 +604,7 @@ static int gicv2_make_dt_node(const struct domain *d,
     const struct dt_device_node *gic = dt_interrupt_controller;
     const void *compatible = NULL;
     u32 len;
-    __be32 *new_cells, *tmp;
+    const __be32 *regs;
     int res = 0;
 
     compatible = dt_get_property(gic, "compatible", &len);
@@ -631,18 +631,22 @@ static int gicv2_make_dt_node(const struct domain *d,
     if ( res )
         return res;
 
-    len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node));
-    len *= 2; /* GIC has two memory regions: Distributor + CPU interface */
-    new_cells = xzalloc_bytes(len);
-    if ( new_cells == NULL )
-        return -FDT_ERR_XEN(ENOMEM);
+    /*
+     * DTB provides up to 4 regions to handle virtualization
+     * (in order GICD, GICC, GICH and GICV interfaces)
+     * however dom0 just needs GICD and GICC provided by Xen.
+     */
+    regs = dt_get_property(gic, "reg", &len);
+    if ( !regs )
+    {
+        dprintk(XENLOG_ERR, "Can't find reg property for the gic node\n");
+        return -FDT_ERR_XEN(ENOENT);
+    }
 
-    tmp = new_cells;
-    dt_set_range(&tmp, node, d->arch.vgic.dbase, PAGE_SIZE);
-    dt_set_range(&tmp, node, d->arch.vgic.cbase, PAGE_SIZE * 2);
+    len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node));
+    len *= 2;
 
-    res = fdt_property(fdt, "reg", new_cells, len);
-    xfree(new_cells);
+    res = fdt_property(fdt, "reg", regs, len);
 
     return res;
 }