[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 |