[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: Automatically EOI guest-bound interrupts if guest takes too long.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1282466228 -3600 # Node ID 59ff5820534f4c5ec006d1ddca0f4356634c3b22 # Parent f77261710856aad506dda92cfa3b92b923be4e15 x86: Automatically EOI guest-bound interrupts if guest takes too long. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/irq.c | 69 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 59 insertions(+), 10 deletions(-) diff -r f77261710856 -r 59ff5820534f xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Fri Aug 20 17:12:00 2010 +0100 +++ b/xen/arch/x86/irq.c Sun Aug 22 09:37:08 2010 +0100 @@ -793,13 +793,55 @@ static void _irq_guest_eoi(struct irq_de desc->handler->enable(irq); } +static void set_eoi_ready(void *data); + static void irq_guest_eoi_timer_fn(void *data) { struct irq_desc *desc = data; + unsigned int irq = desc - irq_desc; + irq_guest_action_t *action; + cpumask_t cpu_eoi_map; unsigned long flags; spin_lock_irqsave(&desc->lock, flags); - _irq_guest_eoi(desc); + + if ( !(desc->status & IRQ_GUEST) ) + goto out; + + action = (irq_guest_action_t *)desc->action; + + if ( action->ack_type != ACKTYPE_NONE ) + { + unsigned int i; + for ( i = 0; i < action->nr_guests; i++ ) + { + struct domain *d = action->guest[i]; + unsigned int pirq = domain_irq_to_pirq(d, irq); + if ( test_and_clear_bit(pirq, d->pirq_mask) ) + action->in_flight--; + } + } + + if ( action->in_flight != 0 ) + goto out; + + switch ( action->ack_type ) + { + case ACKTYPE_UNMASK: + desc->handler->end(irq); + break; + case ACKTYPE_EOI: + cpu_eoi_map = action->cpu_eoi_map; + spin_unlock_irq(&desc->lock); + on_selected_cpus(&cpu_eoi_map, set_eoi_ready, desc, 0); + spin_lock_irq(&desc->lock); + break; + case ACKTYPE_NONE: + _irq_guest_eoi(desc); + break; + } + + out: spin_unlock_irqrestore(&desc->lock, flags); } @@ -856,9 +898,11 @@ static void __do_IRQ_guest(int irq) } } - if ( already_pending == action->nr_guests ) - { - stop_timer(&action->eoi_timer); + stop_timer(&action->eoi_timer); + + if ( (action->ack_type == ACKTYPE_NONE) && + (already_pending == action->nr_guests) ) + { desc->handler->disable(irq); desc->status |= IRQ_GUEST_EOI_PENDING; for ( i = 0; i < already_pending; ++i ) @@ -874,9 +918,10 @@ static void __do_IRQ_guest(int irq) * - skip the timer setup below. */ } - migrate_timer(&action->eoi_timer, smp_processor_id()); - set_timer(&action->eoi_timer, NOW() + MILLISECS(1)); - } + } + + migrate_timer(&action->eoi_timer, smp_processor_id()); + set_timer(&action->eoi_timer, NOW() + MILLISECS(1)); } /* @@ -1315,9 +1360,7 @@ static irq_guest_action_t *__pirq_guest_ BUG_ON(!cpus_empty(action->cpu_eoi_map)); desc->action = NULL; - desc->status &= ~IRQ_GUEST; - desc->status &= ~IRQ_INPROGRESS; - kill_timer(&action->eoi_timer); + desc->status &= ~(IRQ_GUEST|IRQ_GUEST_EOI_PENDING|IRQ_INPROGRESS); desc->handler->shutdown(irq); /* Caller frees the old guest descriptor block. */ @@ -1351,7 +1394,10 @@ void pirq_guest_unbind(struct domain *d, spin_unlock_irq(&desc->lock); if ( oldaction != NULL ) + { + kill_timer(&oldaction->eoi_timer); xfree(oldaction); + } } static int pirq_guest_force_unbind(struct domain *d, int irq) @@ -1389,7 +1435,10 @@ static int pirq_guest_force_unbind(struc spin_unlock_irq(&desc->lock); if ( oldaction != NULL ) + { + kill_timer(&oldaction->eoi_timer); xfree(oldaction); + } return bound; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |