intc/arm_gic: Implement GICD_ISACTIVERn and GICD_ICACTIVERn registers

Implement GICD_ISACTIVERn and GICD_ICACTIVERn registers in the GICv2.
Those registers allow to set or clear the active state of an IRQ in the
distributor.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-3-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Luc Michel 2018-08-14 17:17:19 +01:00 committed by Peter Maydell
parent 67ce697ac8
commit 3bb0b03897

View File

@ -725,8 +725,16 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
}
}
} else if (offset < 0x400) {
/* Interrupt Active. */
irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
/* Interrupt Set/Clear Active. */
if (offset < 0x380) {
irq = (offset - 0x300) * 8;
} else if (s->revision == 2) {
irq = (offset - 0x380) * 8;
} else {
goto bad_reg;
}
irq += GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
res = 0;
@ -1007,9 +1015,54 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
GIC_DIST_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
}
}
} else if (offset < 0x380) {
/* Interrupt Set Active. */
if (s->revision != 2) {
goto bad_reg;
}
irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq) {
goto bad_reg;
}
/* This register is banked per-cpu for PPIs */
int cm = irq < GIC_INTERNAL ? (1 << cpu) : ALL_CPU_MASK;
for (i = 0; i < 8; i++) {
if (s->security_extn && !attrs.secure &&
!GIC_DIST_TEST_GROUP(irq + i, 1 << cpu)) {
continue; /* Ignore Non-secure access of Group0 IRQ */
}
if (value & (1 << i)) {
GIC_DIST_SET_ACTIVE(irq + i, cm);
}
}
} else if (offset < 0x400) {
/* Interrupt Active. */
goto bad_reg;
/* Interrupt Clear Active. */
if (s->revision != 2) {
goto bad_reg;
}
irq = (offset - 0x380) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq) {
goto bad_reg;
}
/* This register is banked per-cpu for PPIs */
int cm = irq < GIC_INTERNAL ? (1 << cpu) : ALL_CPU_MASK;
for (i = 0; i < 8; i++) {
if (s->security_extn && !attrs.secure &&
!GIC_DIST_TEST_GROUP(irq + i, 1 << cpu)) {
continue; /* Ignore Non-secure access of Group0 IRQ */
}
if (value & (1 << i)) {
GIC_DIST_CLEAR_ACTIVE(irq + i, cm);
}
}
} else if (offset < 0x800) {
/* Interrupt Priority. */
irq = (offset - 0x400) + GIC_BASE_IRQ;