|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |