aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-01-08 13:57:45 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-01-08 13:57:45 +0000
commita4071f906a47241e84a6fb6565902c42e79c7186 (patch)
treef59f06bd40f548ad541780de7f774d763003514b
parentd3f057861094611207862770fac4dcc6a140dd1e (diff)
downloadxen-a4071f906a47241e84a6fb6565902c42e79c7186.tar.gz
xen-a4071f906a47241e84a6fb6565902c42e79c7186.tar.bz2
xen-a4071f906a47241e84a6fb6565902c42e79c7186.zip
hvm: hpet: Fix per-timer enable/disable.
The enable/disable per timer interrupt bit is wrongly used as per timer enable/disable. According to spec, comparator value should constantly increasing when HPET is globally enabled, no matter whether the timer interrupt is enabled or not. From: Haitao Shan <haitao.shan@intel.com> Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/hvm/hpet.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 74f8aa56f9..603ffe8915 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -75,7 +75,6 @@
(S_TO_NS*TSC_PER_HPET_TICK)/h->tsc_freq)
#define timer_config(h, n) (h->hpet.timers[n].config)
-#define timer_enabled(h, n) (timer_config(h, n) & HPET_TN_ENABLE)
#define timer_is_periodic(h, n) (timer_config(h, n) & HPET_TN_PERIODIC)
#define timer_is_32bit(h, n) (timer_config(h, n) & HPET_TN_32BIT)
#define hpet_enabled(h) (h->hpet.config & HPET_CFG_ENABLE)
@@ -195,9 +194,6 @@ static void hpet_set_timer(HPETState *h, unsigned int tn)
ASSERT(tn < HPET_TIMER_NUM);
ASSERT(spin_is_locked(&h->lock));
- if ( !hpet_enabled(h) || !timer_enabled(h, tn) )
- return;
-
if ( (tn == 0) && (h->hpet.config & HPET_CFG_LEGACY) )
{
/* HPET specification requires PIT shouldn't generate
@@ -308,10 +304,6 @@ static void hpet_write(
if ( new_val & HPET_TN_32BIT )
h->hpet.timers[tn].cmp = (uint32_t)h->hpet.timers[tn].cmp;
- if ( !(old_val & HPET_TN_ENABLE) && (new_val & HPET_TN_ENABLE) )
- hpet_set_timer(h, tn);
- else if ( (old_val & HPET_TN_ENABLE) && !(new_val & HPET_TN_ENABLE) )
- hpet_stop_timer(h, tn);
break;
case HPET_T0_CMP:
@@ -326,7 +318,7 @@ static void hpet_write(
else
h->hpet.period[tn] = new_val;
h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
- if ( hpet_enabled(h) && timer_enabled(h, tn) )
+ if ( hpet_enabled(h) )
hpet_set_timer(h, tn);
break;
@@ -397,13 +389,14 @@ static void hpet_timer_fn(void *opaque)
spin_lock(&h->lock);
- if ( !hpet_enabled(h) || !timer_enabled(h, tn) )
+ if ( !hpet_enabled(h) )
{
spin_unlock(&h->lock);
return;
}
- hpet_route_interrupt(h, tn);
+ if ( timer_config(h, tn) & HPET_TN_ENABLE )
+ hpet_route_interrupt(h, tn);
if ( timer_is_periodic(h, tn) && (h->hpet.period[tn] != 0) )
{
@@ -522,7 +515,8 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h)
/* Restart the timers */
for ( i = 0; i < HPET_TIMER_NUM; i++ )
- hpet_set_timer(hp, i);
+ if ( hpet_enabled(hp) )
+ hpet_set_timer(hp, i);
spin_unlock(&hp->lock);