diff -r ec6d1ed854fb xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Thu Jul 03 10:47:27 2008 +0800 +++ b/xen/arch/x86/hvm/vlapic.c Thu Jul 03 11:26:54 2008 +0800 @@ -413,9 +413,8 @@ if ( vlapic_test_and_clear_vector(vector, &vlapic->regs->data[APIC_TMR]) ) vioapic_update_EOI(vlapic_domain(vlapic), vector); - - if ( iommu_enabled ) - hvm_dpci_msi_eoi(current->domain, vector); + + hvm_dpci_msi_eoi(current->domain, vector); } static int vlapic_ipi( diff -r ec6d1ed854fb xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Thu Jul 03 10:47:27 2008 +0800 +++ b/xen/arch/x86/irq.c Thu Jul 03 11:26:54 2008 +0800 @@ -48,6 +48,20 @@ end_none }; +static void irq_timer_fn(void *data) +{ + irq_desc_t *desc = data; + unsigned vector = desc - irq_desc; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + + desc->status &= ~IRQ_INPROGRESS; + desc->handler->enable(vector); + + spin_unlock_irqrestore(&desc->lock, flags); +} + atomic_t irq_err_count; asmlinkage void do_IRQ(struct cpu_user_regs *regs) @@ -59,6 +73,21 @@ perfc_incr(irqs); spin_lock(&desc->lock); + + if ( unlikely(desc->status & IRQ_INPROGRESS) ) + { + desc->handler->disable(vector); + desc->handler->ack(vector); + if ( !desc->timer ) + { + desc->timer = xmalloc(struct timer); + init_timer(desc->timer, irq_timer_fn, desc, smp_processor_id()); + } + set_timer(desc->timer, NOW() + MILLISECS(1)); + spin_unlock(&desc->lock); + return; + } + desc->handler->ack(vector); if ( likely(desc->status & IRQ_GUEST) ) @@ -206,8 +235,11 @@ irq_desc_t *desc = &irq_desc[vector]; irq_guest_action_t *action = (irq_guest_action_t *)desc->action; struct domain *d; - int i, sp; + int i, sp, is_hvm_edge_irq = 0; struct pending_eoi *peoi = this_cpu(pending_eoi); + + if ( action->ack_type == ACKTYPE_NONE ) + desc->status |= IRQ_INPROGRESS; if ( unlikely(action->nr_guests == 0) ) { @@ -239,8 +271,12 @@ action->in_flight++; if (!hvm_do_IRQ_dpci(d, irq)) send_guest_pirq(d, irq); + else + is_hvm_edge_irq = action->ack_type == ACKTYPE_NONE; + } - } + if ( !is_hvm_edge_irq ) + desc->status &= ~IRQ_INPROGRESS; } /* Flush all ready EOIs from the top of this CPU's pending-EOI stack. */ diff -r ec6d1ed854fb xen/drivers/passthrough/io.c --- a/xen/drivers/passthrough/io.c Thu Jul 03 10:47:27 2008 +0800 +++ b/xen/drivers/passthrough/io.c Thu Jul 03 11:26:54 2008 +0800 @@ -220,15 +220,26 @@ { struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; int pirq; + unsigned long flags; + irq_desc_t *desc; if ( !iommu_enabled || (hvm_irq_dpci == NULL) ) return; pirq = hvm_irq_dpci->msi_gvec_pirq[vector]; + if ( ( pirq >= 0 ) && (pirq < NR_PIRQS) && (hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_VALID) && (hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MSI) ) - pirq_guest_eoi(d, pirq); + { + int vec; + vec = domain_irq_to_vector(d, pirq); + desc = &irq_desc[vec]; + + spin_lock_irqsave(&desc->lock, flags); + desc->status &= ~IRQ_INPROGRESS; + spin_unlock_irqrestore(&desc->lock, flags); + } } void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, diff -r ec6d1ed854fb xen/include/xen/irq.h --- a/xen/include/xen/irq.h Thu Jul 03 10:47:27 2008 +0800 +++ b/xen/include/xen/irq.h Thu Jul 03 11:26:54 2008 +0800 @@ -56,6 +56,7 @@ unsigned int status; /* IRQ status */ hw_irq_controller *handler; struct msi_desc *msi_desc; + struct timer *timer; struct irqaction *action; /* IRQ action list */ unsigned int depth; /* nested irq disables */ spinlock_t lock;