Blob Blame History Raw
xen/MSI: don't open-code pass-through of enable bit modifications

Without this the actual XSA-131 fix would cause the enable bit to not
get set anymore (due to the write back getting suppressed there based
on the OR of emu_mask, ro_mask, and res_mask).

Note that the fiddling with the enable bit shouldn't really be done by
qemu, but making this work right (via libxc and the hypervisor) will
require more extensive changes, which can be postponed until after the
security issue got addressed.

This is a preparatory patch for XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

--- a/tools/qemu-xen-traditional/hw/pass-through.c
+++ b/tools/qemu-xen-traditional/hw/pass-through.c
@@ -648,7 +648,7 @@ static struct pt_reg_info_tbl pt_emu_reg
         .size       = 2,
         .init_val   = 0x0000,
         .ro_mask    = 0xFF8E,
-        .emu_mask   = 0x017F,
+        .emu_mask   = 0x017E,
         .init       = pt_msgctrl_reg_init,
         .u.w.read   = pt_word_reg_read,
         .u.w.write  = pt_msgctrl_reg_write,
@@ -3901,6 +3901,9 @@ static int pt_msgctrl_reg_write(struct p
 
     /* modify emulate register */
     writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
+    /* also emulate MSI_ENABLE bit for MSI-INTx translation */
+    if (ptdev->msi_trans_en)
+        writable_mask |= PCI_MSI_FLAGS_ENABLE & valid_mask;
     cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask);
     /* update the msi_info too */
     ptdev->msi->flags |= cfg_entry->data &
@@ -3909,6 +3912,9 @@ static int pt_msgctrl_reg_write(struct p
     /* create value for writing to I/O device register */
     val = *value;
     throughable_mask = ~reg->emu_mask & valid_mask;
+    /* don't pass through MSI_ENABLE bit for MSI-INTx translation */
+    if (ptdev->msi_trans_en)
+        throughable_mask &= ~PCI_MSI_FLAGS_ENABLE;
     *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
 
     /* update MSI */
@@ -3952,12 +3958,6 @@ static int pt_msgctrl_reg_write(struct p
         }
     }
 
-    /* pass through MSI_ENABLE bit when no MSI-INTx translation */
-    if (!ptdev->msi_trans_en) {
-        *value &= ~PCI_MSI_FLAGS_ENABLE;
-        *value |= val & PCI_MSI_FLAGS_ENABLE;
-    }
-
     return 0;
 }