[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 2/3] vhpet: add support for level triggered interrupts
Level triggered interrupts are not an optional feature of HPET, and must be implemented in order to comply with the HPET specification. Implement them by adding a callback to the timer which sets the interrupt bit in the general interrupt status register. Further interrupts (in case of periodic mode) will not be injected until the bit is cleared. In order to reset the interrupts when the status bit is clear Xen must also detect accesses to such register. While there convert tn and i in hpet_write to unsigned. Reported-by: Stefan Bader <stefan.bader@xxxxxxxxxxxxx> Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- Cc: Jan Beulich <jbeulich@xxxxxxxx> Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Cc: Stefan Bader <stefan.bader@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/hpet.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c index f7aed7f69e..1cfd72592e 100644 --- a/xen/arch/x86/hvm/hpet.c +++ b/xen/arch/x86/hvm/hpet.c @@ -220,6 +220,17 @@ static void hpet_stop_timer(HPETState *h, unsigned int tn, hpet_get_comparator(h, tn, guest_time); } +static void hpet_timer_fired(struct vcpu *v, void *data) +{ + unsigned int tn = (unsigned int)data; + HPETState *h = vcpu_vhpet(v); + + write_lock(&h->lock); + ASSERT(!test_bit(tn, &h->hpet.isr)); + __set_bit(tn, &h->hpet.isr); + write_unlock(&h->lock); +} + /* the number of HPET tick that stands for * 1/(2^10) second, namely, 0.9765625 milliseconds */ #define HPET_TINY_TIME_SPAN ((h->stime_freq >> 10) / STIME_PER_HPET_TICK) @@ -241,7 +252,7 @@ static void hpet_set_timer(HPETState *h, unsigned int tn, pit_stop_channel0_irq(&vhpet_domain(h)->arch.vpit); } - if ( !timer_enabled(h, tn) ) + if ( !timer_enabled(h, tn) || test_bit(tn, &h->hpet.isr) ) return; tn_cmp = hpet_get_comparator(h, tn, guest_time); @@ -277,8 +288,12 @@ static void hpet_set_timer(HPETState *h, unsigned int tn, * timer we also need the period which may be different because time may * have elapsed between the time the comparator was written and the timer * being enabled (now). + * + * NB: set periodic timers as oneshot if interrupt type is set to level + * because the user must ack the interrupt (by writing 1 to the interrupt + * status register) before another interrupt can be delivered. */ - oneshot = !timer_is_periodic(h, tn); + oneshot = !timer_is_periodic(h, tn) || timer_level(h, tn); TRACE_2_LONG_4D(TRC_HVM_EMUL_HPET_START_TIMER, tn, irq, TRC_PAR_LONG(hpet_tick_to_ns(h, diff)), TRC_PAR_LONG(oneshot ? 0LL : @@ -286,7 +301,9 @@ static void hpet_set_timer(HPETState *h, unsigned int 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); + irq, + timer_level(h, tn) ? hpet_timer_fired : NULL, + (void *)(unsigned long)tn); } static inline uint64_t hpet_fixup_reg( @@ -304,7 +321,7 @@ static int hpet_write( HPETState *h = vcpu_vhpet(v); uint64_t old_val, new_val; uint64_t guest_time; - int tn, i; + unsigned int tn, i; /* Acculumate a bit mask of timers whos state is changed by this write. */ unsigned long start_timers = 0; @@ -360,6 +377,19 @@ static int hpet_write( } break; + case HPET_STATUS: + /* write 1 to clear. */ + while (new_val) + { + i = find_first_set_bit(new_val); + if ( i >= HPET_TIMER_NUM ) + break; + __clear_bit(i, &new_val); + if ( __test_and_clear_bit(i, &h->hpet.isr) ) + set_start_timer(i); + } + break; + case HPET_COUNTER: h->hpet.mc64 = new_val; if ( hpet_enabled(h) ) @@ -379,14 +409,6 @@ static int hpet_write( h->hpet.timers[tn].config = hpet_fixup_reg(new_val, old_val, 0x3f4e); - if ( timer_level(h, tn) ) - { - gdprintk(XENLOG_ERR, - "HPET: level triggered interrupt not supported now\n"); - domain_crash(current->domain); - break; - } - if ( new_val & HPET_TN_32BIT ) { h->hpet.timers[tn].cmp = (uint32_t)h->hpet.timers[tn].cmp; -- 2.16.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |