diff mbox

[v14,2/3] hw/ptimer: Fix counter - 1 returned by ptimer_get_count for the active timer

Message ID bf8a11d66b68c0d0738428bf6dd18d1a532b3eb3.1466167530.git.digetx@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Dmitry Osipenko June 17, 2016, 1:17 p.m. UTC
Due to rounding down performed by ptimer_get_count, it returns counter - 1 for
the active timer. That's incorrect because counter should decrement only after
period been expired, not before. I.e. if running timer has been loaded with
value X, then timer counter should stay with X until period expired and
decrement after. Fix this by adding 1 to the counter value for the active and
unexpired timer.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 hw/core/ptimer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Dmitry Osipenko June 20, 2016, 7:51 p.m. UTC | #1
I started to port MPTimer tests to QTest that allows precise VM clock control. 
It helped to find out that the last period of the periodic timer is getting 
lost, i.e. when counter = 0 (before wrap around). So the counter should be 
loaded with limit + 1 after wrapping around. This worked before because we are 
returning counter = 0 for the expired timer, that expiration doesn't happen 
under QTest and some of the tests fail. I'll send new revision of the patch 
after receiving feedback to the "policy" patch and once QTests would be ready.

On 17.06.2016 16:17, Dmitry Osipenko wrote:
> Due to rounding down performed by ptimer_get_count, it returns counter - 1 for
> the active timer. That's incorrect because counter should decrement only after
> period been expired, not before. I.e. if running timer has been loaded with
> value X, then timer counter should stay with X until period expired and
> decrement after. Fix this by adding 1 to the counter value for the active and
> unexpired timer.
>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  hw/core/ptimer.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
> index 289e23e..7f89001 100644
> --- a/hw/core/ptimer.c
> +++ b/hw/core/ptimer.c
> @@ -89,10 +89,10 @@ static void ptimer_tick(void *opaque)
>
>  uint64_t ptimer_get_count(ptimer_state *s)
>  {
> +    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>      uint64_t counter;
>
> -    if (s->enabled && s->delta != 0) {
> -        int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +    if (s->enabled && s->delta != 0 && now != s->last_event) {
>          int64_t next = s->next_event;
>          bool expired = (now - next >= 0);
>          bool oneshot = (s->enabled == 2);
> @@ -144,7 +144,7 @@ uint64_t ptimer_get_count(ptimer_state *s)
>                  if ((uint32_t)(period_frac << shift))
>                      div += 1;
>              }
> -            counter = rem / div;
> +            counter = rem / div + (expired ? 0 : 1);
>
>              if (expired && counter != 0) {
>                  /* Wrap around periodic counter.  */
>
diff mbox

Patch

diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index 289e23e..7f89001 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -89,10 +89,10 @@  static void ptimer_tick(void *opaque)
 
 uint64_t ptimer_get_count(ptimer_state *s)
 {
+    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
     uint64_t counter;
 
-    if (s->enabled && s->delta != 0) {
-        int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    if (s->enabled && s->delta != 0 && now != s->last_event) {
         int64_t next = s->next_event;
         bool expired = (now - next >= 0);
         bool oneshot = (s->enabled == 2);
@@ -144,7 +144,7 @@  uint64_t ptimer_get_count(ptimer_state *s)
                 if ((uint32_t)(period_frac << shift))
                     div += 1;
             }
-            counter = rem / div;
+            counter = rem / div + (expired ? 0 : 1);
 
             if (expired && counter != 0) {
                 /* Wrap around periodic counter.  */