diff -r 19970181d6a4 xen/arch/x86/msi.c --- a/xen/arch/x86/msi.c Tue Jul 01 14:50:35 2008 +0100 +++ b/xen/arch/x86/msi.c Wed Jul 02 13:43:42 2008 +0800 @@ -435,14 +435,6 @@ xfree(entry); } -void msi_free_vectors(struct pci_dev* dev) -{ - struct msi_desc *entry, *tmp; - - list_for_each_entry_safe( entry, tmp, &dev->msi_list, list ) - msi_free_vector(entry->vector); -} - static struct msi_desc *find_msi_entry(struct pci_dev *dev, int vector, int cap_id) { @@ -790,16 +782,40 @@ __pci_disable_msix(vector); } +extern struct hw_interrupt_type pci_msi_type; +static void msi_free_vectors(struct pci_dev* dev) +{ + struct msi_desc *entry, *tmp; + irq_desc_t *desc; + unsigned long flags; + + list_for_each_entry_safe( entry, tmp, &dev->msi_list, list ) + { + desc = &irq_desc[entry->vector]; + + spin_lock_irqsave(&desc->lock, flags); + if ( desc->handler == &pci_msi_type ) + { + /* MSI is not shared, so should be released already */ + BUG_ON(desc->status & IRQ_GUEST); + desc->handler = &no_irq_type; + } + spin_unlock_irqrestore(&desc->lock, flags); + + msi_free_vector(entry->vector); + } +} + void pci_cleanup_msi(u8 bus, u8 devfn) { struct pci_dev *dev = get_msi_pdev(bus, devfn); if ( !dev ) return; - msi_free_vectors(dev); /* Disable MSI and/or MSI-X */ msi_set_enable(dev, 0); msix_set_enable(dev, 0); + msi_free_vectors(dev); } diff -r 19970181d6a4 xen/drivers/passthrough/io.c --- a/xen/drivers/passthrough/io.c Tue Jul 01 14:50:35 2008 +0100 +++ b/xen/drivers/passthrough/io.c Wed Jul 02 13:43:42 2008 +0800 @@ -75,13 +75,18 @@ { int pirq = pt_irq_bind->machine_irq; + if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_VALID ) ) + { + hvm_irq_dpci->mirq[pirq].flags |= HVM_IRQ_DPCI_VALID | + HVM_IRQ_DPCI_MSI ; + pirq_guest_bind(d->vcpu[0], pirq, 0); + } + hvm_irq_dpci->mirq[pirq].flags |= HVM_IRQ_DPCI_VALID |HVM_IRQ_DPCI_MSI ; hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec; hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags; - hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = pirq; - pirq_guest_bind(d->vcpu[0], pirq, BIND_PIRQ__WILL_SHARE); } else {