Author: jhb
Date: Mon Apr 27 22:27:35 2020
New Revision: 360399
URL: https://svnweb.freebsd.org/changeset/base/360399

Log:
  Update the cached MSI state when any MSI capability register is written.
  
  bhyve uses cached copies of the MSI capability registers to generate
  MSI interrupts for device models.  Previously, these cached fields
  were only set when the MSI capability control register was updated.
  The Linux kernel recently adopted a change to deal with races in MSI
  interrupt delivery that writes to the MSI capability address and data
  registers to alter the destination of MSI interrupts without writing
  to the MSI capability control register.  bhyve was not updating its
  cached registers for these writes and continued to send interrupts
  with the old data value to the old address.  Fix this by recomputing
  the cached values for every write to any MSI capability register.
  
  Reported by:  Jason Tubnor, Ryan Moeller
  Reported by:  Marc Dionne (bisected the Linux kernel commit)
  Reviewed by:  grehan
  MFC after:    1 week
  Differential Revision:        https://reviews.freebsd.org/D24593

Modified:
  head/usr.sbin/bhyve/pci_emul.c

Modified: head/usr.sbin/bhyve/pci_emul.c
==============================================================================
--- head/usr.sbin/bhyve/pci_emul.c      Mon Apr 27 22:02:44 2020        
(r360398)
+++ head/usr.sbin/bhyve/pci_emul.c      Mon Apr 27 22:27:35 2020        
(r360399)
@@ -915,26 +915,26 @@ msicap_cfgwrite(struct pci_devinst *pi, int capoff, in
                msgctrl &= ~rwmask;
                msgctrl |= val & rwmask;
                val = msgctrl;
+       }
+       CFGWRITE(pi, offset, val, bytes);
 
-               addrlo = pci_get_cfgdata32(pi, capoff + 4);
-               if (msgctrl & PCIM_MSICTRL_64BIT)
-                       msgdata = pci_get_cfgdata16(pi, capoff + 12);
-               else
-                       msgdata = pci_get_cfgdata16(pi, capoff + 8);
+       msgctrl = pci_get_cfgdata16(pi, capoff + 2);
+       addrlo = pci_get_cfgdata32(pi, capoff + 4);
+       if (msgctrl & PCIM_MSICTRL_64BIT)
+               msgdata = pci_get_cfgdata16(pi, capoff + 12);
+       else
+               msgdata = pci_get_cfgdata16(pi, capoff + 8);
 
-               mme = msgctrl & PCIM_MSICTRL_MME_MASK;
-               pi->pi_msi.enabled = msgctrl & PCIM_MSICTRL_MSI_ENABLE ? 1 : 0;
-               if (pi->pi_msi.enabled) {
-                       pi->pi_msi.addr = addrlo;
-                       pi->pi_msi.msg_data = msgdata;
-                       pi->pi_msi.maxmsgnum = 1 << (mme >> 4);
-               } else {
-                       pi->pi_msi.maxmsgnum = 0;
-               }
-               pci_lintr_update(pi);
+       mme = msgctrl & PCIM_MSICTRL_MME_MASK;
+       pi->pi_msi.enabled = msgctrl & PCIM_MSICTRL_MSI_ENABLE ? 1 : 0;
+       if (pi->pi_msi.enabled) {
+               pi->pi_msi.addr = addrlo;
+               pi->pi_msi.msg_data = msgdata;
+               pi->pi_msi.maxmsgnum = 1 << (mme >> 4);
+       } else {
+               pi->pi_msi.maxmsgnum = 0;
        }
-
-       CFGWRITE(pi, offset, val, bytes);
+       pci_lintr_update(pi);
 }
 
 void
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to