uint32_t msi_ad[3]; /* Shadow of address low, high and data */
} gentries[MAX_MSIX_ACC_ENTRIES];
struct rcu_head rcu;
- const struct pirq *pirq;
};
static DEFINE_RCU_READ_LOCK(msixtbl_rcu_lock);
void *virt;
unsigned int nr_entry, index;
int r = X86EMUL_UNHANDLEABLE;
- unsigned long flags, orig;
- struct irq_desc *desc;
if ( len != 4 || (address & 3) )
return r;
if ( !virt )
goto out;
- desc = pirq_spin_lock_irq_desc(entry->pirq, &flags);
- if ( !desc )
- goto out;
-
- if ( !desc->msi_desc )
- goto unlock;
-
+ /* Do not allow the mask bit to be changed. */
+#if 0 /* XXX
+ * As the mask bit is the only defined bit in the word, and as the
+ * host MSI-X code doesn't preserve the other bits anyway, doing
+ * this is pointless. So for now just discard the write (also
+ * saving us from having to determine the matching irq_desc).
+ */
+ spin_lock_irqsave(&desc->lock, flags);
orig = readl(virt);
-
- /*
- * Do not allow guest to modify MSI-X control bit if it is masked
- * by Xen. We'll only handle the case where Xen thinks that
- * bit is unmasked, but hardware has silently masked the bit
- * (in case of SR-IOV VF reset, etc). On the other hand, if Xen
- * thinks that the bit is masked, but it's really not,
- * we log a warning.
- */
- if ( desc->msi_desc->msi_attrib.masked )
- {
- if ( !(orig & PCI_MSIX_VECTOR_BITMASK) )
- printk(XENLOG_WARNING "MSI-X control bit is unmasked when"
- " it is expected to be masked [%04x:%02x:%02x.%01x]\n",
- entry->pdev->seg, entry->pdev->bus,
- PCI_SLOT(entry->pdev->devfn),
- PCI_FUNC(entry->pdev->devfn));
-
- goto unlock;
- }
-
- /*
- * The mask bit is the only defined bit in the word. But we
- * ought to preserve the reserved bits. Clearing the reserved
- * bits can result in undefined behaviour (see PCI Local Bus
- * Specification revision 2.3).
- */
- val &= PCI_MSIX_VECTOR_BITMASK;
- val |= (orig & ~PCI_MSIX_VECTOR_BITMASK);
+ val &= ~PCI_MSIX_VECTOR_BITMASK;
+ val |= orig & PCI_MSIX_VECTOR_BITMASK;
writel(val, virt);
-
-unlock:
spin_unlock_irqrestore(&desc->lock, flags);
- r = X86EMUL_OKAY;
+#endif
+ r = X86EMUL_OKAY;
out:
rcu_read_unlock(&msixtbl_rcu_lock);
return r;
static void add_msixtbl_entry(struct domain *d,
struct pci_dev *pdev,
uint64_t gtable,
- struct msixtbl_entry *entry,
- const struct pirq *pirq)
+ struct msixtbl_entry *entry)
{
u32 len;
entry->table_len = len;
entry->pdev = pdev;
entry->gtable = (unsigned long) gtable;
- entry->pirq = pirq;
list_add_rcu(&entry->list, &d->arch.hvm_domain.msixtbl_list);
}
entry = new_entry;
new_entry = NULL;
- add_msixtbl_entry(d, pdev, gtable, entry, pirq);
+ add_msixtbl_entry(d, pdev, gtable, entry);
found:
- ASSERT(entry->pirq == pirq);
atomic_inc(&entry->refcnt);
spin_unlock(&d->arch.hvm_domain.msixtbl_list_lock);
r = 0;