aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2020-04-27 22:27:35 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2020-04-27 22:27:35 +0000
commit7840d1c45fc01dde62d6feb58e332cb71b534cc5 (patch)
tree5dbb468594f501effc57048080da75a334511265 /usr.sbin
parent45818bf1a0fae8b5b13def517953d4a3d9d19257 (diff)
downloadsrc-7840d1c45fc01dde62d6feb58e332cb71b534cc5.tar.gz
src-7840d1c45fc01dde62d6feb58e332cb71b534cc5.zip
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
Notes
Notes: svn path=/head/; revision=360399
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bhyve/pci_emul.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index 036aaeb5ed92..145b33b5ffd2 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -915,26 +915,26 @@ msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
msgctrl &= ~rwmask;
msgctrl |= val & rwmask;
val = msgctrl;
-
- 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);
}
-
CFGWRITE(pi, offset, val, bytes);
+
+ 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);
}
void