On 29 June 2018 at 14:29, Luc Michel <luc.mic...@greensocs.com> wrote:
> Implement write access to 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.mic...@greensocs.com>
> ---
>  hw/intc/arm_gic.c | 41 +++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 39 insertions(+), 2 deletions(-)
>
> diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
> index ea0323f969..5755a4fb2c 100644
> --- a/hw/intc/arm_gic.c
> +++ b/hw/intc/arm_gic.c
> @@ -982,9 +982,46 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
>                  GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
>              }
>          }
> +    } else if (offset < 0x380) {
> +        /* Interrupt Set Active.  */

These are read-only for the GICv1 and 11MPCore, so we need
to guard this code with a check on s->revision == 2:
           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);

You don't introduce this macro until patch 2, so this patch
has to go after that, so that we still compile at all points
in the patch sequence.

> +            }
> +        }
>      } else if (offset < 0x400) {
> -        /* Interrupt Active.  */
> -        goto bad_reg;
> +        /* Interrupt Clear Active.  */
> +        irq = (offset - 0x380) * 8 + GIC_BASE_IRQ;
> +        if (irq >= s->num_irq) {
> +            goto bad_reg;
> +        }

These registers only exist for GICv2, so again a check
on s->revision is required.

You also need to implement reading of GICD_ICACTIVERn for
GICv2 -- the code in gic_dist_readb() only implements reads of
GICD_ISACTIVERn (which is all that GICv1 needed).

> +
> +        /* 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;
> --
> 2.17.1

Looks good otherwise.

thanks
-- PMM

Reply via email to