diff options
Diffstat (limited to 'hw/vfio')
-rw-r--r-- | hw/vfio/pci.c | 88 |
1 files changed, 37 insertions, 51 deletions
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 73d34b9b2e..77f92f1e97 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1508,44 +1508,29 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque, { VFIOQuirk *quirk = opaque; VFIOPCIDevice *vdev = quirk->vdev; + uint64_t val = 0; + + if (!quirk->data.flags) { /* Non-MSI-X table access */ + return vfio_region_read(&vdev->bars[quirk->data.bar].region, + addr + 0x70, size); + } switch (addr) { case 4: /* address */ - if (quirk->data.flags) { - trace_vfio_rtl8168_window_quirk_read_fake( - memory_region_name(&quirk->mem), - vdev->vbasedev.name); - - return quirk->data.address_match ^ 0x80000000U; - } + val = quirk->data.address_match ^ 0x80000000U; /* latch/complete */ break; case 0: /* data */ - if (quirk->data.flags) { - uint64_t val; - - trace_vfio_rtl8168_window_quirk_read_table( - memory_region_name(&quirk->mem), - vdev->vbasedev.name); - - if (!(vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) { - return 0; - } - + if ((vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) { memory_region_dispatch_read(&vdev->pdev.msix_table_mmio, - (hwaddr)(quirk->data.address_match - & 0xfff), - &val, - size, - MEMTXATTRS_UNSPECIFIED); - return val; + (hwaddr)(quirk->data.address_match & 0xfff), + &val, size, MEMTXATTRS_UNSPECIFIED); } + break; } - trace_vfio_rtl8168_window_quirk_read_direct(memory_region_name(&quirk->mem), - vdev->vbasedev.name); - - return vfio_region_read(&vdev->bars[quirk->data.bar].region, - addr + 0x70, size); + trace_vfio_rtl8168_quirk_read(vdev->vbasedev.name, + addr ? "address" : "data", val); + return val; } static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr, @@ -1556,36 +1541,36 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr, switch (addr) { case 4: /* address */ - if ((data & 0x7fff0000) == 0x10000) { - if (data & 0x80000000U && - vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) { - - trace_vfio_rtl8168_window_quirk_write_table( - memory_region_name(&quirk->mem), - vdev->vbasedev.name); - - memory_region_dispatch_write(&vdev->pdev.msix_table_mmio, - (hwaddr)(data & 0xfff), - (uint64_t)quirk->data.address_mask, - size, MEMTXATTRS_UNSPECIFIED); - } - - quirk->data.flags = 1; + if ((data & 0x7fff0000) == 0x10000) { /* MSI-X table */ + quirk->data.flags = 1; /* Activate reads */ quirk->data.address_match = data; - return; + trace_vfio_rtl8168_quirk_write(vdev->vbasedev.name, data); + + if (data & 0x80000000U) { /* Do write */ + if (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) { + hwaddr offset = data & 0xfff; + uint64_t val = quirk->data.address_mask; + + trace_vfio_rtl8168_quirk_msix(vdev->vbasedev.name, + (uint16_t)offset, val); + + /* Write to the proper guest MSI-X table instead */ + memory_region_dispatch_write(&vdev->pdev.msix_table_mmio, + offset, val, size, + MEMTXATTRS_UNSPECIFIED); + } + return; /* Do not write guest MSI-X data to hardware */ + } + } else { + quirk->data.flags = 0; /* De-activate reads, non-MSI-X */ } - quirk->data.flags = 0; break; case 0: /* data */ quirk->data.address_mask = data; break; } - trace_vfio_rtl8168_window_quirk_write_direct( - memory_region_name(&quirk->mem), - vdev->vbasedev.name); - vfio_region_write(&vdev->bars[quirk->data.bar].region, addr + 0x70, data, size); } @@ -1622,8 +1607,9 @@ static void vfio_probe_rtl8168_bar2_window_quirk(VFIOPCIDevice *vdev, int nr) QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); - trace_vfio_probe_rtl8168_bar2_window_quirk(vdev->vbasedev.name); + trace_vfio_rtl8168_quirk_enable(vdev->vbasedev.name); } + /* * Trap the BAR2 MMIO window to config space as well. */ |