]> rtime.felk.cvut.cz Git - jailhouse.git/blobdiff - hypervisor/arch/arm/gic-v2.c
arm: Remove SPI target reset on cell destruction
[jailhouse.git] / hypervisor / arch / arm / gic-v2.c
index e47c1424eb1cc692f43f3ad88bd0d3a12c1ed70a..9d1d311ef49e2aa7169680da8e4015a316efafac 100644 (file)
@@ -76,11 +76,18 @@ static int gic_cpu_reset(struct per_cpu *cpu_data, bool is_shutdown)
                        mmio_write32(gicc_base + GICC_DIR, i);
        }
 
-       /* Disable PPIs if necessary */
-       if (!root_shutdown)
-               mmio_write32(gicd_base + GICD_ICENABLER, 0xffff0000);
-       /* Ensure IPIs are enabled */
-       mmio_write32(gicd_base + GICD_ISENABLER, 0x0000ffff);
+       /* Ensure all IPIs and the maintenance PPI are enabled */
+       mmio_write32(gicd_base + GICD_ISENABLER,
+                    0x0000ffff | (1 << MAINTENANCE_IRQ));
+
+       /*
+        * Disable PPIs, except for the maintenance interrupt.
+        * On shutdown, the root cell expects to find all its PPIs still
+        * enabled - except for the maintenance interrupt we used.
+        */
+       mmio_write32(gicd_base + GICD_ICENABLER,
+                    root_shutdown ? 1 << MAINTENANCE_IRQ :
+                                    0xffff0000 & ~(1 << MAINTENANCE_IRQ));
 
        if (is_shutdown)
                mmio_write32(gich_base + GICH_HCR, 0);
@@ -110,8 +117,9 @@ static int gic_cpu_init(struct per_cpu *cpu_data)
        u32 vtr, vmcr;
        u32 cell_gicc_ctlr, cell_gicc_pmr;
 
-       /* Ensure all IPIs are enabled */
-       mmio_write32(gicd_base + GICD_ISENABLER, 0x0000ffff);
+       /* Ensure all IPIs and the maintenance PPI are enabled. */
+       mmio_write32(gicd_base + GICD_ISENABLER,
+                    0x0000ffff | (1 << MAINTENANCE_IRQ));
 
        cell_gicc_ctlr = mmio_read32(gicc_base + GICC_CTLR);
        cell_gicc_pmr = mmio_read32(gicc_base + GICC_PMR);
@@ -208,8 +216,6 @@ static void gic_cell_exit(struct cell *cell)
 {
        paging_destroy(&cell->arch.mm, (unsigned long)gicc_base, gicc_size,
                       PAGING_NON_COHERENT);
-       /* Reset interrupt routing of the cell's spis */
-       gic_target_spis(cell, &root_cell);
 }
 
 static int gic_send_sgi(struct sgi *sgi)
@@ -228,7 +234,7 @@ static int gic_send_sgi(struct sgi *sgi)
        return 0;
 }
 
-static int gic_inject_irq(struct per_cpu *cpu_data, struct pending_irq *irq)
+static int gic_inject_irq(struct per_cpu *cpu_data, u16 irq_id)
 {
        int i;
        int first_free = -1;
@@ -247,20 +253,20 @@ static int gic_inject_irq(struct per_cpu *cpu_data, struct pending_irq *irq)
 
                /* Check that there is no overlapping */
                lr = gic_read_lr(i);
-               if ((lr & GICH_LR_VIRT_ID_MASK) == irq->virt_id)
-                       return -EINVAL;
+               if ((lr & GICH_LR_VIRT_ID_MASK) == irq_id)
+                       return -EEXIST;
        }
 
        if (first_free == -1)
                return -EBUSY;
 
        /* Inject group 0 interrupt (seen as IRQ by the guest) */
-       lr = irq->virt_id;
+       lr = irq_id;
        lr |= GICH_LR_PENDING_BIT;
 
-       if (!is_sgi(irq->virt_id)) {
+       if (!is_sgi(irq_id)) {
                lr |= GICH_LR_HW_BIT;
-               lr |= irq->virt_id << GICH_LR_PHYS_ID_SHIFT;
+               lr |= (u32)irq_id << GICH_LR_PHYS_ID_SHIFT;
        }
 
        gic_write_lr(first_free, lr);
@@ -280,12 +286,19 @@ static void gic_enable_maint_irq(bool enable)
        mmio_write32(gich_base + GICH_HCR, hcr);
 }
 
+enum mmio_result gic_handle_irq_route(struct mmio_access *mmio,
+                                     unsigned int irq)
+{
+       /* doesn't exist in v2 - ignore access */
+       return MMIO_HANDLED;
+}
+
 unsigned int irqchip_mmio_count_regions(struct cell *cell)
 {
        return 1;
 }
 
-struct irqchip_ops gic_irqchip = {
+struct irqchip_ops irqchip = {
        .init = gic_init,
        .cpu_init = gic_cpu_init,
        .cpu_reset = gic_cpu_reset,