qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Vladimir Prus <vladimir@codesourcery.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] Re: Fix ptimer_get_count overflow.
Date: Wed, 04 Mar 2009 12:31:29 +0300	[thread overview]
Message-ID: <golhpd$sm5$1@ger.gmane.org> (raw)
In-Reply-To: 200902121733.43146.vladimir@codesourcery.com

[-- Attachment #1: Type: text/plain, Size: 824 bytes --]

Vladimir Prus wrote:

> 
> At present, ptimers have a slight inaccuracy that can lead to
> overflow. The period is stored as 64.32 fixed point number.
> ptimer_reload uses both integer and fractional part of the perion
> when computing when the next event should happen. ptimer_get_count,
> however, uses only integer part of the period. Therefore, when
> ptimer_get_count is called very soon after ptimer_reload the value
> returned may be greater than the value ptimer_reload has set.
> And if the counter was 0xFFFFFFFF, this may result in overflow.
> 
> This was observed in SH4A emulation as "time jumps", where system
> time gets magically increased by 10 minutes sometimes.
> 
> This patch fixes this. The math is not the most accurate possible,
> but it's relatively fast and fixes the problems.

Ping?

- Volodya



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: primer_overflow.diff --]
[-- Type: text/x-diff; name="primer_overflow.diff", Size: 2008 bytes --]

commit f1b78f0ca2b7fe12cdaabcb97c08484d3c26b99f
Author: Vladimir Prus <vladimir@codesourcery.com>
Date:   Thu Dec 25 17:20:38 2008 +0300

    Fix ptimer_get_count overflow.
    
    	* hw/ptimer.c (ptimer_get_count): Don't ignore
    	fractional part of period.

diff --git a/hw/ptimer.c b/hw/ptimer.c
index 9d38627..9278f83 100644
--- a/hw/ptimer.c
+++ b/hw/ptimer.c
@@ -7,7 +7,7 @@
  */
 #include "hw.h"
 #include "qemu-timer.h"
-
+#include "host-utils.h"
 
 struct ptimer_state
 {
@@ -78,10 +78,41 @@ uint64_t ptimer_get_count(ptimer_state *s)
         } else {
             uint64_t rem;
             uint64_t div;
+            uint32_t frac;
+            int clz1, clz2;
+            int shift;
+
+            /* We need to divide time by period, where time is stored in
+               rem (64-bit integer) and period is stored in period/period_frac
+               (64.32 fixed point). The result should be rounded down, so that
+               we never get the value greater than the timer's limit.
+
+               We normalize both numerator and demoninator by left-shifting
+               until one of them has non-zero MSB, and then do 64-bit division.
+            */
 
             rem = s->next_event - now;
             div = s->period;
-            counter = rem / div;
+
+            clz1 = clz64(rem);
+            clz2 = clz64(div);
+            shift = clz1 < clz2 ? clz1 : clz2;
+
+            rem <<= shift;
+            div <<= shift;
+            if (shift <= 32)
+                div |= (unsigned long long)(
+                    (s->period_frac >> (32 - shift)) & ((1ull << shift) - 1));
+            else
+                div |= (s->period_frac << (shift - 32));
+            
+            /* Look at remaining bits of period_frac and round div up if 
+               necessary.  */
+            frac = s->period_frac << shift;
+            if (frac)
+                div += 1;
+            
+            counter = rem/div;
         }
     } else {
         counter = s->delta;

  reply	other threads:[~2009-03-04  9:31 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-12 14:33 [Qemu-devel] Fix ptimer_get_count overflow Vladimir Prus
2009-03-04  9:31 ` Vladimir Prus [this message]
2009-03-31 14:38   ` [Qemu-devel] " Paul Brook

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='golhpd$sm5$1@ger.gmane.org' \
    --to=vladimir@codesourcery.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).