From 3b24c34cbfafd3b068f6ca2350da521ba0301d7d Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Mon, 19 Nov 2018 15:59:50 -0800 Subject: [PATCH] hv: msix: corrently determine when the guest is changing Message Data/Addr The guest could write the MSI-X Table fields in DWORD or QWORD. For example the Message Address could be a QWORD write or two DWORD writes, the Message Data could be a DWORD write or part of a QWORD write that is combined with the Vector Control. This patch captures all the possible combinations when the guest is configuring the MSI-X Table. Tracked-On: #1568 Signed-off-by: Zide Chen Reviewed-by: Li, Fei1 --- hypervisor/dm/vpci/msix.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/hypervisor/dm/vpci/msix.c b/hypervisor/dm/vpci/msix.c index 50c3df3d3..9c2da0646 100644 --- a/hypervisor/dm/vpci/msix.c +++ b/hypervisor/dm/vpci/msix.c @@ -217,10 +217,22 @@ static void vmsix_table_rw(struct pci_vdev *vdev, struct mmio_request *mmio, uin /* Save for comparison */ vector_control = entry->vector_control; - /* Writing different value to Message Data/Addr? */ - if (((offsetof(struct msix_table_entry, addr) == entry_offset) && (entry->addr != mmio->value)) || - ((offsetof(struct msix_table_entry, data) == entry_offset) && (entry->data != (uint32_t)mmio->value))) { - message_changed = true; + /* + * Writing different value to Message Data/Addr? + * PCI Spec: Software is permitted to fill in MSI-X Table entry DWORD fields individually + * with DWORD writes, or software in certain cases is permitted to fill in appropriate pairs + * of DWORDs with a single QWORD write + */ + if (entry_offset < offsetof(struct msix_table_entry, data)) { + uint64_t qword_mask = ~0UL; + if (mmio->size == 4U) { + qword_mask = (entry_offset == 0U) ? 0x00000000FFFFFFFFUL : 0xFFFFFFFF00000000UL; + } + message_changed = ((entry->addr & qword_mask) != (mmio->value & qword_mask)); + } else { + if (entry_offset == offsetof(struct msix_table_entry, data)) { + message_changed = (entry->data != (uint32_t)mmio->value); + } } /* Write to pci_vdev */