[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 4/6] x86/HVM: properly handle RTC periodic timer even when !RTC_PIE
At 14:53 +0100 on 29 Apr (1367247238), Jan Beulich wrote: > Since in that case the processing it pr_intr_post() won't occur, we > need to do some additional work in pt_update_irq(). Additionally we > must not pay attention to the respective IRQ being masked. I don't think this is the right fix for 4.3. We should just revert to the old system (where the vpt code raises the IRQ) rather than bodge up the new one -- especially since the new _behaviour_ is disabled anyway. After 4.3 branches (which is RSN, right Goerge?) we can sort out a proper interface for all of that, and this might well be it. Tim. > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> > > --- a/xen/arch/x86/hvm/rtc.c > +++ b/xen/arch/x86/hvm/rtc.c > @@ -67,11 +67,13 @@ static void rtc_update_irq(RTCState *s) > hvm_isa_irq_assert(vrtc_domain(s), RTC_IRQ); > } > > -void rtc_periodic_interrupt(void *opaque) > +bool_t rtc_periodic_interrupt(void *opaque) > { > RTCState *s = opaque; > + bool_t ret; > > spin_lock(&s->lock); > + ret = !(s->hw.cmos_data[RTC_REG_C] & RTC_IRQF); > if ( !(s->hw.cmos_data[RTC_REG_C] & RTC_PF) ) > { > s->hw.cmos_data[RTC_REG_C] |= RTC_PF; > @@ -83,7 +85,11 @@ void rtc_periodic_interrupt(void *opaque > destroy_periodic_time(&s->pt); > s->pt_code = 0; > } > + if ( !(s->hw.cmos_data[RTC_REG_C] & RTC_IRQF) ) > + ret = 0; > spin_unlock(&s->lock); > + > + return ret; > } > > /* Enable/configure/disable the periodic timer based on the RTC_PIE and > --- a/xen/arch/x86/hvm/vpt.c > +++ b/xen/arch/x86/hvm/vpt.c > @@ -216,18 +216,23 @@ static void pt_timer_fn(void *data) > int pt_update_irq(struct vcpu *v) > { > struct list_head *head = &v->arch.hvm_vcpu.tm_list; > - struct periodic_time *pt, *temp, *earliest_pt = NULL; > - uint64_t max_lag = -1ULL; > + struct periodic_time *pt, *temp, *earliest_pt; > + uint64_t max_lag; > int irq, is_lapic; > void *pt_priv; > > + rescan: > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > + rescan_locked: > + earliest_pt = NULL; > + max_lag = -1ULL; > list_for_each_entry_safe ( pt, temp, head, list ) > { > if ( pt->pending_intr_nr ) > { > - if ( pt_irq_masked(pt) ) > + /* RTC code takes care of disabling the timer itself. */ > + if ( (pt->irq != RTC_IRQ || !pt->priv) && pt_irq_masked(pt) ) > { > /* suspend timer emulation */ > list_del(&pt->list); > @@ -260,7 +265,41 @@ int pt_update_irq(struct vcpu *v) > if ( is_lapic ) > vlapic_set_irq(vcpu_vlapic(v), irq, 0); > else if ( irq == RTC_IRQ && pt_priv ) > - rtc_periodic_interrupt(pt_priv); > + { > + if ( !rtc_periodic_interrupt(pt_priv) ) > + irq = -1; > + > + pt_lock(earliest_pt); > + > + if ( irq < 0 && earliest_pt->pending_intr_nr ) > + { > + /* > + * RTC periodic timer runs without the corresponding interrupt > + * being enabled - need to mimic enough of pt_intr_post() to keep > + * things going. > + */ > + earliest_pt->pending_intr_nr = 0; > + earliest_pt->irq_issued = 0; > + set_timer(&earliest_pt->timer, earliest_pt->scheduled); > + } > + else if ( irq >= 0 && pt_irq_masked(earliest_pt) ) > + { > + if ( earliest_pt->on_list ) > + { > + /* suspend timer emulation */ > + list_del(&earliest_pt->list); > + earliest_pt->on_list = 0; > + } > + irq = -1; > + } > + > + /* Avoid dropping the lock if we can. */ > + if ( irq < 0 && v == earliest_pt->vcpu ) > + goto rescan_locked; > + pt_unlock(earliest_pt); > + if ( irq < 0 ) > + goto rescan; > + } > else > { > hvm_isa_irq_deassert(v->domain, irq); > --- a/xen/include/asm-x86/hvm/vpt.h > +++ b/xen/include/asm-x86/hvm/vpt.h > @@ -183,7 +183,7 @@ void rtc_migrate_timers(struct vcpu *v); > void rtc_deinit(struct domain *d); > void rtc_reset(struct domain *d); > void rtc_update_clock(struct domain *d); > -void rtc_periodic_interrupt(void *); > +bool_t rtc_periodic_interrupt(void *); > > void pmtimer_init(struct vcpu *v); > void pmtimer_deinit(struct domain *d); > > > > x86/HVM: properly handle RTC periodic timer even when !RTC_PIE > > Since in that case the processing it pr_intr_post() won't occur, we > need to do some additional work in pt_update_irq(). Additionally we > must not pay attention to the respective IRQ being masked. > > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> > > --- a/xen/arch/x86/hvm/rtc.c > +++ b/xen/arch/x86/hvm/rtc.c > @@ -67,11 +67,13 @@ static void rtc_update_irq(RTCState *s) > hvm_isa_irq_assert(vrtc_domain(s), RTC_IRQ); > } > > -void rtc_periodic_interrupt(void *opaque) > +bool_t rtc_periodic_interrupt(void *opaque) > { > RTCState *s = opaque; > + bool_t ret; > > spin_lock(&s->lock); > + ret = !(s->hw.cmos_data[RTC_REG_C] & RTC_IRQF); > if ( !(s->hw.cmos_data[RTC_REG_C] & RTC_PF) ) > { > s->hw.cmos_data[RTC_REG_C] |= RTC_PF; > @@ -83,7 +85,11 @@ void rtc_periodic_interrupt(void *opaque > destroy_periodic_time(&s->pt); > s->pt_code = 0; > } > + if ( !(s->hw.cmos_data[RTC_REG_C] & RTC_IRQF) ) > + ret = 0; > spin_unlock(&s->lock); > + > + return ret; > } > > /* Enable/configure/disable the periodic timer based on the RTC_PIE and > --- a/xen/arch/x86/hvm/vpt.c > +++ b/xen/arch/x86/hvm/vpt.c > @@ -216,18 +216,23 @@ static void pt_timer_fn(void *data) > int pt_update_irq(struct vcpu *v) > { > struct list_head *head = &v->arch.hvm_vcpu.tm_list; > - struct periodic_time *pt, *temp, *earliest_pt = NULL; > - uint64_t max_lag = -1ULL; > + struct periodic_time *pt, *temp, *earliest_pt; > + uint64_t max_lag; > int irq, is_lapic; > void *pt_priv; > > + rescan: > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > + rescan_locked: > + earliest_pt = NULL; > + max_lag = -1ULL; > list_for_each_entry_safe ( pt, temp, head, list ) > { > if ( pt->pending_intr_nr ) > { > - if ( pt_irq_masked(pt) ) > + /* RTC code takes care of disabling the timer itself. */ > + if ( (pt->irq != RTC_IRQ || !pt->priv) && pt_irq_masked(pt) ) > { > /* suspend timer emulation */ > list_del(&pt->list); > @@ -260,7 +265,41 @@ int pt_update_irq(struct vcpu *v) > if ( is_lapic ) > vlapic_set_irq(vcpu_vlapic(v), irq, 0); > else if ( irq == RTC_IRQ && pt_priv ) > - rtc_periodic_interrupt(pt_priv); > + { > + if ( !rtc_periodic_interrupt(pt_priv) ) > + irq = -1; > + > + pt_lock(earliest_pt); > + > + if ( irq < 0 && earliest_pt->pending_intr_nr ) > + { > + /* > + * RTC periodic timer runs without the corresponding interrupt > + * being enabled - need to mimic enough of pt_intr_post() to keep > + * things going. > + */ > + earliest_pt->pending_intr_nr = 0; > + earliest_pt->irq_issued = 0; > + set_timer(&earliest_pt->timer, earliest_pt->scheduled); > + } > + else if ( irq >= 0 && pt_irq_masked(earliest_pt) ) > + { > + if ( earliest_pt->on_list ) > + { > + /* suspend timer emulation */ > + list_del(&earliest_pt->list); > + earliest_pt->on_list = 0; > + } > + irq = -1; > + } > + > + /* Avoid dropping the lock if we can. */ > + if ( irq < 0 && v == earliest_pt->vcpu ) > + goto rescan_locked; > + pt_unlock(earliest_pt); > + if ( irq < 0 ) > + goto rescan; > + } > else > { > hvm_isa_irq_deassert(v->domain, irq); > --- a/xen/include/asm-x86/hvm/vpt.h > +++ b/xen/include/asm-x86/hvm/vpt.h > @@ -183,7 +183,7 @@ void rtc_migrate_timers(struct vcpu *v); > void rtc_deinit(struct domain *d); > void rtc_reset(struct domain *d); > void rtc_update_clock(struct domain *d); > -void rtc_periodic_interrupt(void *); > +bool_t rtc_periodic_interrupt(void *); > > void pmtimer_init(struct vcpu *v); > void pmtimer_deinit(struct domain *d); _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |