aboutsummaryrefslogtreecommitdiffstats
path: root/main/xen/xsa337-1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/xen/xsa337-1.patch')
-rw-r--r--main/xen/xsa337-1.patch87
1 files changed, 87 insertions, 0 deletions
diff --git a/main/xen/xsa337-1.patch b/main/xen/xsa337-1.patch
new file mode 100644
index 0000000000..eae4185a84
--- /dev/null
+++ b/main/xen/xsa337-1.patch
@@ -0,0 +1,87 @@
+From: Roger Pau Monné <roger.pau@citrix.com>
+Subject: x86/msi: get rid of read_msi_msg
+
+It's safer and faster to just use the cached last written
+(untranslated) MSI message stored in msi_desc for the single user that
+calls read_msi_msg.
+
+This also prevents relying on the data read from the device MSI
+registers in order to figure out the index into the IOMMU interrupt
+remapping table, which is not safe.
+
+This is part of XSA-337.
+
+Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Requested-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/arch/x86/msi.c
++++ b/xen/arch/x86/msi.c
+@@ -185,54 +185,6 @@ void msi_compose_msg(unsigned vector, co
+ MSI_DATA_VECTOR(vector);
+ }
+
+-static bool read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
+-{
+- switch ( entry->msi_attrib.type )
+- {
+- case PCI_CAP_ID_MSI:
+- {
+- struct pci_dev *dev = entry->dev;
+- int pos = entry->msi_attrib.pos;
+- uint16_t data;
+-
+- msg->address_lo = pci_conf_read32(dev->sbdf,
+- msi_lower_address_reg(pos));
+- if ( entry->msi_attrib.is_64 )
+- {
+- msg->address_hi = pci_conf_read32(dev->sbdf,
+- msi_upper_address_reg(pos));
+- data = pci_conf_read16(dev->sbdf, msi_data_reg(pos, 1));
+- }
+- else
+- {
+- msg->address_hi = 0;
+- data = pci_conf_read16(dev->sbdf, msi_data_reg(pos, 0));
+- }
+- msg->data = data;
+- break;
+- }
+- case PCI_CAP_ID_MSIX:
+- {
+- void __iomem *base = entry->mask_base;
+-
+- if ( unlikely(!msix_memory_decoded(entry->dev,
+- entry->msi_attrib.pos)) )
+- return false;
+- msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+- msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+- msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET);
+- break;
+- }
+- default:
+- BUG();
+- }
+-
+- if ( iommu_intremap )
+- iommu_read_msi_from_ire(entry, msg);
+-
+- return true;
+-}
+-
+ static int write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
+ {
+ entry->msg = *msg;
+@@ -304,10 +256,7 @@ void set_msi_affinity(struct irq_desc *d
+
+ ASSERT(spin_is_locked(&desc->lock));
+
+- memset(&msg, 0, sizeof(msg));
+- if ( !read_msi_msg(msi_desc, &msg) )
+- return;
+-
++ msg = msi_desc->msg;
+ msg.data &= ~MSI_DATA_VECTOR_MASK;
+ msg.data |= MSI_DATA_VECTOR(desc->arch.vector);
+ msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;