diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-10-22 12:04:32 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-10-22 12:04:32 +0100 |
commit | bfd5a3fec25a6dd88425dff7c908127ef4b1dada (patch) | |
tree | ab0ea83f81ac7dbd523c8af817cda23b8035cf2b /xen/arch/x86/hvm/vpt.c | |
parent | c916f30553fc9df0959932324b056d316e603b3f (diff) | |
download | xen-bfd5a3fec25a6dd88425dff7c908127ef4b1dada.tar.gz xen-bfd5a3fec25a6dd88425dff7c908127ef4b1dada.tar.bz2 xen-bfd5a3fec25a6dd88425dff7c908127ef4b1dada.zip |
Port HPET device model to vpt timer subsystem
The current hpet implementation runs a one-shot xen timer for each
hpet timer whenever the main counter is enabled regardless of whether
or not the individual hpet timers are enabled. When the timer fires,
if it is enabled the interrupt is routed to the guest. If the hpet
timer is periodic, a new one-shot timer is set, for NOW()+period.
There are a number of problems with this the most significant is guest
time drift. Windows does not read the hardware clock to verify time,
it depends on timer interrupts firing at the expected interval. The
existing implementation queues a new one-shot timer each time it fires
and does not allow for a difference between NOW() and the time the
timer was expected to fire, causing drift. Also there is
no allowance for lost ticks. This modification changes HPET to use the
Virtual Platform Timer (VPT) and, for periodic timers, to use periodic
timers. The VPT ensures an interrupt is delivered to the guest for
each period that elapses, plus, its use of xen periodic timers ensures
no drift.
Signed-off-by: Peter Johnston <peter.johnston@citrix.com>
Diffstat (limited to 'xen/arch/x86/hvm/vpt.c')
-rw-r--r-- | xen/arch/x86/hvm/vpt.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c index 1b4b4f5840..27bacd9b28 100644 --- a/xen/arch/x86/hvm/vpt.c +++ b/xen/arch/x86/hvm/vpt.c @@ -355,8 +355,8 @@ void pt_migrate(struct vcpu *v) } void create_periodic_time( - struct vcpu *v, struct periodic_time *pt, uint64_t period, - uint8_t irq, char one_shot, time_cb *cb, void *data) + struct vcpu *v, struct periodic_time *pt, uint64_t delta, + uint64_t period, uint8_t irq, time_cb *cb, void *data) { ASSERT(pt->source != 0); @@ -369,7 +369,7 @@ void create_periodic_time( pt->irq_issued = 0; /* Periodic timer must be at least 0.9ms. */ - if ( (period < 900000) && !one_shot ) + if ( (period < 900000) && period ) { if ( !test_and_set_bool(pt->warned_timeout_too_short) ) gdprintk(XENLOG_WARNING, "HVM_PlatformTime: program too " @@ -382,15 +382,15 @@ void create_periodic_time( pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu); pt->irq = irq; pt->period_cycles = (u64)period; - pt->one_shot = one_shot; - pt->scheduled = NOW() + period; + pt->one_shot = !period; + pt->scheduled = NOW() + delta; /* * Offset LAPIC ticks from other timer ticks. Otherwise guests which use * LAPIC ticks for process accounting can see long sequences of process * ticks incorrectly accounted to interrupt processing. */ if ( pt->source == PTSRC_lapic ) - pt->scheduled += period >> 1; + pt->scheduled += delta >> 1; pt->cb = cb; pt->priv = data; |