]> rtime.felk.cvut.cz Git - jailhouse.git/blobdiff - hypervisor/arch/arm/gic-common.c
arm: Rework spi_in_cell to irqchip_irq_in_cell
[jailhouse.git] / hypervisor / arch / arm / gic-common.c
index a8ac4c7efb1ffe052f80597ff5ae879e3640d29b..ab405e52577fdaa953cd380eb265ea3467756dfc 100644 (file)
@@ -57,14 +57,9 @@ restrict_bitmask_access(struct mmio_access *mmio, unsigned int reg_index,
        /* First, extract the first interrupt affected by this access */
        unsigned int first_irq = reg_index * irqs_per_reg;
 
-       for (irq = first_irq; irq < first_irq + irqs_per_reg; irq++) {
-               unsigned int bit_nr = (irq - first_irq) * bits_per_irq;
-
-               if ((is_spi(irq) && spi_in_cell(cell, irq - 32)) ||
-                   irq == SGI_INJECT || irq == SGI_CPU_OFF ||
-                   irq == MAINTENANCE_IRQ)
-                       access_mask |= irq_bits << bit_nr;
-       }
+       for (irq = 0; irq < irqs_per_reg; irq++)
+               if (irqchip_irq_in_cell(cell, first_irq + irq))
+                       access_mask |= irq_bits << (irq * bits_per_irq);
 
        if (!mmio->is_write) {
                /* Restrict the read value */
@@ -100,51 +95,11 @@ restrict_bitmask_access(struct mmio_access *mmio, unsigned int reg_index,
        return MMIO_HANDLED;
 }
 
-/*
- * GICv3 uses a 64bit register IROUTER for each IRQ
- */
-static enum mmio_result handle_irq_route(struct mmio_access *mmio,
-                                        unsigned int irq)
-{
-       struct cell *cell = this_cell();
-       unsigned int cpu;
-
-       /* Ignore aff3 on AArch32 (return 0) */
-       if (mmio->size == 4 && (mmio->address % 8))
-               return MMIO_HANDLED;
-
-       /* SGIs and PPIs are res0 */
-       if (!is_spi(irq))
-               return MMIO_HANDLED;
-
-       /*
-        * Ignore accesses to SPIs that do not belong to the cell. This isn't
-        * forbidden, because the guest driver may simply iterate over all
-        * registers at initialisation
-        */
-       if (!spi_in_cell(cell, irq - 32))
-               return MMIO_HANDLED;
-
-       /* Translate the virtual cpu id into the physical one */
-       if (mmio->is_write) {
-               mmio->value = arm_cpu_virt2phys(cell, mmio->value);
-               if (mmio->value == -1) {
-                       printk("Attempt to route IRQ%d outside of cell\n", irq);
-                       return MMIO_ERROR;
-               }
-               mmio_perform_access(gicd_base, mmio);
-       } else {
-               cpu = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq);
-               mmio->value = arm_cpu_phys2virt(cpu);
-       }
-       return MMIO_HANDLED;
-}
-
 /*
  * GICv2 uses 8bit values for each IRQ in the ITARGETRs registers
  */
 static enum mmio_result handle_irq_target(struct mmio_access *mmio,
-                                         unsigned int reg)
+                                         unsigned int irq)
 {
        /*
         * ITARGETSR contain one byte per IRQ, so the first one affected by this
@@ -152,7 +107,6 @@ static enum mmio_result handle_irq_target(struct mmio_access *mmio,
         */
        struct cell *cell = this_cell();
        unsigned int i, cpu;
-       unsigned int spi = reg - 32;
        unsigned int offset;
        u32 access_mask = 0;
        u8 targets;
@@ -161,22 +115,22 @@ static enum mmio_result handle_irq_target(struct mmio_access *mmio,
         * Let the guest freely access its SGIs and PPIs, which may be used to
         * fill its CPU interface map.
         */
-       if (!is_spi(reg)) {
+       if (!is_spi(irq)) {
                mmio_perform_access(gicd_base, mmio);
                return MMIO_HANDLED;
        }
 
        /*
-        * The registers are byte-accessible, extend the access to a word if
-        * necessary.
+        * The registers are byte-accessible, but we always do word accesses.
         */
-       offset = spi % 4;
+       offset = irq % 4;
+       mmio->address &= ~0x3;
        mmio->value <<= 8 * offset;
        mmio->size = 4;
-       spi -= offset;
+       irq &= ~0x3;
 
-       for (i = 0; i < 4; i++, spi++) {
-               if (spi_in_cell(cell, spi))
+       for (i = 0; i < 4; i++, irq++) {
+               if (irqchip_irq_in_cell(cell, irq))
                        access_mask |= 0xff << (8 * i);
                else
                        continue;
@@ -194,7 +148,7 @@ static enum mmio_result handle_irq_target(struct mmio_access *mmio,
                        if (per_cpu(cpu)->cell == cell)
                                continue;
 
-                       printk("Attempt to route SPI%d outside of cell\n", spi);
+                       printk("Attempt to route IRQ%d outside of cell\n", irq);
                        return MMIO_ERROR;
                }
        }
@@ -202,7 +156,7 @@ static enum mmio_result handle_irq_target(struct mmio_access *mmio,
        if (mmio->is_write) {
                spin_lock(&dist_lock);
                u32 itargetsr =
-                       mmio_read32(gicd_base + GICD_ITARGETSR + reg + offset);
+                       mmio_read32(gicd_base + GICD_ITARGETSR + irq + offset);
                mmio->value &= access_mask;
                /* Combine with external SPIs */
                mmio->value |= (itargetsr & ~access_mask);
@@ -304,7 +258,7 @@ enum mmio_result gic_handle_dist_access(void *arg, struct mmio_access *mmio)
 
        switch (reg) {
        case REG_RANGE(GICD_IROUTER, 1024, 8):
-               ret = handle_irq_route(mmio, (reg - GICD_IROUTER) / 8);
+               ret = gic_handle_irq_route(mmio, (reg - GICD_IROUTER) / 8);
                break;
 
        case REG_RANGE(GICD_ITARGETSR, 1024, 1):
@@ -404,7 +358,7 @@ void gic_target_spis(struct cell *config_cell, struct cell *dest_cell)
        itargetsr += 4 * 8;
 
        for (i = 0; i < 64; i++, shift = (shift + 8) % 32) {
-               if (spi_in_cell(config_cell, i)) {
+               if (irqchip_irq_in_cell(config_cell, 32 + i)) {
                        mask |= (0xff << shift);
                        bits |= (cpu_itf << shift);
                }