All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: "~axelheider" <axelheider@gmx.de>
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org
Subject: Re: [PATCH qemu.git v3 8/8] hw/timer/imx_epit: fix compare timer handling
Date: Tue, 4 Apr 2023 16:44:45 +0100	[thread overview]
Message-ID: <CAFEAcA9JLOhxa3LeiFJ8YqinuSV33N4Vbj2m4ZnoOxry0=YGGA@mail.gmail.com> (raw)
In-Reply-To: <166990932074.29941.8709118178538288040-8@git.sr.ht>

On Thu, 1 Dec 2022 at 15:42, ~axelheider <axelheider@git.sr.ht> wrote:
>
> From: Axel Heider <axel.heider@hensoldt.net>
>
> - fix #1263 for CR writes
> - rework compare time handling
>   - The compare timer has to run even if CR.OCIEN is not set,
>     as SR.OCIF must be updated.
>   - The compare timer fires exactly once when the
>     compare value is less than the current value, but the
>     reload values is less than the compare value.
>   - The compare timer will never fire if the reload value is
>     less than the compare value. Disable it in this case.
>
> Signed-off-by: Axel Heider <axel.heider@hensoldt.net>

Hi; Coverity has just noticed an issue with this patch:


> -/* Must be called from ptimer_transaction_begin/commit block for s->timer_cmp */
> -static void imx_epit_reload_compare_timer(IMXEPITState *s)
> +/*
> + * Must be called from a ptimer_transaction_begin/commit block for
> + * s->timer_cmp, but outside of a transaction block of s->timer_reload,
> + * so the proper counter value is read.
> + */
> +static void imx_epit_update_compare_timer(IMXEPITState *s)
>  {
> -    if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN))  {
> -        /* if the compare feature is on and timers are running */
> -        uint32_t tmp = ptimer_get_count(s->timer_reload);
> -        uint64_t next;
> -        if (tmp > s->cmp) {
> -            /* It'll fire in this round of the timer */
> -            next = tmp - s->cmp;
> -        } else { /* catch it next time around */
> -            next = tmp - s->cmp + ((s->cr & CR_RLD) ? EPIT_TIMER_MAX : s->lr);
> +    uint64_t counter = 0;
> +    bool is_oneshot = false;

Here we declare the is_oneshot variable...

> +    /* The compare timer only has to run if the timer peripheral is active
> +     * and there is an input clock, Otherwise it can be switched off.
> +     */
> +    bool is_active = (s->cr & CR_EN) && imx_epit_get_freq(s);
> +    if (is_active) {
> +        /*
> +         * Calculate next timeout for compare timer. Reading the reload
> +         * counter returns proper results only if pending transactions
> +         * on it are committed here. Otherwise stale values are be read.
> +         */
> +        counter = ptimer_get_count(s->timer_reload);
> +        uint64_t limit = ptimer_get_limit(s->timer_cmp);
> +        /*
> +         * The compare timer is a periodic timer if the limit is at least
> +         * the compare value. Otherwise it may fire at most once in the
> +         * current round.
> +         */
> +        bool is_oneshot = (limit >= s->cmp);

...but here we declare another is_oneshot, which shadows the first
declaration...

> +        if (counter >= s->cmp) {
> +            /* The compare timer fires in the current round. */
> +            counter -= s->cmp;
> +        } else if (!is_oneshot) {
> +            /*
> +             * The compare timer fires after a reload, as it below the
> +             * compare value already in this round. Note that the counter
> +             * value calculated below can be above the 32-bit limit, which
> +             * is legal here because the compare timer is an internal
> +             * helper ptimer only.
> +             */
> +            counter += limit - s->cmp;
> +        } else {
> +            /*
> +             * The compare timer won't fire in this round, and the limit is
> +             * set to a value below the compare value. This practically means
> +             * it will never fire, so it can be switched off.
> +             */
> +            is_active = false;
>          }
> -        ptimer_set_count(s->timer_cmp, next);
>      }
> +
> +    /*
> +     * Set the compare timer and let it run, or stop it. This is agnostic
> +     * of CR.OCIEN bit, as this bit affects interrupt generation only. The
> +     * compare timer needs to run even if no interrupts are to be generated,
> +     * because the SR.OCIF bit must be updated also.
> +     * Note that the timer might already be stopped or be running with
> +     * counter values. However, finding out when an update is needed and
> +     * when not is not trivial. It's much easier applying the setting again,
> +     * as this does not harm either and the overhead is negligible.
> +     */
> +    if (is_active) {
> +        ptimer_set_count(s->timer_cmp, counter);
> +        ptimer_run(s->timer_cmp, is_oneshot ? 1 : 0);

...so here when the inner variable is no longer in scope, the
value of the outer is_oneshot variable must always be 'false',
because there's never any assignment to it.

> +    } else {
> +        ptimer_stop(s->timer_cmp);
> +    }
> +
>  }

What was the intention here? My guess is that there should only
have been one 'is_oneshot', not two.

There's also been this bug report:
https://gitlab.com/qemu-project/qemu/-/issues/1491
which suggests that the condition for setting is_oneshot
should be "(limit <= s->cmp)" rather than ">=".

What do you think ?

thanks
-- PMM


  parent reply	other threads:[~2023-04-04 15:45 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-01 15:42 [PATCH qemu.git v3 0/8] hw/timer/imx_epit: improve and fix EPIT compare timer ~axelheider
2022-10-25 10:33 ` [PATCH qemu.git v3 7/8] hw/timer/imx_epit: remove explicit fields cnt and freq ~axelheider
2023-01-05 12:08   ` Peter Maydell
2022-10-25 15:33 ` [PATCH qemu.git v3 1/8] hw/timer/imx_epit: improve comments ~axelheider
2023-01-05 12:00   ` Peter Maydell
2022-10-25 18:32 ` [PATCH qemu.git v3 4/8] hw/timer/imx_epit: update interrupt state on CR write access ~axelheider
2023-01-05 12:03   ` Peter Maydell
2022-10-27 13:09 ` [PATCH qemu.git v3 6/8] hw/timer/imx_epit: factor out register write handlers ~axelheider
2023-01-05 12:04   ` Peter Maydell
2022-10-30 23:59 ` [PATCH qemu.git v3 2/8] hw/timer/imx_epit: cleanup CR defines ~axelheider
2023-01-05 12:00   ` Peter Maydell
2022-11-19 14:59 ` [PATCH qemu.git v3 3/8] hw/timer/imx_epit: define SR_OCIF ~axelheider
2023-01-05 12:01   ` Peter Maydell
2022-11-19 16:09 ` [PATCH qemu.git v3 5/8] hw/timer/imx_epit: hard reset initializes CR with 0 ~axelheider
2023-01-05 12:04   ` Peter Maydell
2022-11-20 19:05 ` [PATCH qemu.git v3 8/8] hw/timer/imx_epit: fix compare timer handling ~axelheider
2023-01-05 12:21   ` Peter Maydell
2023-01-05 21:08     ` Axel Heider
2023-04-04 15:44   ` Peter Maydell [this message]
2023-04-04 16:26     ` Axel Heider
2023-01-05 12:23 ` [PATCH qemu.git v3 0/8] hw/timer/imx_epit: improve and fix EPIT compare timer Peter Maydell
2023-01-05 21:11   ` Axel Heider

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAFEAcA9JLOhxa3LeiFJ8YqinuSV33N4Vbj2m4ZnoOxry0=YGGA@mail.gmail.com' \
    --to=peter.maydell@linaro.org \
    --cc=axelheider@gmx.de \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.