[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: Clean up APIC local timer handling.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1257240802 0 # Node ID 450f2ddd2dc6688bb3c5be3636944b33b3b1bb9c # Parent 7d7631b57d1966ba2fe7ccf4333f87d8a77d2fb4 x86: Clean up APIC local timer handling. 1. Writing TMICT=0 disables the timer. Use this fact to simplify and improve reprogram_timer(). In particular, we always write TMICT, and write zero when we do not need a timer interrupt. 2. In HPET broadcast timer handler, set TMICT=0 when we mask the APIC local timer. May as well do this early, before entering deep sleep. 3. In HVM-guest APIC emulation, disable the emulated local timer when the guest sets TMICT=0. Previously we would issue an immediate one-shot interrupt. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/apic.c | 62 ++++++++-------------------------------------- xen/arch/x86/hpet.c | 7 ++--- xen/arch/x86/hvm/vlapic.c | 11 ++++++-- 3 files changed, 23 insertions(+), 57 deletions(-) diff -r 7d7631b57d19 -r 450f2ddd2dc6 xen/arch/x86/apic.c --- a/xen/arch/x86/apic.c Tue Nov 03 08:40:40 2009 +0000 +++ b/xen/arch/x86/apic.c Tue Nov 03 09:33:22 2009 +0000 @@ -1178,65 +1178,25 @@ void enable_APIC_timer(void) #undef APIC_DIVISOR /* - * reprogram the APIC timer. Timeoutvalue is in ns from start of boot - * returns 1 on success - * returns 0 if the timeout value is too small or in the past. + * reprogram_timer: Reprogram the APIC timer. + * Timeout is a Xen system time (nanoseconds since boot); 0 disables the timer. + * Returns 1 on success; 0 if the timeout is too soon or is in the past. */ int reprogram_timer(s_time_t timeout) { - s_time_t now; - s_time_t expire; - u64 apic_tmict; - - /* - * If we don't have local APIC then we just poll the timer list off the - * PIT interrupt. - */ + s_time_t expire; + u32 apic_tmict = 0; + + /* No local APIC: timer list is polled via the PIT interrupt. */ if ( !cpu_has_apic ) return 1; - /* - * We use this value because we don't trust zero (we think it may just - * cause an immediate interrupt). At least this is guaranteed to hold it - * off for ages (esp. since the clock ticks on bus clock, not cpu clock!). - */ - if ( timeout == 0 ) - { - apic_tmict = 0xffffffff; - goto reprogram; - } - - now = NOW(); - expire = timeout - now; /* value from now */ - - if ( expire <= 0 ) - { - Dprintk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n", - smp_processor_id(), (u32)(now>>32), - (u32)now, (u32)(timeout>>32),(u32)timeout); - return 0; - } - - /* conversion to bus units */ - apic_tmict = (((u64)bus_scale) * expire)>>18; - - if ( apic_tmict >= 0xffffffff ) - { - Dprintk("APICT[%02d] Timeout value too large\n", smp_processor_id()); - apic_tmict = 0xffffffff; - } - - if ( apic_tmict == 0 ) - { - Dprintk("APICT[%02d] timeout value too small\n", smp_processor_id()); - return 0; - } - - reprogram: - /* Program the timer. */ + if ( timeout && ((expire = timeout - NOW()) > 0) ) + apic_tmict = min_t(u64, (bus_scale * expire) >> 18, UINT_MAX); + apic_write(APIC_TMICT, (unsigned long)apic_tmict); - return 1; + return apic_tmict || !timeout; } fastcall void smp_apic_timer_interrupt(struct cpu_user_regs * regs) diff -r 7d7631b57d19 -r 450f2ddd2dc6 xen/arch/x86/hpet.c --- a/xen/arch/x86/hpet.c Tue Nov 03 08:40:40 2009 +0000 +++ b/xen/arch/x86/hpet.c Tue Nov 03 09:33:22 2009 +0000 @@ -642,6 +642,8 @@ void hpet_broadcast_enter(void) if ( hpet_attach_channel ) hpet_attach_channel(cpu, ch); + /* Cancel any outstanding LAPIC timer event and disable interrupts. */ + reprogram_timer(0); disable_APIC_timer(); cpu_set(cpu, ch->cpumask); @@ -664,11 +666,8 @@ void hpet_broadcast_exit(void) if ( cpu_test_and_clear(cpu, ch->cpumask) ) { - /* Cancel any outstanding LAPIC event and re-enable interrupts. */ - reprogram_timer(0); + /* Reprogram the deadline; trigger timer work now if it has passed. */ enable_APIC_timer(); - - /* Reprogram the deadline; trigger timer work now if it has passed. */ if ( !reprogram_timer(per_cpu(timer_deadline, cpu)) ) raise_softirq(TIMER_SOFTIRQ); diff -r 7d7631b57d19 -r 450f2ddd2dc6 xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Tue Nov 03 08:40:40 2009 +0000 +++ b/xen/arch/x86/hvm/vlapic.c Tue Nov 03 09:33:22 2009 +0000 @@ -667,10 +667,17 @@ static int vlapic_write(struct vcpu *v, case APIC_TMICT: { - uint64_t period = (uint64_t)APIC_BUS_CYCLE_NS * - (uint32_t)val * vlapic->hw.timer_divisor; + uint64_t period; vlapic_set_reg(vlapic, APIC_TMICT, val); + if ( val == 0 ) + { + destroy_periodic_time(&vlapic->pt); + break; + } + + period = ((uint64_t)APIC_BUS_CYCLE_NS * + (uint32_t)val * vlapic->hw.timer_divisor); create_periodic_time(current, &vlapic->pt, period, vlapic_lvtt_period(vlapic) ? period : 0, vlapic->pt.irq, vlapic_pt_cb, _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |