|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 03/10] hvm/hpet: Only set comparator or period not both.
The current code sets both. If setting the comparator also set
comparator64 (the hidden version).
Based on:
software-developers-hpet-spec-1-0a.pdf
A write call should only change comparator or period, not both.
Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx>
---
xen/arch/x86/hvm/hpet.c | 58 ++++++++++++++++++++++++++++++++-----------------
1 file changed, 38 insertions(+), 20 deletions(-)
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 16c0f07..0795f29 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -399,30 +399,48 @@ static int hpet_write(
tn = HPET_TN(CMP, addr);
if ( timer_is_32bit(h, tn) )
new_val = (uint32_t)new_val;
- h->hpet.timers[tn].cmp = new_val;
- if ( h->hpet.timers[tn].config & HPET_TN_SETVAL )
- /*
- * When SETVAL is one, software is able to "directly set a periodic
- * timer's accumulator." That is, set the comparator without
- * adjusting the period. Much the same as just setting the
- * comparator on an enabled one-shot timer.
- *
- * This configuration bit clears when the comparator is written.
- */
- h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
- else if ( timer_is_periodic(h, tn) )
+ if ( timer_is_periodic(h, tn) )
+ {
+ if ( h->hpet.timers[tn].config & HPET_TN_SETVAL )
+ {
+ /*
+ * When SETVAL is one, software is able to "directly
+ * set a periodic timer's accumulator." That is,
+ * set the comparator without adjusting the period.
+ * Much the same as just setting the comparator on
+ * an enabled one-shot timer.
+ *
+ * This configuration bit clears when the comparator
+ * is written.
+ */
+ h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
+ h->hpet.timers[tn].cmp = new_val;
+ h->hpet.comparator64[tn] = new_val;
+ }
+ else
+ {
+ /*
+ * Clamp period to reasonable min/max values:
+ * - minimum is 100us, same as timers controlled by vpt.c
+ * - maximum is to prevent overflow in time_after()
+ * calculations
+ */
+ if ( hpet_tick_to_ns(h, new_val) < MICROSECS(100) )
+ new_val = (MICROSECS(100) << 10) / h->hpet_to_ns_scale;
+ new_val &= (timer_is_32bit(h, tn) ? ~0u : ~0ull) >> 1;
+ h->hpet.period[tn] = new_val;
+ }
+ }
+ else
{
/*
- * Clamp period to reasonable min/max values:
- * - minimum is 100us, same as timers controlled by vpt.c
- * - maximum is to prevent overflow in time_after() calculations
+ * The spec says "do not use", but clear if specified.
*/
- if ( hpet_tick_to_ns(h, new_val) < MICROSECS(100) )
- new_val = (MICROSECS(100) << 10) / h->hpet_to_ns_scale;
- new_val &= (timer_is_32bit(h, tn) ? ~0u : ~0ull) >> 1;
- h->hpet.period[tn] = new_val;
+ if ( h->hpet.timers[tn].config & HPET_TN_SETVAL )
+ h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
+ h->hpet.timers[tn].cmp = new_val;
+ h->hpet.comparator64[tn] = new_val;
}
- h->hpet.comparator64[tn] = new_val;
if ( hpet_enabled(h) && timer_enabled(h, tn) )
set_restart_timer(tn);
break;
--
1.8.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |