debuggers.hg
changeset 16727:66db23ecd562
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>
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>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Tue Jan 08 13:57:45 2008 +0000 (2008-01-08) |
parents | 4fcc8b64c2b5 |
children | 01adaec882d4 |
files | xen/arch/x86/hvm/hpet.c |
line diff
1.1 --- a/xen/arch/x86/hvm/hpet.c Tue Jan 08 10:13:11 2008 +0000 1.2 +++ b/xen/arch/x86/hvm/hpet.c Tue Jan 08 13:57:45 2008 +0000 1.3 @@ -75,7 +75,6 @@ 1.4 (S_TO_NS*TSC_PER_HPET_TICK)/h->tsc_freq) 1.5 1.6 #define timer_config(h, n) (h->hpet.timers[n].config) 1.7 -#define timer_enabled(h, n) (timer_config(h, n) & HPET_TN_ENABLE) 1.8 #define timer_is_periodic(h, n) (timer_config(h, n) & HPET_TN_PERIODIC) 1.9 #define timer_is_32bit(h, n) (timer_config(h, n) & HPET_TN_32BIT) 1.10 #define hpet_enabled(h) (h->hpet.config & HPET_CFG_ENABLE) 1.11 @@ -195,9 +194,6 @@ static void hpet_set_timer(HPETState *h, 1.12 ASSERT(tn < HPET_TIMER_NUM); 1.13 ASSERT(spin_is_locked(&h->lock)); 1.14 1.15 - if ( !hpet_enabled(h) || !timer_enabled(h, tn) ) 1.16 - return; 1.17 - 1.18 if ( (tn == 0) && (h->hpet.config & HPET_CFG_LEGACY) ) 1.19 { 1.20 /* HPET specification requires PIT shouldn't generate 1.21 @@ -308,10 +304,6 @@ static void hpet_write( 1.22 if ( new_val & HPET_TN_32BIT ) 1.23 h->hpet.timers[tn].cmp = (uint32_t)h->hpet.timers[tn].cmp; 1.24 1.25 - if ( !(old_val & HPET_TN_ENABLE) && (new_val & HPET_TN_ENABLE) ) 1.26 - hpet_set_timer(h, tn); 1.27 - else if ( (old_val & HPET_TN_ENABLE) && !(new_val & HPET_TN_ENABLE) ) 1.28 - hpet_stop_timer(h, tn); 1.29 break; 1.30 1.31 case HPET_T0_CMP: 1.32 @@ -326,7 +318,7 @@ static void hpet_write( 1.33 else 1.34 h->hpet.period[tn] = new_val; 1.35 h->hpet.timers[tn].config &= ~HPET_TN_SETVAL; 1.36 - if ( hpet_enabled(h) && timer_enabled(h, tn) ) 1.37 + if ( hpet_enabled(h) ) 1.38 hpet_set_timer(h, tn); 1.39 break; 1.40 1.41 @@ -397,13 +389,14 @@ static void hpet_timer_fn(void *opaque) 1.42 1.43 spin_lock(&h->lock); 1.44 1.45 - if ( !hpet_enabled(h) || !timer_enabled(h, tn) ) 1.46 + if ( !hpet_enabled(h) ) 1.47 { 1.48 spin_unlock(&h->lock); 1.49 return; 1.50 } 1.51 1.52 - hpet_route_interrupt(h, tn); 1.53 + if ( timer_config(h, tn) & HPET_TN_ENABLE ) 1.54 + hpet_route_interrupt(h, tn); 1.55 1.56 if ( timer_is_periodic(h, tn) && (h->hpet.period[tn] != 0) ) 1.57 { 1.58 @@ -522,7 +515,8 @@ static int hpet_load(struct domain *d, h 1.59 1.60 /* Restart the timers */ 1.61 for ( i = 0; i < HPET_TIMER_NUM; i++ ) 1.62 - hpet_set_timer(hp, i); 1.63 + if ( hpet_enabled(hp) ) 1.64 + hpet_set_timer(hp, i); 1.65 1.66 spin_unlock(&hp->lock); 1.67