Based on the software-developers-hpet-spec-1-0a.pdf, the comparator
for a periodic timer will change to the new value when it matches
the master clock. The current code here uses a very standard
rounding formula of "((x + y - 1) / y) * y". This is wrong because
in this case you need to go to the next comparator value when "x"
equals "y". Not when "x + 1" equals "y". In this case "y" is the
period and "x" is the master clock.
The code lines:
elapsed = hpet_read_maincounter(h, guest_time) +
period - 1 - comparator;
comparator += (elapsed / period) * period;
are what matter here.
Using some numbers to help show the issue:
hpet_read_maincounter(h, guest_time) = 130252
period = 62500
comparator : 130252
elapsed : 62499
elapsed/period : 0
comparator_delta : 0
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>
if (period)
{
elapsed = hpet_read_maincounter(h, guest_time) +
- period - 1 - comparator;
+ period - comparator;
comparator += (elapsed / period) * period;
h->hpet.comparator64[tn] = comparator;
}