1c00d61d8SAlex Williamson /* 2c00d61d8SAlex Williamson * device quirks for PCI devices 3c00d61d8SAlex Williamson * 4c00d61d8SAlex Williamson * Copyright Red Hat, Inc. 2012-2015 5c00d61d8SAlex Williamson * 6c00d61d8SAlex Williamson * Authors: 7c00d61d8SAlex Williamson * Alex Williamson <alex.williamson@redhat.com> 8c00d61d8SAlex Williamson * 9c00d61d8SAlex Williamson * This work is licensed under the terms of the GNU GPL, version 2. See 10c00d61d8SAlex Williamson * the COPYING file in the top-level directory. 11c00d61d8SAlex Williamson */ 12c00d61d8SAlex Williamson 13c00d61d8SAlex Williamson #include "pci.h" 14c00d61d8SAlex Williamson #include "trace.h" 15c00d61d8SAlex Williamson #include "qemu/range.h" 16c00d61d8SAlex Williamson 17*056dfcb6SAlex Williamson #define PCI_ANY_ID (~0) 18*056dfcb6SAlex Williamson 19*056dfcb6SAlex Williamson /* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */ 20*056dfcb6SAlex Williamson static bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device) 21*056dfcb6SAlex Williamson { 22*056dfcb6SAlex Williamson PCIDevice *pdev = &vdev->pdev; 23*056dfcb6SAlex Williamson 24*056dfcb6SAlex Williamson return (vendor == PCI_ANY_ID || 25*056dfcb6SAlex Williamson vendor == pci_get_word(pdev->config + PCI_VENDOR_ID)) && 26*056dfcb6SAlex Williamson (device == PCI_ANY_ID || 27*056dfcb6SAlex Williamson device == pci_get_word(pdev->config + PCI_DEVICE_ID)); 28*056dfcb6SAlex Williamson } 29*056dfcb6SAlex Williamson 30c00d61d8SAlex Williamson /* 31c00d61d8SAlex Williamson * List of device ids/vendor ids for which to disable 32c00d61d8SAlex Williamson * option rom loading. This avoids the guest hangs during rom 33c00d61d8SAlex Williamson * execution as noticed with the BCM 57810 card for lack of a 34c00d61d8SAlex Williamson * more better way to handle such issues. 35c00d61d8SAlex Williamson * The user can still override by specifying a romfile or 36c00d61d8SAlex Williamson * rombar=1. 37c00d61d8SAlex Williamson * Please see https://bugs.launchpad.net/qemu/+bug/1284874 38c00d61d8SAlex Williamson * for an analysis of the 57810 card hang. When adding 39c00d61d8SAlex Williamson * a new vendor id/device id combination below, please also add 40c00d61d8SAlex Williamson * your card/environment details and information that could 41c00d61d8SAlex Williamson * help in debugging to the bug tracking this issue 42c00d61d8SAlex Williamson */ 43*056dfcb6SAlex Williamson static const struct { 44*056dfcb6SAlex Williamson uint32_t vendor; 45*056dfcb6SAlex Williamson uint32_t device; 46*056dfcb6SAlex Williamson } romblacklist[] = { 47*056dfcb6SAlex Williamson { 0x14e4, 0x168e }, /* Broadcom BCM 57810 */ 48c00d61d8SAlex Williamson }; 49c00d61d8SAlex Williamson 50c00d61d8SAlex Williamson bool vfio_blacklist_opt_rom(VFIOPCIDevice *vdev) 51c00d61d8SAlex Williamson { 52*056dfcb6SAlex Williamson int i; 53c00d61d8SAlex Williamson 54*056dfcb6SAlex Williamson for (i = 0 ; i < ARRAY_SIZE(romblacklist); i++) { 55*056dfcb6SAlex Williamson if (vfio_pci_is(vdev, romblacklist[i].vendor, romblacklist[i].device)) { 56*056dfcb6SAlex Williamson trace_vfio_quirk_rom_blacklisted(vdev->vbasedev.name, 57*056dfcb6SAlex Williamson romblacklist[i].vendor, 58*056dfcb6SAlex Williamson romblacklist[i].device); 59c00d61d8SAlex Williamson return true; 60c00d61d8SAlex Williamson } 61c00d61d8SAlex Williamson } 62c00d61d8SAlex Williamson return false; 63c00d61d8SAlex Williamson } 64c00d61d8SAlex Williamson 65c00d61d8SAlex Williamson /* 66c00d61d8SAlex Williamson * Device specific quirks 67c00d61d8SAlex Williamson */ 68c00d61d8SAlex Williamson 69c00d61d8SAlex Williamson /* Is range1 fully contained within range2? */ 70c00d61d8SAlex Williamson static bool vfio_range_contained(uint64_t first1, uint64_t len1, 71c00d61d8SAlex Williamson uint64_t first2, uint64_t len2) { 72c00d61d8SAlex Williamson return (first1 >= first2 && first1 + len1 <= first2 + len2); 73c00d61d8SAlex Williamson } 74c00d61d8SAlex Williamson 75c00d61d8SAlex Williamson static bool vfio_flags_enabled(uint8_t flags, uint8_t mask) 76c00d61d8SAlex Williamson { 77c00d61d8SAlex Williamson return (mask && (flags & mask) == mask); 78c00d61d8SAlex Williamson } 79c00d61d8SAlex Williamson 80c00d61d8SAlex Williamson static uint64_t vfio_generic_window_quirk_read(void *opaque, 81c00d61d8SAlex Williamson hwaddr addr, unsigned size) 82c00d61d8SAlex Williamson { 83c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 84c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 85c00d61d8SAlex Williamson uint64_t data; 86c00d61d8SAlex Williamson 87c00d61d8SAlex Williamson if (vfio_flags_enabled(quirk->data.flags, quirk->data.read_flags) && 88c00d61d8SAlex Williamson ranges_overlap(addr, size, 89c00d61d8SAlex Williamson quirk->data.data_offset, quirk->data.data_size)) { 90c00d61d8SAlex Williamson hwaddr offset = addr - quirk->data.data_offset; 91c00d61d8SAlex Williamson 92c00d61d8SAlex Williamson if (!vfio_range_contained(addr, size, quirk->data.data_offset, 93c00d61d8SAlex Williamson quirk->data.data_size)) { 94c00d61d8SAlex Williamson hw_error("%s: window data read not fully contained: %s", 95c00d61d8SAlex Williamson __func__, memory_region_name(&quirk->mem)); 96c00d61d8SAlex Williamson } 97c00d61d8SAlex Williamson 98c00d61d8SAlex Williamson data = vfio_pci_read_config(&vdev->pdev, 99c00d61d8SAlex Williamson quirk->data.address_val + offset, size); 100c00d61d8SAlex Williamson 101c00d61d8SAlex Williamson trace_vfio_generic_window_quirk_read(memory_region_name(&quirk->mem), 102c00d61d8SAlex Williamson vdev->vbasedev.name, 103c00d61d8SAlex Williamson quirk->data.bar, 104c00d61d8SAlex Williamson addr, size, data); 105c00d61d8SAlex Williamson } else { 106c00d61d8SAlex Williamson data = vfio_region_read(&vdev->bars[quirk->data.bar].region, 107c00d61d8SAlex Williamson addr + quirk->data.base_offset, size); 108c00d61d8SAlex Williamson } 109c00d61d8SAlex Williamson 110c00d61d8SAlex Williamson return data; 111c00d61d8SAlex Williamson } 112c00d61d8SAlex Williamson 113c00d61d8SAlex Williamson static void vfio_generic_window_quirk_write(void *opaque, hwaddr addr, 114c00d61d8SAlex Williamson uint64_t data, unsigned size) 115c00d61d8SAlex Williamson { 116c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 117c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 118c00d61d8SAlex Williamson 119c00d61d8SAlex Williamson if (ranges_overlap(addr, size, 120c00d61d8SAlex Williamson quirk->data.address_offset, quirk->data.address_size)) { 121c00d61d8SAlex Williamson 122c00d61d8SAlex Williamson if (addr != quirk->data.address_offset) { 123c00d61d8SAlex Williamson hw_error("%s: offset write into address window: %s", 124c00d61d8SAlex Williamson __func__, memory_region_name(&quirk->mem)); 125c00d61d8SAlex Williamson } 126c00d61d8SAlex Williamson 127c00d61d8SAlex Williamson if ((data & ~quirk->data.address_mask) == quirk->data.address_match) { 128c00d61d8SAlex Williamson quirk->data.flags |= quirk->data.write_flags | 129c00d61d8SAlex Williamson quirk->data.read_flags; 130c00d61d8SAlex Williamson quirk->data.address_val = data & quirk->data.address_mask; 131c00d61d8SAlex Williamson } else { 132c00d61d8SAlex Williamson quirk->data.flags &= ~(quirk->data.write_flags | 133c00d61d8SAlex Williamson quirk->data.read_flags); 134c00d61d8SAlex Williamson } 135c00d61d8SAlex Williamson } 136c00d61d8SAlex Williamson 137c00d61d8SAlex Williamson if (vfio_flags_enabled(quirk->data.flags, quirk->data.write_flags) && 138c00d61d8SAlex Williamson ranges_overlap(addr, size, 139c00d61d8SAlex Williamson quirk->data.data_offset, quirk->data.data_size)) { 140c00d61d8SAlex Williamson hwaddr offset = addr - quirk->data.data_offset; 141c00d61d8SAlex Williamson 142c00d61d8SAlex Williamson if (!vfio_range_contained(addr, size, quirk->data.data_offset, 143c00d61d8SAlex Williamson quirk->data.data_size)) { 144c00d61d8SAlex Williamson hw_error("%s: window data write not fully contained: %s", 145c00d61d8SAlex Williamson __func__, memory_region_name(&quirk->mem)); 146c00d61d8SAlex Williamson } 147c00d61d8SAlex Williamson 148c00d61d8SAlex Williamson vfio_pci_write_config(&vdev->pdev, 149c00d61d8SAlex Williamson quirk->data.address_val + offset, data, size); 150c00d61d8SAlex Williamson trace_vfio_generic_window_quirk_write(memory_region_name(&quirk->mem), 151c00d61d8SAlex Williamson vdev->vbasedev.name, 152c00d61d8SAlex Williamson quirk->data.bar, 153c00d61d8SAlex Williamson addr, data, size); 154c00d61d8SAlex Williamson return; 155c00d61d8SAlex Williamson } 156c00d61d8SAlex Williamson 157c00d61d8SAlex Williamson vfio_region_write(&vdev->bars[quirk->data.bar].region, 158c00d61d8SAlex Williamson addr + quirk->data.base_offset, data, size); 159c00d61d8SAlex Williamson } 160c00d61d8SAlex Williamson 161c00d61d8SAlex Williamson static const MemoryRegionOps vfio_generic_window_quirk = { 162c00d61d8SAlex Williamson .read = vfio_generic_window_quirk_read, 163c00d61d8SAlex Williamson .write = vfio_generic_window_quirk_write, 164c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 165c00d61d8SAlex Williamson }; 166c00d61d8SAlex Williamson 167c00d61d8SAlex Williamson static uint64_t vfio_generic_quirk_read(void *opaque, 168c00d61d8SAlex Williamson hwaddr addr, unsigned size) 169c00d61d8SAlex Williamson { 170c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 171c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 172c00d61d8SAlex Williamson hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK; 173c00d61d8SAlex Williamson hwaddr offset = quirk->data.address_match & ~TARGET_PAGE_MASK; 174c00d61d8SAlex Williamson uint64_t data; 175c00d61d8SAlex Williamson 176c00d61d8SAlex Williamson if (vfio_flags_enabled(quirk->data.flags, quirk->data.read_flags) && 177c00d61d8SAlex Williamson ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) { 178c00d61d8SAlex Williamson if (!vfio_range_contained(addr, size, offset, 179c00d61d8SAlex Williamson quirk->data.address_mask + 1)) { 180c00d61d8SAlex Williamson hw_error("%s: read not fully contained: %s", 181c00d61d8SAlex Williamson __func__, memory_region_name(&quirk->mem)); 182c00d61d8SAlex Williamson } 183c00d61d8SAlex Williamson 184c00d61d8SAlex Williamson data = vfio_pci_read_config(&vdev->pdev, addr - offset, size); 185c00d61d8SAlex Williamson 186c00d61d8SAlex Williamson trace_vfio_generic_quirk_read(memory_region_name(&quirk->mem), 187c00d61d8SAlex Williamson vdev->vbasedev.name, quirk->data.bar, 188c00d61d8SAlex Williamson addr + base, size, data); 189c00d61d8SAlex Williamson } else { 190c00d61d8SAlex Williamson data = vfio_region_read(&vdev->bars[quirk->data.bar].region, 191c00d61d8SAlex Williamson addr + base, size); 192c00d61d8SAlex Williamson } 193c00d61d8SAlex Williamson 194c00d61d8SAlex Williamson return data; 195c00d61d8SAlex Williamson } 196c00d61d8SAlex Williamson 197c00d61d8SAlex Williamson static void vfio_generic_quirk_write(void *opaque, hwaddr addr, 198c00d61d8SAlex Williamson uint64_t data, unsigned size) 199c00d61d8SAlex Williamson { 200c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 201c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 202c00d61d8SAlex Williamson hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK; 203c00d61d8SAlex Williamson hwaddr offset = quirk->data.address_match & ~TARGET_PAGE_MASK; 204c00d61d8SAlex Williamson 205c00d61d8SAlex Williamson if (vfio_flags_enabled(quirk->data.flags, quirk->data.write_flags) && 206c00d61d8SAlex Williamson ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) { 207c00d61d8SAlex Williamson if (!vfio_range_contained(addr, size, offset, 208c00d61d8SAlex Williamson quirk->data.address_mask + 1)) { 209c00d61d8SAlex Williamson hw_error("%s: write not fully contained: %s", 210c00d61d8SAlex Williamson __func__, memory_region_name(&quirk->mem)); 211c00d61d8SAlex Williamson } 212c00d61d8SAlex Williamson 213c00d61d8SAlex Williamson vfio_pci_write_config(&vdev->pdev, addr - offset, data, size); 214c00d61d8SAlex Williamson 215c00d61d8SAlex Williamson trace_vfio_generic_quirk_write(memory_region_name(&quirk->mem), 216c00d61d8SAlex Williamson vdev->vbasedev.name, quirk->data.bar, 217c00d61d8SAlex Williamson addr + base, data, size); 218c00d61d8SAlex Williamson } else { 219c00d61d8SAlex Williamson vfio_region_write(&vdev->bars[quirk->data.bar].region, 220c00d61d8SAlex Williamson addr + base, data, size); 221c00d61d8SAlex Williamson } 222c00d61d8SAlex Williamson } 223c00d61d8SAlex Williamson 224c00d61d8SAlex Williamson static const MemoryRegionOps vfio_generic_quirk = { 225c00d61d8SAlex Williamson .read = vfio_generic_quirk_read, 226c00d61d8SAlex Williamson .write = vfio_generic_quirk_write, 227c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 228c00d61d8SAlex Williamson }; 229c00d61d8SAlex Williamson 230c00d61d8SAlex Williamson #define PCI_VENDOR_ID_ATI 0x1002 231c00d61d8SAlex Williamson 232c00d61d8SAlex Williamson /* 233c00d61d8SAlex Williamson * Radeon HD cards (HD5450 & HD7850) report the upper byte of the I/O port BAR 234c00d61d8SAlex Williamson * through VGA register 0x3c3. On newer cards, the I/O port BAR is always 235c00d61d8SAlex Williamson * BAR4 (older cards like the X550 used BAR1, but we don't care to support 236c00d61d8SAlex Williamson * those). Note that on bare metal, a read of 0x3c3 doesn't always return the 237c00d61d8SAlex Williamson * I/O port BAR address. Originally this was coded to return the virtual BAR 238c00d61d8SAlex Williamson * address only if the physical register read returns the actual BAR address, 239c00d61d8SAlex Williamson * but users have reported greater success if we return the virtual address 240c00d61d8SAlex Williamson * unconditionally. 241c00d61d8SAlex Williamson */ 242c00d61d8SAlex Williamson static uint64_t vfio_ati_3c3_quirk_read(void *opaque, 243c00d61d8SAlex Williamson hwaddr addr, unsigned size) 244c00d61d8SAlex Williamson { 245c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 246c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 247c00d61d8SAlex Williamson uint64_t data = vfio_pci_read_config(&vdev->pdev, 248c00d61d8SAlex Williamson PCI_BASE_ADDRESS_0 + (4 * 4) + 1, 249c00d61d8SAlex Williamson size); 250c00d61d8SAlex Williamson trace_vfio_ati_3c3_quirk_read(data); 251c00d61d8SAlex Williamson 252c00d61d8SAlex Williamson return data; 253c00d61d8SAlex Williamson } 254c00d61d8SAlex Williamson 255c00d61d8SAlex Williamson static const MemoryRegionOps vfio_ati_3c3_quirk = { 256c00d61d8SAlex Williamson .read = vfio_ati_3c3_quirk_read, 257c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 258c00d61d8SAlex Williamson }; 259c00d61d8SAlex Williamson 260c00d61d8SAlex Williamson static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice *vdev) 261c00d61d8SAlex Williamson { 262c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 263c00d61d8SAlex Williamson VFIOQuirk *quirk; 264c00d61d8SAlex Williamson 265c00d61d8SAlex Williamson if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { 266c00d61d8SAlex Williamson return; 267c00d61d8SAlex Williamson } 268c00d61d8SAlex Williamson 269c00d61d8SAlex Williamson /* 270c00d61d8SAlex Williamson * As long as the BAR is >= 256 bytes it will be aligned such that the 271c00d61d8SAlex Williamson * lower byte is always zero. Filter out anything else, if it exists. 272c00d61d8SAlex Williamson */ 273c00d61d8SAlex Williamson if (!vdev->bars[4].ioport || vdev->bars[4].region.size < 256) { 274c00d61d8SAlex Williamson return; 275c00d61d8SAlex Williamson } 276c00d61d8SAlex Williamson 277c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 278c00d61d8SAlex Williamson quirk->vdev = vdev; 279c00d61d8SAlex Williamson 280c00d61d8SAlex Williamson memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, quirk, 281c00d61d8SAlex Williamson "vfio-ati-3c3-quirk", 1); 282c00d61d8SAlex Williamson memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 283c00d61d8SAlex Williamson 3 /* offset 3 bytes from 0x3c0 */, &quirk->mem); 284c00d61d8SAlex Williamson 285c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, 286c00d61d8SAlex Williamson quirk, next); 287c00d61d8SAlex Williamson 288c00d61d8SAlex Williamson trace_vfio_vga_probe_ati_3c3_quirk(vdev->vbasedev.name); 289c00d61d8SAlex Williamson } 290c00d61d8SAlex Williamson 291c00d61d8SAlex Williamson /* 292c00d61d8SAlex Williamson * Newer ATI/AMD devices, including HD5450 and HD7850, have a window to PCI 293c00d61d8SAlex Williamson * config space through MMIO BAR2 at offset 0x4000. Nothing seems to access 294c00d61d8SAlex Williamson * the MMIO space directly, but a window to this space is provided through 295c00d61d8SAlex Williamson * I/O port BAR4. Offset 0x0 is the address register and offset 0x4 is the 296c00d61d8SAlex Williamson * data register. When the address is programmed to a range of 0x4000-0x4fff 297c00d61d8SAlex Williamson * PCI configuration space is available. Experimentation seems to indicate 298c00d61d8SAlex Williamson * that only read-only access is provided, but we drop writes when the window 299c00d61d8SAlex Williamson * is enabled to config space nonetheless. 300c00d61d8SAlex Williamson */ 301c00d61d8SAlex Williamson static void vfio_probe_ati_bar4_window_quirk(VFIOPCIDevice *vdev, int nr) 302c00d61d8SAlex Williamson { 303c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 304c00d61d8SAlex Williamson VFIOQuirk *quirk; 305c00d61d8SAlex Williamson 306c00d61d8SAlex Williamson if (!vdev->has_vga || nr != 4 || 307c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { 308c00d61d8SAlex Williamson return; 309c00d61d8SAlex Williamson } 310c00d61d8SAlex Williamson 311c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 312c00d61d8SAlex Williamson quirk->vdev = vdev; 313c00d61d8SAlex Williamson quirk->data.address_size = 4; 314c00d61d8SAlex Williamson quirk->data.data_offset = 4; 315c00d61d8SAlex Williamson quirk->data.data_size = 4; 316c00d61d8SAlex Williamson quirk->data.address_match = 0x4000; 317c00d61d8SAlex Williamson quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; 318c00d61d8SAlex Williamson quirk->data.bar = nr; 319c00d61d8SAlex Williamson quirk->data.read_flags = quirk->data.write_flags = 1; 320c00d61d8SAlex Williamson 321c00d61d8SAlex Williamson memory_region_init_io(&quirk->mem, OBJECT(vdev), 322c00d61d8SAlex Williamson &vfio_generic_window_quirk, quirk, 323c00d61d8SAlex Williamson "vfio-ati-bar4-window-quirk", 8); 324c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 325c00d61d8SAlex Williamson quirk->data.base_offset, &quirk->mem, 1); 326c00d61d8SAlex Williamson 327c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 328c00d61d8SAlex Williamson 329c00d61d8SAlex Williamson trace_vfio_probe_ati_bar4_window_quirk(vdev->vbasedev.name); 330c00d61d8SAlex Williamson } 331c00d61d8SAlex Williamson 332c00d61d8SAlex Williamson /* 333c00d61d8SAlex Williamson * Trap the BAR2 MMIO window to config space as well. 334c00d61d8SAlex Williamson */ 335c00d61d8SAlex Williamson static void vfio_probe_ati_bar2_4000_quirk(VFIOPCIDevice *vdev, int nr) 336c00d61d8SAlex Williamson { 337c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 338c00d61d8SAlex Williamson VFIOQuirk *quirk; 339c00d61d8SAlex Williamson 340c00d61d8SAlex Williamson /* Only enable on newer devices where BAR2 is 64bit */ 341c00d61d8SAlex Williamson if (!vdev->has_vga || nr != 2 || !vdev->bars[2].mem64 || 342c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { 343c00d61d8SAlex Williamson return; 344c00d61d8SAlex Williamson } 345c00d61d8SAlex Williamson 346c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 347c00d61d8SAlex Williamson quirk->vdev = vdev; 348c00d61d8SAlex Williamson quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; 349c00d61d8SAlex Williamson quirk->data.address_match = 0x4000; 350c00d61d8SAlex Williamson quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; 351c00d61d8SAlex Williamson quirk->data.bar = nr; 352c00d61d8SAlex Williamson 353c00d61d8SAlex Williamson memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, quirk, 354c00d61d8SAlex Williamson "vfio-ati-bar2-4000-quirk", 355c00d61d8SAlex Williamson TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); 356c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 357c00d61d8SAlex Williamson quirk->data.address_match & TARGET_PAGE_MASK, 358c00d61d8SAlex Williamson &quirk->mem, 1); 359c00d61d8SAlex Williamson 360c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 361c00d61d8SAlex Williamson 362c00d61d8SAlex Williamson trace_vfio_probe_ati_bar2_4000_quirk(vdev->vbasedev.name); 363c00d61d8SAlex Williamson } 364c00d61d8SAlex Williamson 365c00d61d8SAlex Williamson /* 366c00d61d8SAlex Williamson * Older ATI/AMD cards like the X550 have a similar window to that above. 367c00d61d8SAlex Williamson * I/O port BAR1 provides a window to a mirror of PCI config space located 368c00d61d8SAlex Williamson * in BAR2 at offset 0xf00. We don't care to support such older cards, but 369c00d61d8SAlex Williamson * note it for future reference. 370c00d61d8SAlex Williamson */ 371c00d61d8SAlex Williamson 372c00d61d8SAlex Williamson #define PCI_VENDOR_ID_NVIDIA 0x10de 373c00d61d8SAlex Williamson 374c00d61d8SAlex Williamson /* 375c00d61d8SAlex Williamson * Nvidia has several different methods to get to config space, the 376c00d61d8SAlex Williamson * nouveu project has several of these documented here: 377c00d61d8SAlex Williamson * https://github.com/pathscale/envytools/tree/master/hwdocs 378c00d61d8SAlex Williamson * 379c00d61d8SAlex Williamson * The first quirk is actually not documented in envytools and is found 380c00d61d8SAlex Williamson * on 10de:01d1 (NVIDIA Corporation G72 [GeForce 7300 LE]). This is an 381c00d61d8SAlex Williamson * NV46 chipset. The backdoor uses the legacy VGA I/O ports to access 382c00d61d8SAlex Williamson * the mirror of PCI config space found at BAR0 offset 0x1800. The access 383c00d61d8SAlex Williamson * sequence first writes 0x338 to I/O port 0x3d4. The target offset is 384c00d61d8SAlex Williamson * then written to 0x3d0. Finally 0x538 is written for a read and 0x738 385c00d61d8SAlex Williamson * is written for a write to 0x3d4. The BAR0 offset is then accessible 386c00d61d8SAlex Williamson * through 0x3d0. This quirk doesn't seem to be necessary on newer cards 387c00d61d8SAlex Williamson * that use the I/O port BAR5 window but it doesn't hurt to leave it. 388c00d61d8SAlex Williamson */ 389c00d61d8SAlex Williamson enum { 390c00d61d8SAlex Williamson NV_3D0_NONE = 0, 391c00d61d8SAlex Williamson NV_3D0_SELECT, 392c00d61d8SAlex Williamson NV_3D0_WINDOW, 393c00d61d8SAlex Williamson NV_3D0_READ, 394c00d61d8SAlex Williamson NV_3D0_WRITE, 395c00d61d8SAlex Williamson }; 396c00d61d8SAlex Williamson 397c00d61d8SAlex Williamson static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque, 398c00d61d8SAlex Williamson hwaddr addr, unsigned size) 399c00d61d8SAlex Williamson { 400c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 401c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 402c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 403c00d61d8SAlex Williamson uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], 404c00d61d8SAlex Williamson addr + quirk->data.base_offset, size); 405c00d61d8SAlex Williamson 406c00d61d8SAlex Williamson if (quirk->data.flags == NV_3D0_READ && addr == quirk->data.data_offset) { 407c00d61d8SAlex Williamson data = vfio_pci_read_config(pdev, quirk->data.address_val, size); 408c00d61d8SAlex Williamson trace_vfio_nvidia_3d0_quirk_read(size, data); 409c00d61d8SAlex Williamson } 410c00d61d8SAlex Williamson 411c00d61d8SAlex Williamson quirk->data.flags = NV_3D0_NONE; 412c00d61d8SAlex Williamson 413c00d61d8SAlex Williamson return data; 414c00d61d8SAlex Williamson } 415c00d61d8SAlex Williamson 416c00d61d8SAlex Williamson static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr, 417c00d61d8SAlex Williamson uint64_t data, unsigned size) 418c00d61d8SAlex Williamson { 419c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 420c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 421c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 422c00d61d8SAlex Williamson 423c00d61d8SAlex Williamson switch (quirk->data.flags) { 424c00d61d8SAlex Williamson case NV_3D0_NONE: 425c00d61d8SAlex Williamson if (addr == quirk->data.address_offset && data == 0x338) { 426c00d61d8SAlex Williamson quirk->data.flags = NV_3D0_SELECT; 427c00d61d8SAlex Williamson } 428c00d61d8SAlex Williamson break; 429c00d61d8SAlex Williamson case NV_3D0_SELECT: 430c00d61d8SAlex Williamson quirk->data.flags = NV_3D0_NONE; 431c00d61d8SAlex Williamson if (addr == quirk->data.data_offset && 432c00d61d8SAlex Williamson (data & ~quirk->data.address_mask) == quirk->data.address_match) { 433c00d61d8SAlex Williamson quirk->data.flags = NV_3D0_WINDOW; 434c00d61d8SAlex Williamson quirk->data.address_val = data & quirk->data.address_mask; 435c00d61d8SAlex Williamson } 436c00d61d8SAlex Williamson break; 437c00d61d8SAlex Williamson case NV_3D0_WINDOW: 438c00d61d8SAlex Williamson quirk->data.flags = NV_3D0_NONE; 439c00d61d8SAlex Williamson if (addr == quirk->data.address_offset) { 440c00d61d8SAlex Williamson if (data == 0x538) { 441c00d61d8SAlex Williamson quirk->data.flags = NV_3D0_READ; 442c00d61d8SAlex Williamson } else if (data == 0x738) { 443c00d61d8SAlex Williamson quirk->data.flags = NV_3D0_WRITE; 444c00d61d8SAlex Williamson } 445c00d61d8SAlex Williamson } 446c00d61d8SAlex Williamson break; 447c00d61d8SAlex Williamson case NV_3D0_WRITE: 448c00d61d8SAlex Williamson quirk->data.flags = NV_3D0_NONE; 449c00d61d8SAlex Williamson if (addr == quirk->data.data_offset) { 450c00d61d8SAlex Williamson vfio_pci_write_config(pdev, quirk->data.address_val, data, size); 451c00d61d8SAlex Williamson trace_vfio_nvidia_3d0_quirk_write(data, size); 452c00d61d8SAlex Williamson return; 453c00d61d8SAlex Williamson } 454c00d61d8SAlex Williamson break; 455c00d61d8SAlex Williamson } 456c00d61d8SAlex Williamson 457c00d61d8SAlex Williamson vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], 458c00d61d8SAlex Williamson addr + quirk->data.base_offset, data, size); 459c00d61d8SAlex Williamson } 460c00d61d8SAlex Williamson 461c00d61d8SAlex Williamson static const MemoryRegionOps vfio_nvidia_3d0_quirk = { 462c00d61d8SAlex Williamson .read = vfio_nvidia_3d0_quirk_read, 463c00d61d8SAlex Williamson .write = vfio_nvidia_3d0_quirk_write, 464c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 465c00d61d8SAlex Williamson }; 466c00d61d8SAlex Williamson 467c00d61d8SAlex Williamson static void vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice *vdev) 468c00d61d8SAlex Williamson { 469c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 470c00d61d8SAlex Williamson VFIOQuirk *quirk; 471c00d61d8SAlex Williamson 472c00d61d8SAlex Williamson if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA || 473c00d61d8SAlex Williamson !vdev->bars[1].region.size) { 474c00d61d8SAlex Williamson return; 475c00d61d8SAlex Williamson } 476c00d61d8SAlex Williamson 477c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 478c00d61d8SAlex Williamson quirk->vdev = vdev; 479c00d61d8SAlex Williamson quirk->data.base_offset = 0x10; 480c00d61d8SAlex Williamson quirk->data.address_offset = 4; 481c00d61d8SAlex Williamson quirk->data.address_size = 2; 482c00d61d8SAlex Williamson quirk->data.address_match = 0x1800; 483c00d61d8SAlex Williamson quirk->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1; 484c00d61d8SAlex Williamson quirk->data.data_offset = 0; 485c00d61d8SAlex Williamson quirk->data.data_size = 4; 486c00d61d8SAlex Williamson 487c00d61d8SAlex Williamson memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_3d0_quirk, 488c00d61d8SAlex Williamson quirk, "vfio-nvidia-3d0-quirk", 6); 489c00d61d8SAlex Williamson memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 490c00d61d8SAlex Williamson quirk->data.base_offset, &quirk->mem); 491c00d61d8SAlex Williamson 492c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, 493c00d61d8SAlex Williamson quirk, next); 494c00d61d8SAlex Williamson 495c00d61d8SAlex Williamson trace_vfio_vga_probe_nvidia_3d0_quirk(vdev->vbasedev.name); 496c00d61d8SAlex Williamson } 497c00d61d8SAlex Williamson 498c00d61d8SAlex Williamson /* 499c00d61d8SAlex Williamson * The second quirk is documented in envytools. The I/O port BAR5 is just 500c00d61d8SAlex Williamson * a set of address/data ports to the MMIO BARs. The BAR we care about is 501c00d61d8SAlex Williamson * again BAR0. This backdoor is apparently a bit newer than the one above 502c00d61d8SAlex Williamson * so we need to not only trap 256 bytes @0x1800, but all of PCI config 503c00d61d8SAlex Williamson * space, including extended space is available at the 4k @0x88000. 504c00d61d8SAlex Williamson */ 505c00d61d8SAlex Williamson enum { 506c00d61d8SAlex Williamson NV_BAR5_ADDRESS = 0x1, 507c00d61d8SAlex Williamson NV_BAR5_ENABLE = 0x2, 508c00d61d8SAlex Williamson NV_BAR5_MASTER = 0x4, 509c00d61d8SAlex Williamson NV_BAR5_VALID = 0x7, 510c00d61d8SAlex Williamson }; 511c00d61d8SAlex Williamson 512c00d61d8SAlex Williamson static void vfio_nvidia_bar5_window_quirk_write(void *opaque, hwaddr addr, 513c00d61d8SAlex Williamson uint64_t data, unsigned size) 514c00d61d8SAlex Williamson { 515c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 516c00d61d8SAlex Williamson 517c00d61d8SAlex Williamson switch (addr) { 518c00d61d8SAlex Williamson case 0x0: 519c00d61d8SAlex Williamson if (data & 0x1) { 520c00d61d8SAlex Williamson quirk->data.flags |= NV_BAR5_MASTER; 521c00d61d8SAlex Williamson } else { 522c00d61d8SAlex Williamson quirk->data.flags &= ~NV_BAR5_MASTER; 523c00d61d8SAlex Williamson } 524c00d61d8SAlex Williamson break; 525c00d61d8SAlex Williamson case 0x4: 526c00d61d8SAlex Williamson if (data & 0x1) { 527c00d61d8SAlex Williamson quirk->data.flags |= NV_BAR5_ENABLE; 528c00d61d8SAlex Williamson } else { 529c00d61d8SAlex Williamson quirk->data.flags &= ~NV_BAR5_ENABLE; 530c00d61d8SAlex Williamson } 531c00d61d8SAlex Williamson break; 532c00d61d8SAlex Williamson case 0x8: 533c00d61d8SAlex Williamson if (quirk->data.flags & NV_BAR5_MASTER) { 534c00d61d8SAlex Williamson if ((data & ~0xfff) == 0x88000) { 535c00d61d8SAlex Williamson quirk->data.flags |= NV_BAR5_ADDRESS; 536c00d61d8SAlex Williamson quirk->data.address_val = data & 0xfff; 537c00d61d8SAlex Williamson } else if ((data & ~0xff) == 0x1800) { 538c00d61d8SAlex Williamson quirk->data.flags |= NV_BAR5_ADDRESS; 539c00d61d8SAlex Williamson quirk->data.address_val = data & 0xff; 540c00d61d8SAlex Williamson } else { 541c00d61d8SAlex Williamson quirk->data.flags &= ~NV_BAR5_ADDRESS; 542c00d61d8SAlex Williamson } 543c00d61d8SAlex Williamson } 544c00d61d8SAlex Williamson break; 545c00d61d8SAlex Williamson } 546c00d61d8SAlex Williamson 547c00d61d8SAlex Williamson vfio_generic_window_quirk_write(opaque, addr, data, size); 548c00d61d8SAlex Williamson } 549c00d61d8SAlex Williamson 550c00d61d8SAlex Williamson static const MemoryRegionOps vfio_nvidia_bar5_window_quirk = { 551c00d61d8SAlex Williamson .read = vfio_generic_window_quirk_read, 552c00d61d8SAlex Williamson .write = vfio_nvidia_bar5_window_quirk_write, 553c00d61d8SAlex Williamson .valid.min_access_size = 4, 554c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 555c00d61d8SAlex Williamson }; 556c00d61d8SAlex Williamson 557c00d61d8SAlex Williamson static void vfio_probe_nvidia_bar5_window_quirk(VFIOPCIDevice *vdev, int nr) 558c00d61d8SAlex Williamson { 559c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 560c00d61d8SAlex Williamson VFIOQuirk *quirk; 561c00d61d8SAlex Williamson 562c00d61d8SAlex Williamson if (!vdev->has_vga || nr != 5 || 563c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) { 564c00d61d8SAlex Williamson return; 565c00d61d8SAlex Williamson } 566c00d61d8SAlex Williamson 567c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 568c00d61d8SAlex Williamson quirk->vdev = vdev; 569c00d61d8SAlex Williamson quirk->data.read_flags = quirk->data.write_flags = NV_BAR5_VALID; 570c00d61d8SAlex Williamson quirk->data.address_offset = 0x8; 571c00d61d8SAlex Williamson quirk->data.address_size = 0; /* actually 4, but avoids generic code */ 572c00d61d8SAlex Williamson quirk->data.data_offset = 0xc; 573c00d61d8SAlex Williamson quirk->data.data_size = 4; 574c00d61d8SAlex Williamson quirk->data.bar = nr; 575c00d61d8SAlex Williamson 576c00d61d8SAlex Williamson memory_region_init_io(&quirk->mem, OBJECT(vdev), 577c00d61d8SAlex Williamson &vfio_nvidia_bar5_window_quirk, quirk, 578c00d61d8SAlex Williamson "vfio-nvidia-bar5-window-quirk", 16); 579c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 580c00d61d8SAlex Williamson 0, &quirk->mem, 1); 581c00d61d8SAlex Williamson 582c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 583c00d61d8SAlex Williamson 584c00d61d8SAlex Williamson trace_vfio_probe_nvidia_bar5_window_quirk(vdev->vbasedev.name); 585c00d61d8SAlex Williamson } 586c00d61d8SAlex Williamson 587c00d61d8SAlex Williamson static void vfio_nvidia_88000_quirk_write(void *opaque, hwaddr addr, 588c00d61d8SAlex Williamson uint64_t data, unsigned size) 589c00d61d8SAlex Williamson { 590c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 591c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 592c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 593c00d61d8SAlex Williamson hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK; 594c00d61d8SAlex Williamson 595c00d61d8SAlex Williamson vfio_generic_quirk_write(opaque, addr, data, size); 596c00d61d8SAlex Williamson 597c00d61d8SAlex Williamson /* 598c00d61d8SAlex Williamson * Nvidia seems to acknowledge MSI interrupts by writing 0xff to the 599c00d61d8SAlex Williamson * MSI capability ID register. Both the ID and next register are 600c00d61d8SAlex Williamson * read-only, so we allow writes covering either of those to real hw. 601c00d61d8SAlex Williamson * NB - only fixed for the 0x88000 MMIO window. 602c00d61d8SAlex Williamson */ 603c00d61d8SAlex Williamson if ((pdev->cap_present & QEMU_PCI_CAP_MSI) && 604c00d61d8SAlex Williamson vfio_range_contained(addr, size, pdev->msi_cap, PCI_MSI_FLAGS)) { 605c00d61d8SAlex Williamson vfio_region_write(&vdev->bars[quirk->data.bar].region, 606c00d61d8SAlex Williamson addr + base, data, size); 607c00d61d8SAlex Williamson } 608c00d61d8SAlex Williamson } 609c00d61d8SAlex Williamson 610c00d61d8SAlex Williamson static const MemoryRegionOps vfio_nvidia_88000_quirk = { 611c00d61d8SAlex Williamson .read = vfio_generic_quirk_read, 612c00d61d8SAlex Williamson .write = vfio_nvidia_88000_quirk_write, 613c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 614c00d61d8SAlex Williamson }; 615c00d61d8SAlex Williamson 616c00d61d8SAlex Williamson /* 617c00d61d8SAlex Williamson * Finally, BAR0 itself. We want to redirect any accesses to either 618c00d61d8SAlex Williamson * 0x1800 or 0x88000 through the PCI config space access functions. 619c00d61d8SAlex Williamson * 620c00d61d8SAlex Williamson * NB - quirk at a page granularity or else they don't seem to work when 621c00d61d8SAlex Williamson * BARs are mmap'd 622c00d61d8SAlex Williamson * 623c00d61d8SAlex Williamson * Here's offset 0x88000... 624c00d61d8SAlex Williamson */ 625c00d61d8SAlex Williamson static void vfio_probe_nvidia_bar0_88000_quirk(VFIOPCIDevice *vdev, int nr) 626c00d61d8SAlex Williamson { 627c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 628c00d61d8SAlex Williamson VFIOQuirk *quirk; 629c00d61d8SAlex Williamson uint16_t vendor, class; 630c00d61d8SAlex Williamson 631c00d61d8SAlex Williamson vendor = pci_get_word(pdev->config + PCI_VENDOR_ID); 632c00d61d8SAlex Williamson class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); 633c00d61d8SAlex Williamson 634c00d61d8SAlex Williamson if (nr != 0 || vendor != PCI_VENDOR_ID_NVIDIA || 635c00d61d8SAlex Williamson class != PCI_CLASS_DISPLAY_VGA) { 636c00d61d8SAlex Williamson return; 637c00d61d8SAlex Williamson } 638c00d61d8SAlex Williamson 639c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 640c00d61d8SAlex Williamson quirk->vdev = vdev; 641c00d61d8SAlex Williamson quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; 642c00d61d8SAlex Williamson quirk->data.address_match = 0x88000; 643c00d61d8SAlex Williamson quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; 644c00d61d8SAlex Williamson quirk->data.bar = nr; 645c00d61d8SAlex Williamson 646c00d61d8SAlex Williamson memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_88000_quirk, 647c00d61d8SAlex Williamson quirk, "vfio-nvidia-bar0-88000-quirk", 648c00d61d8SAlex Williamson TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); 649c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 650c00d61d8SAlex Williamson quirk->data.address_match & TARGET_PAGE_MASK, 651c00d61d8SAlex Williamson &quirk->mem, 1); 652c00d61d8SAlex Williamson 653c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 654c00d61d8SAlex Williamson 655c00d61d8SAlex Williamson trace_vfio_probe_nvidia_bar0_88000_quirk(vdev->vbasedev.name); 656c00d61d8SAlex Williamson } 657c00d61d8SAlex Williamson 658c00d61d8SAlex Williamson /* 659c00d61d8SAlex Williamson * And here's the same for BAR0 offset 0x1800... 660c00d61d8SAlex Williamson */ 661c00d61d8SAlex Williamson static void vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr) 662c00d61d8SAlex Williamson { 663c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 664c00d61d8SAlex Williamson VFIOQuirk *quirk; 665c00d61d8SAlex Williamson 666c00d61d8SAlex Williamson if (!vdev->has_vga || nr != 0 || 667c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) { 668c00d61d8SAlex Williamson return; 669c00d61d8SAlex Williamson } 670c00d61d8SAlex Williamson 671c00d61d8SAlex Williamson /* Log the chipset ID */ 672c00d61d8SAlex Williamson trace_vfio_probe_nvidia_bar0_1800_quirk_id( 673c00d61d8SAlex Williamson (unsigned int)(vfio_region_read(&vdev->bars[0].region, 0, 4) >> 20) 674c00d61d8SAlex Williamson & 0xff); 675c00d61d8SAlex Williamson 676c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 677c00d61d8SAlex Williamson quirk->vdev = vdev; 678c00d61d8SAlex Williamson quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; 679c00d61d8SAlex Williamson quirk->data.address_match = 0x1800; 680c00d61d8SAlex Williamson quirk->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1; 681c00d61d8SAlex Williamson quirk->data.bar = nr; 682c00d61d8SAlex Williamson 683c00d61d8SAlex Williamson memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, quirk, 684c00d61d8SAlex Williamson "vfio-nvidia-bar0-1800-quirk", 685c00d61d8SAlex Williamson TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); 686c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 687c00d61d8SAlex Williamson quirk->data.address_match & TARGET_PAGE_MASK, 688c00d61d8SAlex Williamson &quirk->mem, 1); 689c00d61d8SAlex Williamson 690c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 691c00d61d8SAlex Williamson 692c00d61d8SAlex Williamson trace_vfio_probe_nvidia_bar0_1800_quirk(vdev->vbasedev.name); 693c00d61d8SAlex Williamson } 694c00d61d8SAlex Williamson 695c00d61d8SAlex Williamson /* 696c00d61d8SAlex Williamson * TODO - Some Nvidia devices provide config access to their companion HDA 697c00d61d8SAlex Williamson * device and even to their parent bridge via these config space mirrors. 698c00d61d8SAlex Williamson * Add quirks for those regions. 699c00d61d8SAlex Williamson */ 700c00d61d8SAlex Williamson 701c00d61d8SAlex Williamson #define PCI_VENDOR_ID_REALTEK 0x10ec 702c00d61d8SAlex Williamson 703c00d61d8SAlex Williamson /* 704c00d61d8SAlex Williamson * RTL8168 devices have a backdoor that can access the MSI-X table. At BAR2 705c00d61d8SAlex Williamson * offset 0x70 there is a dword data register, offset 0x74 is a dword address 706c00d61d8SAlex Williamson * register. According to the Linux r8169 driver, the MSI-X table is addressed 707c00d61d8SAlex Williamson * when the "type" portion of the address register is set to 0x1. This appears 708c00d61d8SAlex Williamson * to be bits 16:30. Bit 31 is both a write indicator and some sort of 709c00d61d8SAlex Williamson * "address latched" indicator. Bits 12:15 are a mask field, which we can 710c00d61d8SAlex Williamson * ignore because the MSI-X table should always be accessed as a dword (full 711c00d61d8SAlex Williamson * mask). Bits 0:11 is offset within the type. 712c00d61d8SAlex Williamson * 713c00d61d8SAlex Williamson * Example trace: 714c00d61d8SAlex Williamson * 715c00d61d8SAlex Williamson * Read from MSI-X table offset 0 716c00d61d8SAlex Williamson * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x74, 0x1f000, 4) // store read addr 717c00d61d8SAlex Williamson * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x74, 4) = 0x8001f000 // latch 718c00d61d8SAlex Williamson * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x70, 4) = 0xfee00398 // read data 719c00d61d8SAlex Williamson * 720c00d61d8SAlex Williamson * Write 0xfee00000 to MSI-X table offset 0 721c00d61d8SAlex Williamson * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x70, 0xfee00000, 4) // write data 722c00d61d8SAlex Williamson * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x74, 0x8001f000, 4) // do write 723c00d61d8SAlex Williamson * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x74, 4) = 0x1f000 // complete 724c00d61d8SAlex Williamson */ 725c00d61d8SAlex Williamson static uint64_t vfio_rtl8168_window_quirk_read(void *opaque, 726c00d61d8SAlex Williamson hwaddr addr, unsigned size) 727c00d61d8SAlex Williamson { 728c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 729c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 730c00d61d8SAlex Williamson uint64_t val = 0; 731c00d61d8SAlex Williamson 732c00d61d8SAlex Williamson if (!quirk->data.flags) { /* Non-MSI-X table access */ 733c00d61d8SAlex Williamson return vfio_region_read(&vdev->bars[quirk->data.bar].region, 734c00d61d8SAlex Williamson addr + 0x70, size); 735c00d61d8SAlex Williamson } 736c00d61d8SAlex Williamson 737c00d61d8SAlex Williamson switch (addr) { 738c00d61d8SAlex Williamson case 4: /* address */ 739c00d61d8SAlex Williamson val = quirk->data.address_match ^ 0x80000000U; /* latch/complete */ 740c00d61d8SAlex Williamson break; 741c00d61d8SAlex Williamson case 0: /* data */ 742c00d61d8SAlex Williamson if ((vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) { 743c00d61d8SAlex Williamson memory_region_dispatch_read(&vdev->pdev.msix_table_mmio, 744c00d61d8SAlex Williamson (hwaddr)(quirk->data.address_match & 0xfff), 745c00d61d8SAlex Williamson &val, size, MEMTXATTRS_UNSPECIFIED); 746c00d61d8SAlex Williamson } 747c00d61d8SAlex Williamson break; 748c00d61d8SAlex Williamson } 749c00d61d8SAlex Williamson 750c00d61d8SAlex Williamson trace_vfio_rtl8168_quirk_read(vdev->vbasedev.name, 751c00d61d8SAlex Williamson addr ? "address" : "data", val); 752c00d61d8SAlex Williamson return val; 753c00d61d8SAlex Williamson } 754c00d61d8SAlex Williamson 755c00d61d8SAlex Williamson static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr, 756c00d61d8SAlex Williamson uint64_t data, unsigned size) 757c00d61d8SAlex Williamson { 758c00d61d8SAlex Williamson VFIOQuirk *quirk = opaque; 759c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 760c00d61d8SAlex Williamson 761c00d61d8SAlex Williamson switch (addr) { 762c00d61d8SAlex Williamson case 4: /* address */ 763c00d61d8SAlex Williamson if ((data & 0x7fff0000) == 0x10000) { /* MSI-X table */ 764c00d61d8SAlex Williamson quirk->data.flags = 1; /* Activate reads */ 765c00d61d8SAlex Williamson quirk->data.address_match = data; 766c00d61d8SAlex Williamson 767c00d61d8SAlex Williamson trace_vfio_rtl8168_quirk_write(vdev->vbasedev.name, data); 768c00d61d8SAlex Williamson 769c00d61d8SAlex Williamson if (data & 0x80000000U) { /* Do write */ 770c00d61d8SAlex Williamson if (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) { 771c00d61d8SAlex Williamson hwaddr offset = data & 0xfff; 772c00d61d8SAlex Williamson uint64_t val = quirk->data.address_mask; 773c00d61d8SAlex Williamson 774c00d61d8SAlex Williamson trace_vfio_rtl8168_quirk_msix(vdev->vbasedev.name, 775c00d61d8SAlex Williamson (uint16_t)offset, val); 776c00d61d8SAlex Williamson 777c00d61d8SAlex Williamson /* Write to the proper guest MSI-X table instead */ 778c00d61d8SAlex Williamson memory_region_dispatch_write(&vdev->pdev.msix_table_mmio, 779c00d61d8SAlex Williamson offset, val, size, 780c00d61d8SAlex Williamson MEMTXATTRS_UNSPECIFIED); 781c00d61d8SAlex Williamson } 782c00d61d8SAlex Williamson return; /* Do not write guest MSI-X data to hardware */ 783c00d61d8SAlex Williamson } 784c00d61d8SAlex Williamson } else { 785c00d61d8SAlex Williamson quirk->data.flags = 0; /* De-activate reads, non-MSI-X */ 786c00d61d8SAlex Williamson } 787c00d61d8SAlex Williamson break; 788c00d61d8SAlex Williamson case 0: /* data */ 789c00d61d8SAlex Williamson quirk->data.address_mask = data; 790c00d61d8SAlex Williamson break; 791c00d61d8SAlex Williamson } 792c00d61d8SAlex Williamson 793c00d61d8SAlex Williamson vfio_region_write(&vdev->bars[quirk->data.bar].region, 794c00d61d8SAlex Williamson addr + 0x70, data, size); 795c00d61d8SAlex Williamson } 796c00d61d8SAlex Williamson 797c00d61d8SAlex Williamson static const MemoryRegionOps vfio_rtl8168_window_quirk = { 798c00d61d8SAlex Williamson .read = vfio_rtl8168_window_quirk_read, 799c00d61d8SAlex Williamson .write = vfio_rtl8168_window_quirk_write, 800c00d61d8SAlex Williamson .valid = { 801c00d61d8SAlex Williamson .min_access_size = 4, 802c00d61d8SAlex Williamson .max_access_size = 4, 803c00d61d8SAlex Williamson .unaligned = false, 804c00d61d8SAlex Williamson }, 805c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 806c00d61d8SAlex Williamson }; 807c00d61d8SAlex Williamson 808c00d61d8SAlex Williamson static void vfio_probe_rtl8168_bar2_window_quirk(VFIOPCIDevice *vdev, int nr) 809c00d61d8SAlex Williamson { 810c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 811c00d61d8SAlex Williamson VFIOQuirk *quirk; 812c00d61d8SAlex Williamson 813c00d61d8SAlex Williamson if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_REALTEK || 814c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_DEVICE_ID) != 0x8168 || nr != 2) { 815c00d61d8SAlex Williamson return; 816c00d61d8SAlex Williamson } 817c00d61d8SAlex Williamson 818c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 819c00d61d8SAlex Williamson quirk->vdev = vdev; 820c00d61d8SAlex Williamson quirk->data.bar = nr; 821c00d61d8SAlex Williamson 822c00d61d8SAlex Williamson memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_rtl8168_window_quirk, 823c00d61d8SAlex Williamson quirk, "vfio-rtl8168-window-quirk", 8); 824c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 825c00d61d8SAlex Williamson 0x70, &quirk->mem, 1); 826c00d61d8SAlex Williamson 827c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 828c00d61d8SAlex Williamson 829c00d61d8SAlex Williamson trace_vfio_rtl8168_quirk_enable(vdev->vbasedev.name); 830c00d61d8SAlex Williamson } 831c00d61d8SAlex Williamson 832c00d61d8SAlex Williamson /* 833c00d61d8SAlex Williamson * Common quirk probe entry points. 834c00d61d8SAlex Williamson */ 835c00d61d8SAlex Williamson void vfio_vga_quirk_setup(VFIOPCIDevice *vdev) 836c00d61d8SAlex Williamson { 837c00d61d8SAlex Williamson vfio_vga_probe_ati_3c3_quirk(vdev); 838c00d61d8SAlex Williamson vfio_vga_probe_nvidia_3d0_quirk(vdev); 839c00d61d8SAlex Williamson } 840c00d61d8SAlex Williamson 841c00d61d8SAlex Williamson void vfio_vga_quirk_teardown(VFIOPCIDevice *vdev) 842c00d61d8SAlex Williamson { 843c00d61d8SAlex Williamson VFIOQuirk *quirk; 844c00d61d8SAlex Williamson int i; 845c00d61d8SAlex Williamson 846c00d61d8SAlex Williamson for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) { 847c00d61d8SAlex Williamson QLIST_FOREACH(quirk, &vdev->vga.region[i].quirks, next) { 848c00d61d8SAlex Williamson memory_region_del_subregion(&vdev->vga.region[i].mem, &quirk->mem); 849c00d61d8SAlex Williamson } 850c00d61d8SAlex Williamson } 851c00d61d8SAlex Williamson } 852c00d61d8SAlex Williamson 853c00d61d8SAlex Williamson void vfio_vga_quirk_free(VFIOPCIDevice *vdev) 854c00d61d8SAlex Williamson { 855c00d61d8SAlex Williamson int i; 856c00d61d8SAlex Williamson 857c00d61d8SAlex Williamson for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) { 858c00d61d8SAlex Williamson while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) { 859c00d61d8SAlex Williamson VFIOQuirk *quirk = QLIST_FIRST(&vdev->vga.region[i].quirks); 860c00d61d8SAlex Williamson object_unparent(OBJECT(&quirk->mem)); 861c00d61d8SAlex Williamson QLIST_REMOVE(quirk, next); 862c00d61d8SAlex Williamson g_free(quirk); 863c00d61d8SAlex Williamson } 864c00d61d8SAlex Williamson } 865c00d61d8SAlex Williamson } 866c00d61d8SAlex Williamson 867c00d61d8SAlex Williamson void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr) 868c00d61d8SAlex Williamson { 869c00d61d8SAlex Williamson vfio_probe_ati_bar4_window_quirk(vdev, nr); 870c00d61d8SAlex Williamson vfio_probe_ati_bar2_4000_quirk(vdev, nr); 871c00d61d8SAlex Williamson vfio_probe_nvidia_bar5_window_quirk(vdev, nr); 872c00d61d8SAlex Williamson vfio_probe_nvidia_bar0_88000_quirk(vdev, nr); 873c00d61d8SAlex Williamson vfio_probe_nvidia_bar0_1800_quirk(vdev, nr); 874c00d61d8SAlex Williamson vfio_probe_rtl8168_bar2_window_quirk(vdev, nr); 875c00d61d8SAlex Williamson } 876c00d61d8SAlex Williamson 877c00d61d8SAlex Williamson void vfio_bar_quirk_teardown(VFIOPCIDevice *vdev, int nr) 878c00d61d8SAlex Williamson { 879c00d61d8SAlex Williamson VFIOBAR *bar = &vdev->bars[nr]; 880c00d61d8SAlex Williamson VFIOQuirk *quirk; 881c00d61d8SAlex Williamson 882c00d61d8SAlex Williamson QLIST_FOREACH(quirk, &bar->quirks, next) { 883c00d61d8SAlex Williamson memory_region_del_subregion(&bar->region.mem, &quirk->mem); 884c00d61d8SAlex Williamson } 885c00d61d8SAlex Williamson } 886c00d61d8SAlex Williamson 887c00d61d8SAlex Williamson void vfio_bar_quirk_free(VFIOPCIDevice *vdev, int nr) 888c00d61d8SAlex Williamson { 889c00d61d8SAlex Williamson VFIOBAR *bar = &vdev->bars[nr]; 890c00d61d8SAlex Williamson 891c00d61d8SAlex Williamson while (!QLIST_EMPTY(&bar->quirks)) { 892c00d61d8SAlex Williamson VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks); 893c00d61d8SAlex Williamson object_unparent(OBJECT(&quirk->mem)); 894c00d61d8SAlex Williamson QLIST_REMOVE(quirk, next); 895c00d61d8SAlex Williamson g_free(quirk); 896c00d61d8SAlex Williamson } 897c00d61d8SAlex Williamson } 898