qemu-arm
[Top][All Lists]
Advanced

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

Re: [Qemu-arm] [PATCH v9 05/14] hw/arm/smmuv3: Wired IRQ and GERROR help


From: Peter Maydell
Subject: Re: [Qemu-arm] [PATCH v9 05/14] hw/arm/smmuv3: Wired IRQ and GERROR helpers
Date: Thu, 8 Mar 2018 17:49:35 +0000

On 17 February 2018 at 18:46, Eric Auger <address@hidden> wrote:
> We introduce some helpers to handle wired IRQs and especially
> GERROR interrupt. SMMU writes GERROR register on GERROR event
> and SW acks GERROR interrupts by setting GERRORn.
>
> The Wired interrupts are edge sensitive hence the pulse usage.
>
> Signed-off-by: Eric Auger <address@hidden>
>
> ---
>
> v7 -> v8:
> - remove SMMU_PENDING_GERRORS macro
> - properly toggle gerror
> - properly sanitize gerrorn write
> ---
>  hw/arm/smmuv3-internal.h | 10 ++++++++
>  hw/arm/smmuv3.c          | 64 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/arm/trace-events      |  3 +++
>  3 files changed, 77 insertions(+)
>
> diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
> index 5be8303..40b39a1 100644
> --- a/hw/arm/smmuv3-internal.h
> +++ b/hw/arm/smmuv3-internal.h
> @@ -152,4 +152,14 @@ static inline uint64_t smmu_read64(uint64_t r, unsigned 
> offset,
>      return extract64(r, offset << 3, 32);
>  }
>
> +/* Interrupts */
> +
> +#define smmuv3_eventq_irq_enabled(s)                   \
> +    (FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN))
> +#define smmuv3_gerror_irq_enabled(s)                  \
> +    (FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN))

These are only ever used in smmuv3.c, so you can just move them
to there (and make them inline functions, ideally).

> +
> +void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
> +void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);

I guess these are global to avoid the compiler complaining about
unused static functions at this point? If so, add a comment
saying so, and flip them back to being static functions when
their callers get added. (Or just add the callers here, if they're
not too complicated.)

> +
>  #endif
> diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
> index dc03c9e..8779d3f 100644
> --- a/hw/arm/smmuv3.c
> +++ b/hw/arm/smmuv3.c
> @@ -30,6 +30,70 @@
>  #include "hw/arm/smmuv3.h"
>  #include "smmuv3-internal.h"
>
> +/**
> + * smmuv3_trigger_irq - pulse @irq if enabled and update
> + * GERROR register in case of GERROR interrupt
> + *
> + * @irq: irq type
> + * @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR)
> + */
> +void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask)
> +{
> +
> +    bool pulse = false;
> +
> +    switch (irq) {
> +    case SMMU_IRQ_EVTQ:
> +        pulse = smmuv3_eventq_irq_enabled(s);
> +        break;
> +    case SMMU_IRQ_PRIQ:
> +        error_setg(&error_fatal, "PRI not supported");

This should either assert() if it would be a bug in the rest
of the smmu code, or LOG_UNIMP if the guest can trigger it.

> +        break;
> +    case SMMU_IRQ_CMD_SYNC:
> +        pulse = true;
> +        break;
> +    case SMMU_IRQ_GERROR:
> +    {
> +        uint32_t pending = s->gerror ^ s->gerrorn;
> +        uint32_t new_gerrors = ~pending & gerror_mask;
> +
> +        if (!new_gerrors) {
> +            /* only toggle non pending errors */
> +            return;
> +        }
> +        s->gerror ^= new_gerrors;
> +        trace_smmuv3_write_gerror(new_gerrors, s->gerror);
> +
> +        /* pulse the GERROR irq only if all previous gerrors were acked */

It's not entirely clear to me that this is correct; should
we generate only one pulse if the implementation raises error A,
and then later raises error B before software acknowledges A ?
There's some language in 3.18 about the SMMU implementation
being able to coalesce events and identical interrupts, but
I think that would mean that we could skip raising the first
pulse for error A if error B arrived sufficiently quickly after it.
(Not something we're going to care about for a s/w model.)

I think the right behaviour is probably that we should pulse
the interrupt if there are any new gerrors, which is to
say to drop this !pending test:

> +        pulse = smmuv3_gerror_irq_enabled(s) && !pending;
> +        break;
> +    }
> +    }
> +    if (pulse) {
> +            trace_smmuv3_trigger_irq(irq);
> +            qemu_irq_pulse(s->irq[irq]);
> +    }
> +}
> +
> +void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
> +{
> +    uint32_t pending = s->gerror ^ s->gerrorn;
> +    uint32_t toggled = s->gerrorn ^ new_gerrorn;
> +    uint32_t acked;
> +
> +    if (toggled & ~pending) {
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "guest toggles non pending errors = 0x%x\n",
> +                      toggled & ~pending);
> +    }
> +
> +    /* Make sure SW does not toggle irqs that are not active */
> +    acked = toggled & pending;
> +    s->gerrorn ^= acked;
> +

I don't think this behaviour is correct. From the hardware's
perspective, we should just take the value the user writes
to SMMU_GERRORN and put it in the register (and update the
status of the irq accordingly).

It is CONSTRAINED UNPREDICTABLE whether we actually raise an
interrupt if the guest toggles a field that corresponds to an
inactive error, so we should just do whatever is easiest.

> +    trace_smmuv3_write_gerrorn(acked, s->gerrorn);
> +}
> +
>  static void smmuv3_init_regs(SMMUv3State *s)
>  {
>      /**
> diff --git a/hw/arm/trace-events b/hw/arm/trace-events
> index 64d2b9b..2ddae40 100644
> --- a/hw/arm/trace-events
> +++ b/hw/arm/trace-events
> @@ -15,3 +15,6 @@ smmu_get_pte(uint64_t baseaddr, int index, uint64_t 
> pteaddr, uint64_t pte) "base
>
>  #hw/arm/smmuv3.c
>  smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 
> 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x"
> +smmuv3_trigger_irq(int irq) "irq=%d"
> +smmuv3_write_gerror(uint32_t toggled, uint32_t gerror) "toggled=0x%x, new 
> gerror=0x%x"
> +smmuv3_write_gerrorn(uint32_t acked, uint32_t gerrorn) "acked=0x%x, new 
> gerrorn=0x%x"

Capitalizing names of registers like GERROR in trace messages would
make them match the convention in the SMMUv3 spec.

> --
> 2.5.5
>

thanks
-- PMM



reply via email to

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