]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
hvm/hpet: comparator can only change when master clock is enabled.
authorDon Slutz <dslutz@verizon.com>
Fri, 2 May 2014 20:18:06 +0000 (16:18 -0400)
committerTim Deegan <tim@xen.org>
Thu, 8 May 2014 11:03:53 +0000 (12:03 +0100)
This is based on software-developers-hpet-spec-1-0a.pdf saying:

When the main counter value matches the value in the timer's
comparator register, an interrupt can be generated.  The hardware
will then automatically increase the value in the compare register
by the last value written to that register.

When the overall enable is off (the main count is halted), none of
the compare registers should change.

The code lines:

    elapsed = hpet_read_maincounter(h, guest_time) +
        period - 1 - comparator;
    comparator += (elapsed / period) * period;

are what matter here.  They will always adjust comparator to be no
more then one period away.

Using some numbers to help show the issue:

hpet_read_maincounter(h, guest_time) = 67752
period = 62500
comparator = 255252 == 67752 + 3 * 62500

comparator       : 255252
elapsed          : -125001
elapsed/period   : -2
comparator_delta : -125000
new comparator   : 130252

Signed-off-by: Don Slutz <dslutz@verizon.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Tim Deegan <tim@xen.org>
xen/arch/x86/hvm/hpet.c

index 741fb7ae9d75a3fea1d62b63bde5ac3522e85b67..f938da977a7d12426eaffb471f27cfc38583bdb2 100644 (file)
@@ -92,7 +92,7 @@ static uint64_t hpet_get_comparator(HPETState *h, unsigned int tn,
     uint64_t elapsed;
 
     comparator = h->hpet.comparator64[tn];
-    if ( timer_is_periodic(h, tn) )
+    if ( hpet_enabled(h) && timer_is_periodic(h, tn) )
     {
         /* update comparator by number of periods elapsed since last update */
         uint64_t period = h->hpet.period[tn];