]> 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 00da4cb2dda592b4a2a97e5b6ae8e8d8f8a783f5..ab405e52577fdaa953cd380eb265ea3467756dfc 100644 (file)
@@ -46,34 +46,24 @@ restrict_bitmask_access(struct mmio_access *mmio, unsigned int reg_index,
                        unsigned int bits_per_irq, bool is_poke)
 {
        struct cell *cell = this_cell();
-       unsigned int spi;
+       unsigned int irq;
        unsigned long access_mask = 0;
        /*
         * In order to avoid division, the number of bits per irq is limited
         * to powers of 2 for the moment.
         */
        unsigned long irqs_per_reg = 32 >> ffsl(bits_per_irq);
-       unsigned long spi_bits = (1 << bits_per_irq) - 1;
+       unsigned long irq_bits = (1 << bits_per_irq) - 1;
        /* First, extract the first interrupt affected by this access */
        unsigned int first_irq = reg_index * irqs_per_reg;
 
-       /* For SGIs or PPIs, let the caller do the mmio access */
-       if (!is_spi(first_irq)) {
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
-               return MMIO_HANDLED;
-       }
-
-       /* For SPIs, compare against the cell config mask */
-       first_irq -= 32;
-       for (spi = first_irq; spi < first_irq + irqs_per_reg; spi++) {
-               unsigned int bit_nr = (spi - first_irq) * bits_per_irq;
-               if (spi_in_cell(cell, spi))
-                       access_mask |= spi_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 */
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
+               mmio_perform_access(gicd_base, mmio);
                mmio->value &= access_mask;
                return MMIO_HANDLED;
        }
@@ -89,58 +79,18 @@ restrict_bitmask_access(struct mmio_access *mmio, unsigned int reg_index,
                spin_lock(&dist_lock);
 
                mmio->is_write = false;
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
+               mmio_perform_access(gicd_base, mmio);
                mmio->is_write = true;
 
                /* Clear 0 bits */
                mmio->value &= ~(access_mask & ~access_val);
                mmio->value |= access_val;
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
+               mmio_perform_access(gicd_base, mmio);
 
                spin_unlock(&dist_lock);
        } else {
                mmio->value &= access_mask;
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
-       }
-       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;
-               }
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
-       } else {
-               cpu = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq);
-               mmio->value = arm_cpu_phys2virt(cpu);
+               mmio_perform_access(gicd_base, mmio);
        }
        return MMIO_HANDLED;
 }
@@ -149,7 +99,7 @@ static enum mmio_result handle_irq_route(struct mmio_access *mmio,
  * 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
@@ -157,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;
@@ -166,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)) {
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
+       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;
@@ -199,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;
                }
        }
@@ -207,15 +156,15 @@ 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);
                /* And do the access */
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
+               mmio_perform_access(gicd_base, mmio);
                spin_unlock(&dist_lock);
        } else {
-               arm_mmio_perform_access((unsigned long)gicd_base, mmio);
+               mmio_perform_access(gicd_base, mmio);
                mmio->value &= access_mask;
        }
 
@@ -293,7 +242,7 @@ void gic_handle_sgir_write(struct sgi *sgi, bool virt_input)
                if (sgi->routing_mode == 0 && !is_target)
                        continue;
 
-               irqchip_set_pending(per_cpu(cpu), sgi->id, false);
+               irqchip_set_pending(per_cpu(cpu), sgi->id);
                sgi->targets |= (1 << cpu);
        }
 
@@ -309,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):
@@ -350,7 +299,7 @@ enum mmio_result gic_handle_dist_access(void *arg, struct mmio_access *mmio)
        case REG_RANGE(GICD_CIDR0, 4, 4):
                /* Allow read access, ignore write */
                if (!mmio->is_write)
-                       arm_mmio_perform_access((unsigned long)gicd_base, mmio);
+                       mmio_perform_access(gicd_base, mmio);
                /* fall through */
        default:
                /* Ignore access. */
@@ -409,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);
                }