@@ -542,13 +542,18 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
if ( (rc = domain_vtimer_init(d)) != 0 )
goto fail;
- if ( d->domain_id )
+ /*
+ * The hardware domain will get a PPI later in
+ * arch/arm/domain_build.c depending on the
+ * interrupt map of the hardware.
+ */
+ if ( !is_hardware_domain(d) )
+ {
d->arch.evtchn_irq = GUEST_EVTCHN_PPI;
- else
- d->arch.evtchn_irq = platform_dom0_evtchn_ppi();
-
- if ( !vgic_reserve_virq(d, d->arch.evtchn_irq) )
- BUG();
+ /* At this stage vgic_reserve_virq should never fail */
+ if ( !vgic_reserve_virq(d, GUEST_EVTCHN_PPI) )
+ BUG();
+ }
/*
* Virtual UART is only used by linux early printk and decompress code.
@@ -627,16 +627,10 @@ static int make_hypervisor_node(struct domain *d,
return res;
/*
- * interrupts is evtchn upcall:
- * - Active-low level-sensitive
- * - All cpus
- *
- * TODO: Handle correctly the cpumask
+ * Placeholder for the event channel interrupt. The values will be
+ * replaced later.
*/
- DPRINT(" Event channel interrupt to %u\n", d->arch.evtchn_irq);
- set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf,
- DT_IRQ_TYPE_LEVEL_LOW);
-
+ set_interrupt_ppi(intr, ~0, 0xf, DT_IRQ_TYPE_INVALID);
res = fdt_property_interrupts(fdt, &intr, 1);
if ( res )
return res;
@@ -1277,6 +1271,43 @@ static void initrd_load(struct kernel_info *kinfo)
}
}
+static void evtchn_fixup(struct domain *d, struct kernel_info *kinfo)
+{
+ int res, node;
+ gic_interrupt_t intr;
+
+ /*
+ * The allocation of the event channel IRQ has been deferred until
+ * now. At this time, all PPIs used by DOM0 have been registered.
+ */
+ res = vgic_allocate_ppi(d);
+ if ( res < 0 )
+ panic("Unable to allocate a PPI for the event channel interrupt\n");
+
+ d->arch.evtchn_irq = res;
+
+ printk("Allocating PPI %u for event channel interrupt\n",
+ d->arch.evtchn_irq);
+
+ /* Fix up "interrupts" in /hypervisor node */
+ node = fdt_path_offset(kinfo->fdt, "/hypervisor");
+ if ( node < 0 )
+ panic("Cannot find the /hypervisor node");
+
+ /* Interrupt event channel upcall:
+ * - Active-low level-sensitive
+ * - All CPUs
+ *
+ * TODO: Handle properly the cpumask
+ */
+ set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf,
+ DT_IRQ_TYPE_LEVEL_LOW);
+ res = fdt_setprop_inplace(kinfo->fdt, node, "interrupts",
+ &intr, sizeof(intr));
+ if ( res )
+ panic("Cannot fix up \"interrupts\" property of the hypervisor node");
+}
+
int construct_dom0(struct domain *d)
{
struct kernel_info kinfo = {};
@@ -1338,6 +1369,8 @@ int construct_dom0(struct domain *d)
kernel_load(&kinfo);
/* initrd_load will fix up the fdt, so call it before dtb_load */
initrd_load(&kinfo);
+ /* Allocate the event channel IRQ and fix up the device tree */
+ evtchn_fixup(d, &kinfo);
dtb_load(&kinfo);
/* Now that we are done restore the original p2m and current. */
@@ -160,13 +160,6 @@ bool_t platform_device_is_blacklisted(const struct dt_device_node *node)
return dt_match_node(blacklist, node);
}
-unsigned int platform_dom0_evtchn_ppi(void)
-{
- if ( platform && platform->dom0_evtchn_ppi )
- return platform->dom0_evtchn_ppi;
- return GUEST_EVTCHN_PPI;
-}
-
void platform_dom0_gnttab(paddr_t *start, paddr_t *size)
{
if ( platform && platform->dom0_gnttab_size )
@@ -232,7 +232,6 @@ PLATFORM_START(xgene_storm, "APM X-GENE STORM")
.quirks = xgene_storm_quirks,
.specific_mapping = xgene_storm_specific_mapping,
- .dom0_evtchn_ppi = 24,
.dom0_gnttab_start = 0x1f800000,
.dom0_gnttab_size = 0x20000,
PLATFORM_END
@@ -38,10 +38,6 @@ struct platform_desc {
*/
const struct dt_device_match *blacklist_dev;
/*
- * The IRQ (PPI) to use to inject event channels to dom0.
- */
- unsigned int dom0_evtchn_ppi;
- /*
* The location of a region of physical address space which dom0
* can use for grant table mappings. If size is zero defaults to
* 0xb0000000-0xb0020000.