--- a/qemu/upstream/hw/xen/xen_pt.h
+++ b/qemu/upstream/hw/xen/xen_pt.h
@@ -181,6 +181,7 @@ typedef struct XenPTMSIXEntry {
 typedef struct XenPTMSIX {
     uint32_t ctrl_offset;
     bool enabled;
+    bool maskall;
     int total_entries;
     int bar_index;
     uint64_t table_base;
@@ -293,7 +294,9 @@ int xen_pt_msix_init(XenPCIPassthroughSt
 void xen_pt_msix_delete(XenPCIPassthroughState *s);
 int xen_pt_msix_update(XenPCIPassthroughState *s);
 int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index);
+void xen_pt_msix_enable(XenPCIPassthroughState *s);
 void xen_pt_msix_disable(XenPCIPassthroughState *s);
+int xen_pt_msix_maskall(XenPCIPassthroughState *s, bool mask);
 
 static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
 {
--- a/qemu/upstream/hw/xen/xen_pt_config_init.c
+++ b/qemu/upstream/hw/xen/xen_pt_config_init.c
@@ -1436,32 +1436,58 @@ static int xen_pt_msixctrl_reg_write(Xen
                                      uint16_t dev_value, uint16_t valid_mask)
 {
     XenPTRegInfo *reg = cfg_entry->reg;
-    uint16_t writable_mask = 0;
+    uint16_t writable_mask, value;
     uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
     int debug_msix_enabled_old;
 
     /* modify emulate register */
     writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
-    cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
+    value = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
+    cfg_entry->data = value;
 
     /* create value for writing to I/O device register */
     *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
 
+    debug_msix_enabled_old = s->msix->enabled;
+
     /* update MSI-X */
-    if ((*val & PCI_MSIX_FLAGS_ENABLE)
-        && !(*val & PCI_MSIX_FLAGS_MASKALL)) {
+    if ((value & PCI_MSIX_FLAGS_ENABLE)
+        && !(value & PCI_MSIX_FLAGS_MASKALL)) {
+        if (!s->msix->enabled) {
+            if (!s->msix->maskall) {
+                xen_pt_msix_maskall(s, true);
+            }
+            xen_pt_msix_enable(s);
+        }
         xen_pt_msix_update(s);
-    } else if (!(*val & PCI_MSIX_FLAGS_ENABLE) && s->msix->enabled) {
-        xen_pt_msix_disable(s);
+        s->msix->enabled = true;
+        s->msix->maskall = false;
+        xen_pt_msix_maskall(s, false);
+    } else if (s->msix->enabled) {
+        if (!(value & PCI_MSIX_FLAGS_ENABLE)) {
+            xen_pt_msix_disable(s);
+            s->msix->enabled = false;
+        } else if (!s->msix->maskall) {
+            s->msix->maskall = true;
+            xen_pt_msix_maskall(s, true);
+        }
     }
 
-    debug_msix_enabled_old = s->msix->enabled;
-    s->msix->enabled = !!(*val & PCI_MSIX_FLAGS_ENABLE);
     if (s->msix->enabled != debug_msix_enabled_old) {
         XEN_PT_LOG(&s->dev, "%s MSI-X\n",
                    s->msix->enabled ? "enable" : "disable");
     }
 
+    xen_host_pci_get_word(&s->real_device, s->msix->ctrl_offset, &dev_value);
+
+    if (s->msix->enabled && !(dev_value & PCI_MSIX_FLAGS_ENABLE)) {
+        XEN_PT_ERR(&s->dev, "MSI-X unexpectedly disabled\n");
+    } else if ((dev_value & PCI_MSIX_FLAGS_ENABLE) &&
+               s->msix->maskall &&
+               !(dev_value & PCI_MSIX_FLAGS_MASKALL)) {
+        XEN_PT_ERR(&s->dev, "MSI-X unexpectedly unmasked\n");
+    }
+
     return 0;
 }
 
@@ -1483,9 +1509,12 @@ static XenPTRegInfo xen_pt_emu_reg_msix[
         .offset     = PCI_MSI_FLAGS,
         .size       = 2,
         .init_val   = 0x0000,
-        .res_mask   = 0x3800,
-        .ro_mask    = 0x07FF,
-        .emu_mask   = 0x0000,
+        /* This must not be split into res_mask (0x3800) and ro_mask (0x07FF)
+         * because even in permissive mode there must not be any write back
+         * to this register.
+         */
+        .ro_mask    = 0x3FFF,
+        .emu_mask   = 0xC000,
         .init       = xen_pt_msixctrl_reg_init,
         .u.w.read   = xen_pt_word_reg_read,
         .u.w.write  = xen_pt_msixctrl_reg_write,
--- a/qemu/upstream/hw/xen/xen_pt_msi.c
+++ b/qemu/upstream/hw/xen/xen_pt_msi.c
@@ -301,8 +301,11 @@ static int msix_set_enable(XenPCIPassthr
         return -1;
     }
 
-    return msi_msix_enable(s, s->msix->ctrl_offset, PCI_MSIX_FLAGS_ENABLE,
-                           enabled);
+    return xc_physdev_msix_enable(xen_xc, s->real_device.domain,
+                                  s->real_device.bus,
+                                  PCI_DEVFN(s->real_device.dev,
+                                            s->real_device.func),
+                                  enabled);
 }
 
 static int xen_pt_msix_update_one(XenPCIPassthroughState *s, int entry_nr)
@@ -361,6 +364,11 @@ int xen_pt_msix_update(XenPCIPassthrough
     return 0;
 }
 
+void xen_pt_msix_enable(XenPCIPassthroughState *s)
+{
+    msix_set_enable(s, true);
+}
+
 void xen_pt_msix_disable(XenPCIPassthroughState *s)
 {
     int i = 0;
@@ -378,6 +386,15 @@ void xen_pt_msix_disable(XenPCIPassthrou
     }
 }
 
+int xen_pt_msix_maskall(XenPCIPassthroughState *s, bool mask)
+{
+    return xc_physdev_msix_mask_all(xen_xc, s->real_device.domain,
+                                    s->real_device.bus,
+                                    PCI_DEVFN(s->real_device.dev,
+                                              s->real_device.func),
+                                    mask);
+}
+
 int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index)
 {
     XenPTMSIXEntry *entry;
