qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/2] hw/intc/grlib_irqmp: add support for extended interrupts


From: Nikita Shushura
Subject: Re: [PATCH 1/2] hw/intc/grlib_irqmp: add support for extended interrupts
Date: Fri, 20 Sep 2024 22:56:03 +0000

Forgot to add 'Signed-off-by', so can be deleted.




Sent with Proton Mail secure email.

On Saturday, September 21st, 2024 at 1:48 AM, Nikita Shushura 
<me@nikitashushura.com> wrote:

> ---
> hw/intc/grlib_irqmp.c | 68 +++++++++++++++++++++++++++++++------------
> 1 file changed, 49 insertions(+), 19 deletions(-)
> 
> diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
> index 37ac63fd80..2fd76dd1b4 100644
> --- a/hw/intc/grlib_irqmp.c
> +++ b/hw/intc/grlib_irqmp.c
> @@ -1,8 +1,6 @@
> /*
> * QEMU GRLIB IRQMP Emulator
> *
> - * (Extended interrupt not supported)
> - *
> * SPDX-License-Identifier: MIT
> *
> * Copyright (c) 2010-2024 AdaCore
> @@ -38,25 +36,29 @@
> #include "qemu/module.h"
> #include "qom/object.h"
> 
> -#define IRQMP_MAX_CPU 16
> -#define IRQMP_REG_SIZE 256 /* Size of memory mapped registers /
> +#define IRQMP_MAX_CPU (16)
> +#define IRQMP_REG_SIZE (256) / Size of memory mapped registers /
> 
> / Memory mapped register offsets /
> -#define LEVEL_OFFSET 0x00
> -#define PENDING_OFFSET 0x04
> -#define FORCE0_OFFSET 0x08
> -#define CLEAR_OFFSET 0x0C
> -#define MP_STATUS_OFFSET 0x10
> -#define BROADCAST_OFFSET 0x14
> -#define MASK_OFFSET 0x40
> -#define FORCE_OFFSET 0x80
> -#define EXTENDED_OFFSET 0xC0
> +#define LEVEL_OFFSET (0x00)
> +#define PENDING_OFFSET (0x04)
> +#define FORCE0_OFFSET (0x08)
> +#define CLEAR_OFFSET (0x0C)
> +#define MP_STATUS_OFFSET (0x10)
> +#define BROADCAST_OFFSET (0x14)
> +#define MASK_OFFSET (0x40)
> +#define FORCE_OFFSET (0x80)
> +#define EXTENDED_OFFSET (0xC0)
> 
> / Multiprocessor Status Register */
> #define MP_STATUS_CPU_STATUS_MASK ((1 << IRQMP_MAX_CPU)-2)
> -#define MP_STATUS_NCPU_SHIFT 28
> +#define MP_STATUS_NCPU_SHIFT (28)
> +#define MP_STATUS_EIRQ_OFFSET (16)
> +
> +#define MAX_PILS_STD (16)
> +#define MAX_PILS_EXT (32)
> 
> -#define MAX_PILS 16
> +#define DEFAULT_EIRQ (12)
> 
> OBJECT_DECLARE_SIMPLE_TYPE(IRQMP, GRLIB_IRQMP)
> 
> @@ -68,6 +70,7 @@ struct IRQMP {
> MemoryRegion iomem;
> 
> unsigned int ncpus;
> + unsigned int eirq;
> IRQMPState *state;
> qemu_irq start_signal[IRQMP_MAX_CPU];
> qemu_irq irq[IRQMP_MAX_CPU];
> @@ -89,13 +92,25 @@ struct IRQMPState {
> 
> static void grlib_irqmp_check_irqs(IRQMPState *state)
> {
> - int i;
> + int i, j;
> 
> assert(state != NULL);
> assert(state->parent != NULL);
> 
> 
> for (i = 0; i < state->parent->ncpus; i++) {
> 
> uint32_t pend = (state->pending | state->force[i]) & state->mask[i];
> 
> +
> + /*
> + * Check is pending interrupt is extended,
> + * if so set pending to EIRQ and acknowledge extended interrupt"
> + */
> + for (j = MAX_PILS_STD; j <= MAX_PILS_EXT; j++) {
> + if ((pend & (1 << j)) != 0) {
> + pend = (1 << state->parent->eirq);
> 
> + state->extended[i] = (j & 0xffff);
> 
> + }
> + }
> +
> uint32_t level0 = pend & ~state->level;
> 
> uint32_t level1 = pend & state->level;
> 
> 
> @@ -110,6 +125,10 @@ static void grlib_irqmp_check_irqs(IRQMPState *state)
> static void grlib_irqmp_ack_mask(IRQMPState *state, unsigned int cpu,
> uint32_t mask)
> {
> + if ((mask & (1 << state->parent->eirq)) != 0) {
> 
> + mask |= (1 << state->extended[cpu]);
> 
> + }
> +
> /* Clear registers */
> state->pending &= ~mask;
> 
> state->force[cpu] &= ~mask;
> 
> @@ -144,7 +163,6 @@ static void grlib_irqmp_set_irq(void *opaque, int irq, 
> int level)
> assert(s != NULL);
> assert(s->parent != NULL);
> 
> 
> -
> if (level) {
> trace_grlib_irqmp_set_irq(irq);
> 
> @@ -278,6 +296,9 @@ static void grlib_irqmp_write(void *opaque, hwaddr addr,
> state->mpstatus &= ~(1 << i);
> 
> }
> }
> +
> + /* Writing EIRQ number */
> + state->mpstatus |= (state->parent->eirq << MP_STATUS_EIRQ_OFFSET);
> 
> return;
> 
> case BROADCAST_OFFSET:
> @@ -345,7 +366,8 @@ static void grlib_irqmp_reset(DeviceState *d)
> memset(irqmp->state, 0, sizeof *irqmp->state);
> 
> irqmp->state->parent = irqmp;
> 
> irqmp->state->mpstatus = ((irqmp->ncpus - 1) << MP_STATUS_NCPU_SHIFT) |
> 
> - ((1 << irqmp->ncpus) - 2);
> 
> + ((1 << irqmp->ncpus) - 2) |
> 
> + (irqmp->eirq << MP_STATUS_EIRQ_OFFSET);
> 
> }
> 
> static void grlib_irqmp_realize(DeviceState *dev, Error **errp)
> @@ -359,7 +381,14 @@ static void grlib_irqmp_realize(DeviceState *dev, Error 
> **errp)
> return;
> }
> 
> - qdev_init_gpio_in(dev, grlib_irqmp_set_irq, MAX_PILS);
> + if ((!irqmp->eirq) || (irqmp->eirq >= MAX_PILS_STD)) {
> 
> + error_setg(errp, "Invalid eirq properties: "
> + "%u, must be 0 < eirq < %u.", irqmp->eirq,
> 
> + MAX_PILS_STD);
> + return;
> + }
> +
> + qdev_init_gpio_in(dev, grlib_irqmp_set_irq, MAX_PILS_EXT);
> 
> /*
> * Transitionning from 0 to 1 starts the CPUs. The opposite can't
> @@ -378,6 +407,7 @@ static void grlib_irqmp_realize(DeviceState *dev, Error 
> **errp)
> 
> static Property grlib_irqmp_properties[] = {
> DEFINE_PROP_UINT32("ncpus", IRQMP, ncpus, 1),
> + DEFINE_PROP_UINT32("eirq", IRQMP, eirq, DEFAULT_EIRQ),
> DEFINE_PROP_END_OF_LIST(),
> };
> 
> --
> 2.46.1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]