[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] x86 hvm: freeze PIT/LAPIC timer emulation while its IRQ is masked
Hi, I've found that modern windows OS never use the PIT timer, and neither cpu#0's LAPIC timer after boot. Despite that, xen emulates them busily. It's inefficient. Note: this patch ignores the IRQ mask of legacy i8259 since rombios frequently modifies it. Thanks, Kouya Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx> diff -r d2a32e24fe50 xen/arch/x86/hvm/i8254.c --- a/xen/arch/x86/hvm/i8254.c Wed Sep 09 16:39:41 2009 +0100 +++ b/xen/arch/x86/hvm/i8254.c Thu Sep 10 09:55:29 2009 +0900 @@ -421,6 +421,8 @@ static int pit_load(struct domain *d, hv spin_unlock(&pit->lock); + pt_freeze_pit_timer_if_irqmasked(d); + return 0; } diff -r d2a32e24fe50 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Wed Sep 09 16:39:41 2009 +0100 +++ b/xen/arch/x86/hvm/vioapic.c Thu Sep 10 09:55:29 2009 +0900 @@ -158,6 +158,9 @@ static void vioapic_write_redirent( pent->fields.remote_irr = 1; vioapic_deliver(vioapic, idx); } + + if ( idx == hvm_isa_irq_to_gsi(0) && !top_word ) + pt_freeze_pit_timer_if_irqmasked(d); spin_unlock(&d->arch.hvm_domain.irq_lock); } diff -r d2a32e24fe50 xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Wed Sep 09 16:39:41 2009 +0100 +++ b/xen/arch/x86/hvm/vlapic.c Thu Sep 10 09:55:29 2009 +0900 @@ -655,6 +655,8 @@ static int vlapic_write(struct vcpu *v, vlapic_set_reg(vlapic, offset, val); if ( offset == APIC_LVT0 ) vlapic_adjust_i8259_target(v->domain); + if ( offset == APIC_LVTT ) + pt_freeze_lapic_timer_if_irqmasked(&vlapic->pt); break; case APIC_TMICT: @@ -770,10 +772,13 @@ void vlapic_adjust_i8259_target(struct d v = d->vcpu ? d->vcpu[0] : NULL; found: - if ( d->arch.hvm_domain.i8259_target == v ) - return; - d->arch.hvm_domain.i8259_target = v; - pt_adjust_global_vcpu_target(v); + if ( d->arch.hvm_domain.i8259_target != v ) + { + d->arch.hvm_domain.i8259_target = v; + pt_adjust_global_vcpu_target(v); + } + + pt_freeze_pit_timer_if_irqmasked(d); } int vlapic_has_pending_irq(struct vcpu *v) @@ -934,6 +939,7 @@ static int lapic_load_regs(struct domain vlapic_adjust_i8259_target(d); lapic_rearm(s); + pt_freeze_lapic_timer_if_irqmasked(&s->pt); return 0; } diff -r d2a32e24fe50 xen/arch/x86/hvm/vpt.c --- a/xen/arch/x86/hvm/vpt.c Wed Sep 09 16:39:41 2009 +0100 +++ b/xen/arch/x86/hvm/vpt.c Thu Sep 10 09:55:29 2009 +0900 @@ -211,6 +211,10 @@ static void pt_timer_fn(void *data) pt_process_missed_ticks(pt); set_timer(&pt->timer, pt->scheduled); } + else + { + pt->frozen_by_irqmask = 0; + } if ( !pt_irq_masked(pt) ) vcpu_kick(pt->vcpu); @@ -394,6 +398,7 @@ void create_periodic_time( pt->on_list = 1; list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); + pt->frozen_by_irqmask = 0; init_timer(&pt->timer, pt_timer_fn, pt, v->processor); set_timer(&pt->timer, pt->scheduled); @@ -411,6 +416,7 @@ void destroy_periodic_time(struct period if ( pt->on_list ) list_del(&pt->list); pt->on_list = 0; + pt->frozen_by_irqmask = 0; pt_unlock(pt); /* @@ -469,3 +475,75 @@ void pt_adjust_global_vcpu_target(struct pt_adjust_vcpu(&pl_time->vhpet.pt[i], v); spin_unlock(&pl_time->vhpet.lock); } + + +static void pt_freeze_timer(struct periodic_time *pt) +{ + struct vcpu *v = NULL; + + pt_lock(pt); + if ( pt->on_list ) + { + v = pt->vcpu; + pt->frozen_by_irqmask = 1; + pt->on_list = 0; + list_del(&pt->list); + stop_timer(&pt->timer); + } + pt_unlock(pt); + + if ( v ) + gdprintk(XENLOG_INFO, "vcpu%d freeze %s timer(irq=%d)\n", v->vcpu_id, + pt->source == PTSRC_lapic ? "LAPIC" : "ISA", pt->irq); +} + +static void pt_thaw_timer(struct periodic_time *pt) +{ + struct vcpu *v = NULL; + + pt_lock(pt); + if ( !pt->on_list && pt->frozen_by_irqmask ) + { + v = pt->vcpu; + pt->on_list = 1; + list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); + migrate_timer(&pt->timer, v->processor); + /* + * It may set the past time, however, TIMER_SOFTIRQ is raised + * and pt_timer_fn() will reset the timer appropriately. + */ + set_timer(&pt->timer, pt->scheduled); + } + pt->frozen_by_irqmask = 0; + pt_unlock(pt); + + if ( v ) + gdprintk(XENLOG_INFO, "vcpu%d thaw %s timer(irq=%d)\n", v->vcpu_id, + pt->source == PTSRC_lapic ? "LAPIC" : "ISA", pt->irq); +} + +void pt_freeze_pit_timer_if_irqmasked(struct domain *d) +{ + struct periodic_time *pt = &d->arch.hvm_domain.pl_time.vpit.pt0; + unsigned int gsi = hvm_isa_irq_to_gsi(pt->irq); + + if ( pt->vcpu == NULL ) + return; + + if ( !vlapic_accept_pic_intr(pt->vcpu) && + domain_vioapic(d)->redirtbl[gsi].fields.mask ) + pt_freeze_timer(pt); + else + pt_thaw_timer(pt); +} + +void pt_freeze_lapic_timer_if_irqmasked(struct periodic_time *pt) +{ + if ( pt->vcpu == NULL ) + return; + + if (vlapic_get_reg(vcpu_vlapic(pt->vcpu), APIC_LVTT) & APIC_LVT_MASKED) + pt_freeze_timer(pt); + else + pt_thaw_timer(pt); +} diff -r d2a32e24fe50 xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Wed Sep 09 16:39:41 2009 +0100 +++ b/xen/include/asm-x86/hvm/vpt.h Thu Sep 10 09:55:29 2009 +0900 @@ -44,6 +44,7 @@ struct periodic_time { bool_t do_not_freeze; bool_t irq_issued; bool_t warned_timeout_too_short; + bool_t frozen_by_irqmask; #define PTSRC_isa 1 /* ISA time source */ #define PTSRC_lapic 2 /* LAPIC time source */ u8 source; /* PTSRC_ */ @@ -145,7 +146,10 @@ void pt_adjust_global_vcpu_target(struct ((d)->arch.hvm_domain.i8259_target ? : (d)->vcpu ? (d)->vcpu[0] : NULL) /* Is given periodic timer active? */ -#define pt_active(pt) ((pt)->on_list) +#define pt_active(pt) ((pt)->on_list || (pt)->frozen_by_irqmask) + +void pt_freeze_pit_timer_if_irqmasked(struct domain *d); +void pt_freeze_lapic_timer_if_irqmasked(struct periodic_time *pt); /* * Create/destroy a periodic (or one-shot!) timer. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |