]> rtime.felk.cvut.cz Git - jailhouse.git/blobdiff - hypervisor/arch/arm/gic-common.c
arm: Fix byte-wise write access to GICD_ITARGETSRn
[jailhouse.git] / hypervisor / arch / arm / gic-common.c
index 7bb6cd336c01cc16673869267cccac8eab1556af..51f6bee02c431d6d0331addb9f279f1b77bc0b33 100644 (file)
@@ -46,29 +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)) {
-               mmio_perform_access(gicd_base, mmio);
-               return MMIO_HANDLED;
-       }
+       for (irq = first_irq; irq < first_irq + irqs_per_reg; irq++) {
+               unsigned int bit_nr = (irq - first_irq) * bits_per_irq;
 
-       /* 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;
+               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;
        }
 
        if (!mmio->is_write) {
@@ -172,10 +167,10 @@ static enum mmio_result handle_irq_target(struct mmio_access *mmio,
        }
 
        /*
-        * 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;
+       mmio->address &= ~0x3;
        mmio->value <<= 8 * offset;
        mmio->size = 4;
        spi -= offset;
@@ -293,7 +288,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);
        }