|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 10/10] hvm/hpet: handle 1st period special
The software-developers-hpet-spec-1-0a.pdf says that the 1st
interrupt is based on the setting of comparator. After that it will
be on each period. Add code that checks for this special case.
Add a callback routine when this special case is active that
will disable the special case on the 1st interrupt.
Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx>
---
xen/arch/x86/hvm/hpet.c | 56 +++++++++++++++++++++++++++++++++++++------
xen/include/asm-x86/hvm/vpt.h | 2 ++
2 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 3226a61..f8ed792 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -94,10 +94,18 @@ static uint64_t hpet_get_comparator(HPETState *h, unsigned
int tn,
{
/* update comparator by number of periods elapsed since last update */
uint64_t period = h->hpet.period[tn];
+ uint64_t mc = hpet_read_maincounter(h, guest_time);
+
+ if ( h->hpet.first_enabled[tn] )
+ {
+ if ( mc >= h->hpet.first_mc64[tn] && mc < comparator )
+ period = 0; /* act like oneshot */
+ else
+ h->hpet.first_enabled[tn] = 0;
+ }
if (period)
{
- elapsed = hpet_read_maincounter(h, guest_time) +
- period - comparator;
+ elapsed = mc + period - comparator;
comparator += (elapsed / period) * period;
h->hpet.comparator64[tn] = comparator;
}
@@ -203,6 +211,13 @@ static void hpet_stop_timer(HPETState *h, unsigned int tn)
* 1/(2^10) second, namely, 0.9765625 milliseconds */
#define HPET_TINY_TIME_SPAN ((h->stime_freq >> 10) / STIME_PER_HPET_TICK)
+static void hpet_time_fired(struct vcpu *v, void *priv)
+{
+ uint8_t *first_enabled_p = (uint8_t *)priv;
+
+ *first_enabled_p = 0;
+}
+
static void hpet_set_timer(HPETState *h, unsigned int tn, int mc_starting)
{
uint64_t tn_cmp, cur_tick, diff;
@@ -223,8 +238,16 @@ static void hpet_set_timer(HPETState *h, unsigned int tn,
int mc_starting)
if ( !timer_enabled(h, tn) )
return;
+ oneshot = !timer_is_periodic(h, tn);
if ( mc_starting )
+ {
guest_time = h->hpet.mc64 - h->mc_offset;
+ if ( !oneshot )
+ {
+ h->hpet.first_mc64[tn] = h->hpet.mc64;
+ h->hpet.first_enabled[tn] = 1;
+ }
+ }
else
guest_time = guest_time_hpet(h);
@@ -262,11 +285,27 @@ static void hpet_set_timer(HPETState *h, unsigned int tn,
int mc_starting)
* have elapsed between the time the comparator was written and the timer
* being enabled (now).
*/
- oneshot = !timer_is_periodic(h, tn);
- create_periodic_time(vhpet_vcpu(h), &h->pt[tn],
- hpet_tick_to_ns(h, diff),
- oneshot ? 0 : hpet_tick_to_ns(h, h->hpet.period[tn]),
- irq, NULL, NULL);
+ if ( oneshot )
+ create_periodic_time(vhpet_vcpu(h), &h->pt[tn],
+ hpet_tick_to_ns(h, diff),
+ 0, irq, NULL, NULL);
+ else
+ {
+ if ( diff <= h->hpet.period[tn] )
+ {
+ h->hpet.first_enabled[tn] = 0;
+ create_periodic_time(vhpet_vcpu(h), &h->pt[tn],
+ hpet_tick_to_ns(h, diff),
+ hpet_tick_to_ns(h, h->hpet.period[tn]),
+ irq, NULL, NULL);
+ }
+ else
+ create_periodic_time(vhpet_vcpu(h), &h->pt[tn],
+ hpet_tick_to_ns(h, diff),
+ hpet_tick_to_ns(h, h->hpet.period[tn]),
+ irq, hpet_time_fired,
+ &h->hpet.first_enabled[tn]);
+ }
}
static inline uint64_t hpet_fixup_reg(
@@ -591,6 +630,9 @@ static int hpet_load(struct domain *d, hvm_domain_context_t
*h)
if ( timer_is_32bit(hp, i) )
cmp = (uint32_t)cmp;
hp->hpet.timers[i].cmp = cmp;
+ /* Init hidden regs also */
+ hp->hpet.first_mc64[i] = 0;
+ hp->hpet.first_enabled[i] = 0;
}
#undef C
diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h
index 41159d8..aea5121 100644
--- a/xen/include/asm-x86/hvm/vpt.h
+++ b/xen/include/asm-x86/hvm/vpt.h
@@ -87,6 +87,8 @@ struct hpet_registers {
/* Hidden register state */
uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
uint64_t comparator64[HPET_TIMER_NUM]; /* 64 bit running comparator */
+ uint64_t first_mc64[HPET_TIMER_NUM]; /* 1st interval main counter */
+ uint8_t first_enabled[HPET_TIMER_NUM]; /* In 1st interval */
};
typedef struct HPETState {
--
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 |