Now there is an ncpus property, use it in order to deliver the IRQ to multiple CPU.
Co-developed-by: Frederic Konrad <konrad.frede...@yahoo.fr> Signed-off-by: Clément Chigot <chi...@adacore.com> --- hw/intc/grlib_irqmp.c | 43 ++++++++++++++++++----------------- hw/sparc/leon3.c | 3 ++- include/hw/intc/grlib_irqmp.h | 2 +- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index be0e840181..4df0293064 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -64,7 +64,7 @@ struct IRQMP { unsigned int ncpus; IRQMPState *state; qemu_irq start_signal[IRQMP_MAX_CPU]; - qemu_irq irq; + qemu_irq irq[IRQMP_MAX_CPU]; }; struct IRQMPState { @@ -83,37 +83,37 @@ struct IRQMPState { static void grlib_irqmp_check_irqs(IRQMPState *state) { - uint32_t pend = 0; - uint32_t level0 = 0; - uint32_t level1 = 0; + uint32_t pend = 0; + uint32_t level0 = 0; + uint32_t level1 = 0; + int i; assert(state != NULL); assert(state->parent != NULL); - /* IRQ for CPU 0 (no SMP support) */ - pend = (state->pending | state->force[0]) - & state->mask[0]; - - level0 = pend & ~state->level; - level1 = pend & state->level; + for (i = 0; i < state->parent->ncpus; i++) { + pend = (state->pending | state->force[i]) & state->mask[i]; + level0 = pend & ~state->level; + level1 = pend & state->level; - trace_grlib_irqmp_check_irqs(state->pending, state->force[0], - state->mask[0], level1, level0); + trace_grlib_irqmp_check_irqs(state->pending, state->force[i], + state->mask[i], level1, level0); - /* Trigger level1 interrupt first and level0 if there is no level1 */ - qemu_set_irq(state->parent->irq, level1 ?: level0); + /* Trigger level1 interrupt first and level0 if there is no level1 */ + qemu_set_irq(state->parent->irq[i], level1 ?: level0); + } } -static void grlib_irqmp_ack_mask(IRQMPState *state, uint32_t mask) +static void grlib_irqmp_ack_mask(IRQMPState *state, int cpu, uint32_t mask) { /* Clear registers */ state->pending &= ~mask; - state->force[0] &= ~mask; /* Only CPU 0 (No SMP support) */ + state->force[cpu] &= ~mask; grlib_irqmp_check_irqs(state); } -void grlib_irqmp_ack(DeviceState *dev, int intno) +void grlib_irqmp_ack(DeviceState *dev, int cpu, int intno) { IRQMP *irqmp = GRLIB_IRQMP(dev); IRQMPState *state; @@ -127,7 +127,7 @@ void grlib_irqmp_ack(DeviceState *dev, int intno) trace_grlib_irqmp_ack(intno); - grlib_irqmp_ack_mask(state, mask); + grlib_irqmp_ack_mask(state, cpu, mask); } static void grlib_irqmp_set_irq(void *opaque, int irq, int level) @@ -153,7 +153,6 @@ static void grlib_irqmp_set_irq(void *opaque, int irq, int level) s->pending |= 1 << irq; } grlib_irqmp_check_irqs(s); - } } @@ -257,7 +256,9 @@ static void grlib_irqmp_write(void *opaque, hwaddr addr, case CLEAR_OFFSET: value &= ~1; /* clean up the value */ - grlib_irqmp_ack_mask(state, value); + for (i = 0; i < irqmp->ncpus; i++) { + grlib_irqmp_ack_mask(state, i, value); + } return; case MP_STATUS_OFFSET: @@ -352,7 +353,7 @@ static void grlib_irqmp_realize(DeviceState *dev, Error **errp) /* Transitionning from 0 to 1 starts the CPUs. */ qdev_init_gpio_out_named(dev, irqmp->start_signal, "grlib-start-cpu", IRQMP_MAX_CPU); - qdev_init_gpio_out_named(dev, &irqmp->irq, "grlib-irq", 1); + qdev_init_gpio_out_named(dev, irqmp->irq, "grlib-irq", irqmp->ncpus); memory_region_init_io(&irqmp->iomem, OBJECT(dev), &grlib_irqmp_ops, irqmp, "irqmp", IRQMP_REG_SIZE); diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 7b9809b81f..94d8ec94b0 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -168,7 +168,8 @@ static void leon3_cache_control_int(CPUSPARCState *env) static void leon3_irq_ack(void *irq_manager, int intno) { - grlib_irqmp_ack((DeviceState *)irq_manager, intno); + /* No SMP support yet. */ + grlib_irqmp_ack((DeviceState *)irq_manager, 0, intno); } /* diff --git a/include/hw/intc/grlib_irqmp.h b/include/hw/intc/grlib_irqmp.h index b9cc584168..776a2508e1 100644 --- a/include/hw/intc/grlib_irqmp.h +++ b/include/hw/intc/grlib_irqmp.h @@ -34,6 +34,6 @@ /* IRQMP */ #define TYPE_GRLIB_IRQMP "grlib-irqmp" -void grlib_irqmp_ack(DeviceState *dev, int intno); +void grlib_irqmp_ack(DeviceState *dev, int cpu, int intno); #endif /* GRLIB_IRQMP_H */ -- 2.25.1