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;
}
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;
}
* 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
*/
struct cell *cell = this_cell();
unsigned int i, cpu;
- unsigned int spi = reg - 32;
unsigned int offset;
u32 access_mask = 0;
u8 targets;
* 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;
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;
}
}
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;
}
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);
}
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):
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. */
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);
}