aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/vpt.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-10-22 12:04:32 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-10-22 12:04:32 +0100
commitbfd5a3fec25a6dd88425dff7c908127ef4b1dada (patch)
treeab0ea83f81ac7dbd523c8af817cda23b8035cf2b /xen/arch/x86/hvm/vpt.c
parentc916f30553fc9df0959932324b056d316e603b3f (diff)
downloadxen-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.c12
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;