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.
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;
}
}
+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 = {};
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. */
return (dt_match_node(blacklist, node) != NULL);
}
-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 )