From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kouya Shimura Subject: [PATCH 2/2] x86 hvm: suspend platform timer emulation while its IRQ is masked Date: Wed, 16 Sep 2009 15:53:18 +0900 Message-ID: <7kljkfcrdi.fsf@pingu.sky.yk.fujitsu.co.jp> References: <7kd45z6s6z.fsf@pingu.sky.yk.fujitsu.co.jp> <7kocpbcrow.fsf@pingu.sky.yk.fujitsu.co.jp> <7kmy4vcri8.fsf@pingu.sky.yk.fujitsu.co.jp> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="97SoBuQg6S" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <7kmy4vcri8.fsf@pingu.sky.yk.fujitsu.co.jp> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com Cc: Keir Fraser List-Id: xen-devel@lists.xenproject.org --97SoBuQg6S Content-Type: text/plain; charset=us-ascii Content-Description: message body text Content-Transfer-Encoding: 7bit This patch gets rid of a timer which IRQ is masked from vcpu's timer list. It reduces the overhead of VM EXIT and context switch of vm. Also fixes a potential bug. (1) VCPU#0: mask the IRQ of a timer. (ex. vioapic.redir[2].mask=1) (2) VCPU#1: pt_timer_fn() is invoked by expiration of the timer. (3) VCPU#1: pt_update_irq() is called but does nothing by pt_irq_masked()=1. (4) VCPU#1: sleep by halt. (5) VCPU#0: unmask the IRQ of the timer. After that, no one wakes up the VCPU#1. IRQ of ISA is masked by: - PIC's IMR - IOAPIC's redir[0] - IOAPIC's redir[N].mask - LAPIC's LVT0 - LAPIC enabled/disabled IRQ of LAPIC timer is masked by: - LAPIC's LVTT - LAPIC disabled When above stuffs are changed, the corresponding vcpu is kicked and suspended timer emulation is resumed. In addition, a small bug fix in pt_adjust_global_vcpu_target(). Signed-off-by: Kouya Shimura --97SoBuQg6S Content-Type: text/x-patch Content-Disposition: inline; filename="vpt2.patch" Content-Transfer-Encoding: 7bit # HG changeset patch # User Kouya Shimura # Date 1253080328 -32400 # Node ID b62a5e4c6125e62fd5fd1e28f7ae1c8a093b689d # Parent 58ef1439ca982cdd2f7e4698ce9bdba1f4b38853 x86 hvm: suspend platform timer emulation while its IRQ is masked This patch gets rid of a timer which IRQ is masked from vcpu's timer list. It reduces the overhead of VM EXIT and context switch of vm. Also fixes a potential bug. (1) VCPU#0: mask the IRQ of a timer. (ex. vioapic.redir[2].mask=1) (2) VCPU#1: pt_timer_fn() is invoked by expiration of the timer. (3) VCPU#1: pt_update_irq() is called but does nothing by pt_irq_masked()=1. (4) VCPU#1: sleep by halt. (5) VCPU#0: unmask the IRQ of the timer. After that, no one wakes up the VCPU#1. IRQ of ISA is masked by: - PIC's IMR - IOAPIC's redir[0] - IOAPIC's redir[N].mask - LAPIC's LVT0 - LAPIC enabled/disabled IRQ of LAPIC timer is masked by: - LAPIC's LVTT - LAPIC disabled When above stuffs are changed, the corresponding vcpu is kicked and suspended timer emulation is resumed. In addition, a small bug fix in pt_adjust_global_vcpu_target(). Signed-off-by: Kouya Shimura diff -r 58ef1439ca98 -r b62a5e4c6125 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Tue Sep 15 10:08:12 2009 +0100 +++ b/xen/arch/x86/hvm/vioapic.c Wed Sep 16 14:52:08 2009 +0900 @@ -125,6 +125,7 @@ static void vioapic_write_redirent( struct domain *d = vioapic_domain(vioapic); struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; union vioapic_redir_entry *pent, ent; + int unmasked = 0; spin_lock(&d->arch.hvm_domain.irq_lock); @@ -138,10 +139,12 @@ static void vioapic_write_redirent( } else { + unmasked = ent.fields.mask; /* Remote IRR and Delivery Status are read-only. */ ent.bits = ((ent.bits >> 32) << 32) | val; ent.fields.delivery_status = 0; ent.fields.remote_irr = pent->fields.remote_irr; + unmasked = unmasked && !ent.fields.mask; } *pent = ent; @@ -160,6 +163,9 @@ static void vioapic_write_redirent( } spin_unlock(&d->arch.hvm_domain.irq_lock); + + if ( idx == 0 || unmasked ) + pt_may_unmask_irq(d, NULL); } static void vioapic_write_indirect( diff -r 58ef1439ca98 -r b62a5e4c6125 xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Tue Sep 15 10:08:12 2009 +0100 +++ b/xen/arch/x86/hvm/vlapic.c Wed Sep 16 14:52:08 2009 +0900 @@ -624,7 +624,10 @@ static int vlapic_write(struct vcpu *v, } } else + { vlapic->hw.disabled &= ~VLAPIC_SW_DISABLED; + pt_may_unmask_irq(vlapic_domain(vlapic), &vlapic->pt); + } break; case APIC_ESR: @@ -654,7 +657,12 @@ static int vlapic_write(struct vcpu *v, val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4]; vlapic_set_reg(vlapic, offset, val); if ( offset == APIC_LVT0 ) + { vlapic_adjust_i8259_target(v->domain); + pt_may_unmask_irq(v->domain, NULL); + } + if ( (offset == APIC_LVTT) && !(val & APIC_LVT_MASKED) ) + pt_may_unmask_irq(NULL, &vlapic->pt); break; case APIC_TMICT: @@ -719,10 +727,12 @@ void vlapic_msr_set(struct vlapic *vlapi { vlapic_reset(vlapic); vlapic->hw.disabled &= ~VLAPIC_HW_DISABLED; + pt_may_unmask_irq(vlapic_domain(vlapic), &vlapic->pt); } else { vlapic->hw.disabled |= VLAPIC_HW_DISABLED; + pt_may_unmask_irq(vlapic_domain(vlapic), NULL); } } diff -r 58ef1439ca98 -r b62a5e4c6125 xen/arch/x86/hvm/vpic.c --- a/xen/arch/x86/hvm/vpic.c Tue Sep 15 10:08:12 2009 +0100 +++ b/xen/arch/x86/hvm/vpic.c Wed Sep 16 14:52:08 2009 +0900 @@ -178,7 +178,7 @@ static void vpic_ioport_write( struct hvm_hw_vpic *vpic, uint32_t addr, uint32_t val) { int priority, cmd, irq; - uint8_t mask; + uint8_t mask, unmasked = 0; vpic_lock(vpic); @@ -190,6 +190,7 @@ static void vpic_ioport_write( /* Clear edge-sensing logic. */ vpic->irr &= vpic->elcr; + unmasked = vpic->imr; /* No interrupts masked or in service. */ vpic->imr = vpic->isr = 0; @@ -268,6 +269,7 @@ static void vpic_ioport_write( { case 0: /* OCW1 */ + unmasked = vpic->imr & (~val); vpic->imr = val; break; case 1: @@ -295,6 +297,9 @@ static void vpic_ioport_write( vpic_update_int_output(vpic); vpic_unlock(vpic); + + if ( unmasked ) + pt_may_unmask_irq(vpic_domain(vpic), NULL); } static uint32_t vpic_ioport_read(struct hvm_hw_vpic *vpic, uint32_t addr) diff -r 58ef1439ca98 -r b62a5e4c6125 xen/arch/x86/hvm/vpt.c --- a/xen/arch/x86/hvm/vpt.c Tue Sep 15 10:08:12 2009 +0100 +++ b/xen/arch/x86/hvm/vpt.c Wed Sep 16 14:52:08 2009 +0900 @@ -221,19 +221,30 @@ void pt_update_irq(struct vcpu *v) void pt_update_irq(struct vcpu *v) { struct list_head *head = &v->arch.hvm_vcpu.tm_list; - struct periodic_time *pt, *earliest_pt = NULL; + struct periodic_time *pt, *temp, *earliest_pt = NULL; uint64_t max_lag = -1ULL; int irq, is_lapic; spin_lock(&v->arch.hvm_vcpu.tm_lock); - list_for_each_entry ( pt, head, list ) + list_for_each_entry_safe ( pt, temp, head, list ) { - if ( pt->pending_intr_nr && !pt_irq_masked(pt) && - ((pt->last_plt_gtime + pt->period) < max_lag) ) + if ( pt->pending_intr_nr ) { - max_lag = pt->last_plt_gtime + pt->period; - earliest_pt = pt; + if ( pt_irq_masked(pt) ) + { + /* suspend timer emulation */ + list_del(&pt->list); + pt->on_list = 0; + } + else + { + if ( (pt->last_plt_gtime + pt->period) < max_lag ) + { + max_lag = pt->last_plt_gtime + pt->period; + earliest_pt = pt; + } + } } } @@ -411,6 +422,7 @@ void destroy_periodic_time(struct period if ( pt->on_list ) list_del(&pt->list); pt->on_list = 0; + pt->pending_intr_nr = 0; pt_unlock(pt); /* @@ -450,11 +462,13 @@ static void pt_adjust_vcpu(struct period void pt_adjust_global_vcpu_target(struct vcpu *v) { - struct pl_time *pl_time = &v->domain->arch.hvm_domain.pl_time; + struct pl_time *pl_time; int i; if ( v == NULL ) return; + + pl_time = &v->domain->arch.hvm_domain.pl_time; spin_lock(&pl_time->vpit.lock); pt_adjust_vcpu(&pl_time->vpit.pt0, v); @@ -469,3 +483,35 @@ 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_resume(struct periodic_time *pt) +{ + if ( pt->vcpu == NULL ) + return; + + pt_lock(pt); + if ( pt->pending_intr_nr && !pt->on_list ) + { + pt->on_list = 1; + list_add(&pt->list, &pt->vcpu->arch.hvm_vcpu.tm_list); + vcpu_kick(pt->vcpu); + } + pt_unlock(pt); +} + +void pt_may_unmask_irq(struct domain *d, struct periodic_time *vlapic_pt) +{ + int i; + + if ( d ) + { + pt_resume(&d->arch.hvm_domain.pl_time.vpit.pt0); + pt_resume(&d->arch.hvm_domain.pl_time.vrtc.pt); + for ( i = 0; i < HPET_TIMER_NUM; i++ ) + pt_resume(&d->arch.hvm_domain.pl_time.vhpet.pt[i]); + } + + if ( vlapic_pt ) + pt_resume(vlapic_pt); +} diff -r 58ef1439ca98 -r b62a5e4c6125 xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Tue Sep 15 10:08:12 2009 +0100 +++ b/xen/include/asm-x86/hvm/vpt.h Wed Sep 16 14:52:08 2009 +0900 @@ -144,8 +144,10 @@ void pt_adjust_global_vcpu_target(struct #define pt_global_vcpu_target(d) \ ((d)->arch.hvm_domain.i8259_target ? : (d)->vcpu ? (d)->vcpu[0] : NULL) +void pt_may_unmask_irq(struct domain *d, struct periodic_time *vlapic_pt); + /* Is given periodic timer active? */ -#define pt_active(pt) ((pt)->on_list) +#define pt_active(pt) ((pt)->on_list || (pt)->pending_intr_nr) /* * Create/destroy a periodic (or one-shot!) timer. --97SoBuQg6S Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --97SoBuQg6S--