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 17056dfcb6SAlex Williamson #define PCI_ANY_ID (~0) 18056dfcb6SAlex Williamson 19056dfcb6SAlex Williamson /* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */ 20056dfcb6SAlex Williamson static bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device) 21056dfcb6SAlex Williamson { 22056dfcb6SAlex Williamson PCIDevice *pdev = &vdev->pdev; 23056dfcb6SAlex Williamson 24056dfcb6SAlex Williamson return (vendor == PCI_ANY_ID || 25056dfcb6SAlex Williamson vendor == pci_get_word(pdev->config + PCI_VENDOR_ID)) && 26056dfcb6SAlex Williamson (device == PCI_ANY_ID || 27056dfcb6SAlex Williamson device == pci_get_word(pdev->config + PCI_DEVICE_ID)); 28056dfcb6SAlex Williamson } 29056dfcb6SAlex 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 */ 43056dfcb6SAlex Williamson static const struct { 44056dfcb6SAlex Williamson uint32_t vendor; 45056dfcb6SAlex Williamson uint32_t device; 46056dfcb6SAlex Williamson } romblacklist[] = { 47056dfcb6SAlex Williamson { 0x14e4, 0x168e }, /* Broadcom BCM 57810 */ 48c00d61d8SAlex Williamson }; 49c00d61d8SAlex Williamson 50c00d61d8SAlex Williamson bool vfio_blacklist_opt_rom(VFIOPCIDevice *vdev) 51c00d61d8SAlex Williamson { 52056dfcb6SAlex Williamson int i; 53c00d61d8SAlex Williamson 54056dfcb6SAlex Williamson for (i = 0 ; i < ARRAY_SIZE(romblacklist); i++) { 55056dfcb6SAlex Williamson if (vfio_pci_is(vdev, romblacklist[i].vendor, romblacklist[i].device)) { 56056dfcb6SAlex Williamson trace_vfio_quirk_rom_blacklisted(vdev->vbasedev.name, 57056dfcb6SAlex Williamson romblacklist[i].vendor, 58056dfcb6SAlex 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 { 838c4f2348SAlex Williamson VFIOLegacyQuirk *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", 958c4f2348SAlex 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 1018c4f2348SAlex 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 { 1168c4f2348SAlex Williamson VFIOLegacyQuirk *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", 1248c4f2348SAlex 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", 1458c4f2348SAlex 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); 1508c4f2348SAlex 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 { 1708c4f2348SAlex Williamson VFIOLegacyQuirk *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", 1818c4f2348SAlex 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 1868c4f2348SAlex 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 { 2008c4f2348SAlex Williamson VFIOLegacyQuirk *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", 2108c4f2348SAlex 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 2158c4f2348SAlex 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 { 245b946d286SAlex Williamson VFIOPCIDevice *vdev = opaque; 246c00d61d8SAlex Williamson uint64_t data = vfio_pci_read_config(&vdev->pdev, 247b946d286SAlex Williamson PCI_BASE_ADDRESS_4 + 1, size); 248b946d286SAlex Williamson 249b946d286SAlex Williamson trace_vfio_quirk_ati_3c3_read(vdev->vbasedev.name, data); 250c00d61d8SAlex Williamson 251c00d61d8SAlex Williamson return data; 252c00d61d8SAlex Williamson } 253c00d61d8SAlex Williamson 254c00d61d8SAlex Williamson static const MemoryRegionOps vfio_ati_3c3_quirk = { 255c00d61d8SAlex Williamson .read = vfio_ati_3c3_quirk_read, 256c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 257c00d61d8SAlex Williamson }; 258c00d61d8SAlex Williamson 259c00d61d8SAlex Williamson static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice *vdev) 260c00d61d8SAlex Williamson { 261c00d61d8SAlex Williamson VFIOQuirk *quirk; 262c00d61d8SAlex Williamson 263c00d61d8SAlex Williamson /* 264c00d61d8SAlex Williamson * As long as the BAR is >= 256 bytes it will be aligned such that the 265c00d61d8SAlex Williamson * lower byte is always zero. Filter out anything else, if it exists. 266c00d61d8SAlex Williamson */ 267b946d286SAlex Williamson if (!vfio_pci_is(vdev, PCI_VENDOR_ID_ATI, PCI_ANY_ID) || 268b946d286SAlex Williamson !vdev->bars[4].ioport || vdev->bars[4].region.size < 256) { 269c00d61d8SAlex Williamson return; 270c00d61d8SAlex Williamson } 271c00d61d8SAlex Williamson 272c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 273b946d286SAlex Williamson quirk->mem = g_malloc0_n(sizeof(MemoryRegion), 1); 2748c4f2348SAlex Williamson quirk->nr_mem = 1; 275c00d61d8SAlex Williamson 276b946d286SAlex Williamson memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, vdev, 277c00d61d8SAlex Williamson "vfio-ati-3c3-quirk", 1); 278c00d61d8SAlex Williamson memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 2798c4f2348SAlex Williamson 3 /* offset 3 bytes from 0x3c0 */, quirk->mem); 280c00d61d8SAlex Williamson 281c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, 282c00d61d8SAlex Williamson quirk, next); 283c00d61d8SAlex Williamson 284b946d286SAlex Williamson trace_vfio_quirk_ati_3c3_probe(vdev->vbasedev.name); 285c00d61d8SAlex Williamson } 286c00d61d8SAlex Williamson 287c00d61d8SAlex Williamson /* 288c00d61d8SAlex Williamson * Newer ATI/AMD devices, including HD5450 and HD7850, have a window to PCI 289c00d61d8SAlex Williamson * config space through MMIO BAR2 at offset 0x4000. Nothing seems to access 290c00d61d8SAlex Williamson * the MMIO space directly, but a window to this space is provided through 291c00d61d8SAlex Williamson * I/O port BAR4. Offset 0x0 is the address register and offset 0x4 is the 292c00d61d8SAlex Williamson * data register. When the address is programmed to a range of 0x4000-0x4fff 293c00d61d8SAlex Williamson * PCI configuration space is available. Experimentation seems to indicate 294c00d61d8SAlex Williamson * that only read-only access is provided, but we drop writes when the window 295c00d61d8SAlex Williamson * is enabled to config space nonetheless. 296c00d61d8SAlex Williamson */ 297c00d61d8SAlex Williamson static void vfio_probe_ati_bar4_window_quirk(VFIOPCIDevice *vdev, int nr) 298c00d61d8SAlex Williamson { 299c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 300c00d61d8SAlex Williamson VFIOQuirk *quirk; 3018c4f2348SAlex Williamson VFIOLegacyQuirk *legacy; 302c00d61d8SAlex Williamson 303c00d61d8SAlex Williamson if (!vdev->has_vga || nr != 4 || 304c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { 305c00d61d8SAlex Williamson return; 306c00d61d8SAlex Williamson } 307c00d61d8SAlex Williamson 308c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 3098c4f2348SAlex Williamson quirk->data = legacy = g_malloc0(sizeof(*legacy)); 3108c4f2348SAlex Williamson quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1); 3118c4f2348SAlex Williamson quirk->nr_mem = 1; 3128c4f2348SAlex Williamson legacy->vdev = vdev; 3138c4f2348SAlex Williamson legacy->data.address_size = 4; 3148c4f2348SAlex Williamson legacy->data.data_offset = 4; 3158c4f2348SAlex Williamson legacy->data.data_size = 4; 3168c4f2348SAlex Williamson legacy->data.address_match = 0x4000; 3178c4f2348SAlex Williamson legacy->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; 3188c4f2348SAlex Williamson legacy->data.bar = nr; 3198c4f2348SAlex Williamson legacy->data.read_flags = legacy->data.write_flags = 1; 320c00d61d8SAlex Williamson 3218c4f2348SAlex Williamson memory_region_init_io(quirk->mem, OBJECT(vdev), 3228c4f2348SAlex Williamson &vfio_generic_window_quirk, legacy, 323c00d61d8SAlex Williamson "vfio-ati-bar4-window-quirk", 8); 324c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 3258c4f2348SAlex Williamson legacy->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; 3398c4f2348SAlex Williamson VFIOLegacyQuirk *legacy; 340c00d61d8SAlex Williamson 341c00d61d8SAlex Williamson /* Only enable on newer devices where BAR2 is 64bit */ 342c00d61d8SAlex Williamson if (!vdev->has_vga || nr != 2 || !vdev->bars[2].mem64 || 343c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { 344c00d61d8SAlex Williamson return; 345c00d61d8SAlex Williamson } 346c00d61d8SAlex Williamson 347c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 3488c4f2348SAlex Williamson quirk->data = legacy = g_malloc0(sizeof(*legacy)); 3498c4f2348SAlex Williamson quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1); 3508c4f2348SAlex Williamson quirk->nr_mem = 1; 3518c4f2348SAlex Williamson legacy->vdev = vdev; 3528c4f2348SAlex Williamson legacy->data.flags = legacy->data.read_flags = legacy->data.write_flags = 1; 3538c4f2348SAlex Williamson legacy->data.address_match = 0x4000; 3548c4f2348SAlex Williamson legacy->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; 3558c4f2348SAlex Williamson legacy->data.bar = nr; 356c00d61d8SAlex Williamson 3578c4f2348SAlex Williamson memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_generic_quirk, legacy, 358c00d61d8SAlex Williamson "vfio-ati-bar2-4000-quirk", 3598c4f2348SAlex Williamson TARGET_PAGE_ALIGN(legacy->data.address_mask + 1)); 360c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 3618c4f2348SAlex Williamson legacy->data.address_match & TARGET_PAGE_MASK, 3628c4f2348SAlex Williamson quirk->mem, 1); 363c00d61d8SAlex Williamson 364c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 365c00d61d8SAlex Williamson 366c00d61d8SAlex Williamson trace_vfio_probe_ati_bar2_4000_quirk(vdev->vbasedev.name); 367c00d61d8SAlex Williamson } 368c00d61d8SAlex Williamson 369c00d61d8SAlex Williamson /* 370c00d61d8SAlex Williamson * Older ATI/AMD cards like the X550 have a similar window to that above. 371c00d61d8SAlex Williamson * I/O port BAR1 provides a window to a mirror of PCI config space located 372c00d61d8SAlex Williamson * in BAR2 at offset 0xf00. We don't care to support such older cards, but 373c00d61d8SAlex Williamson * note it for future reference. 374c00d61d8SAlex Williamson */ 375c00d61d8SAlex Williamson 376c00d61d8SAlex Williamson #define PCI_VENDOR_ID_NVIDIA 0x10de 377c00d61d8SAlex Williamson 378c00d61d8SAlex Williamson /* 379c00d61d8SAlex Williamson * Nvidia has several different methods to get to config space, the 380c00d61d8SAlex Williamson * nouveu project has several of these documented here: 381c00d61d8SAlex Williamson * https://github.com/pathscale/envytools/tree/master/hwdocs 382c00d61d8SAlex Williamson * 383c00d61d8SAlex Williamson * The first quirk is actually not documented in envytools and is found 384c00d61d8SAlex Williamson * on 10de:01d1 (NVIDIA Corporation G72 [GeForce 7300 LE]). This is an 385c00d61d8SAlex Williamson * NV46 chipset. The backdoor uses the legacy VGA I/O ports to access 386c00d61d8SAlex Williamson * the mirror of PCI config space found at BAR0 offset 0x1800. The access 387c00d61d8SAlex Williamson * sequence first writes 0x338 to I/O port 0x3d4. The target offset is 388c00d61d8SAlex Williamson * then written to 0x3d0. Finally 0x538 is written for a read and 0x738 389c00d61d8SAlex Williamson * is written for a write to 0x3d4. The BAR0 offset is then accessible 390c00d61d8SAlex Williamson * through 0x3d0. This quirk doesn't seem to be necessary on newer cards 391c00d61d8SAlex Williamson * that use the I/O port BAR5 window but it doesn't hurt to leave it. 392c00d61d8SAlex Williamson */ 393*6029a424SAlex Williamson typedef enum {NONE = 0, SELECT, WINDOW, READ, WRITE} VFIONvidia3d0State; 394*6029a424SAlex Williamson static const char *nv3d0_states[] = { "NONE", "SELECT", 395*6029a424SAlex Williamson "WINDOW", "READ", "WRITE" }; 396*6029a424SAlex Williamson 397*6029a424SAlex Williamson typedef struct VFIONvidia3d0Quirk { 398*6029a424SAlex Williamson VFIOPCIDevice *vdev; 399*6029a424SAlex Williamson VFIONvidia3d0State state; 400*6029a424SAlex Williamson uint32_t offset; 401*6029a424SAlex Williamson } VFIONvidia3d0Quirk; 402*6029a424SAlex Williamson 403*6029a424SAlex Williamson static uint64_t vfio_nvidia_3d4_quirk_read(void *opaque, 404*6029a424SAlex Williamson hwaddr addr, unsigned size) 405*6029a424SAlex Williamson { 406*6029a424SAlex Williamson VFIONvidia3d0Quirk *quirk = opaque; 407*6029a424SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 408*6029a424SAlex Williamson 409*6029a424SAlex Williamson quirk->state = NONE; 410*6029a424SAlex Williamson 411*6029a424SAlex Williamson return vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], 412*6029a424SAlex Williamson addr + 0x14, size); 413*6029a424SAlex Williamson } 414*6029a424SAlex Williamson 415*6029a424SAlex Williamson static void vfio_nvidia_3d4_quirk_write(void *opaque, hwaddr addr, 416*6029a424SAlex Williamson uint64_t data, unsigned size) 417*6029a424SAlex Williamson { 418*6029a424SAlex Williamson VFIONvidia3d0Quirk *quirk = opaque; 419*6029a424SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 420*6029a424SAlex Williamson VFIONvidia3d0State old_state = quirk->state; 421*6029a424SAlex Williamson 422*6029a424SAlex Williamson quirk->state = NONE; 423*6029a424SAlex Williamson 424*6029a424SAlex Williamson switch (data) { 425*6029a424SAlex Williamson case 0x338: 426*6029a424SAlex Williamson if (old_state == NONE) { 427*6029a424SAlex Williamson quirk->state = SELECT; 428*6029a424SAlex Williamson trace_vfio_quirk_nvidia_3d0_state(vdev->vbasedev.name, 429*6029a424SAlex Williamson nv3d0_states[quirk->state]); 430*6029a424SAlex Williamson } 431*6029a424SAlex Williamson break; 432*6029a424SAlex Williamson case 0x538: 433*6029a424SAlex Williamson if (old_state == WINDOW) { 434*6029a424SAlex Williamson quirk->state = READ; 435*6029a424SAlex Williamson trace_vfio_quirk_nvidia_3d0_state(vdev->vbasedev.name, 436*6029a424SAlex Williamson nv3d0_states[quirk->state]); 437*6029a424SAlex Williamson } 438*6029a424SAlex Williamson break; 439*6029a424SAlex Williamson case 0x738: 440*6029a424SAlex Williamson if (old_state == WINDOW) { 441*6029a424SAlex Williamson quirk->state = WRITE; 442*6029a424SAlex Williamson trace_vfio_quirk_nvidia_3d0_state(vdev->vbasedev.name, 443*6029a424SAlex Williamson nv3d0_states[quirk->state]); 444*6029a424SAlex Williamson } 445*6029a424SAlex Williamson break; 446*6029a424SAlex Williamson } 447*6029a424SAlex Williamson 448*6029a424SAlex Williamson vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], 449*6029a424SAlex Williamson addr + 0x14, data, size); 450*6029a424SAlex Williamson } 451*6029a424SAlex Williamson 452*6029a424SAlex Williamson static const MemoryRegionOps vfio_nvidia_3d4_quirk = { 453*6029a424SAlex Williamson .read = vfio_nvidia_3d4_quirk_read, 454*6029a424SAlex Williamson .write = vfio_nvidia_3d4_quirk_write, 455*6029a424SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 456c00d61d8SAlex Williamson }; 457c00d61d8SAlex Williamson 458c00d61d8SAlex Williamson static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque, 459c00d61d8SAlex Williamson hwaddr addr, unsigned size) 460c00d61d8SAlex Williamson { 461*6029a424SAlex Williamson VFIONvidia3d0Quirk *quirk = opaque; 462c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 463*6029a424SAlex Williamson VFIONvidia3d0State old_state = quirk->state; 464c00d61d8SAlex Williamson uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], 465*6029a424SAlex Williamson addr + 0x10, size); 466c00d61d8SAlex Williamson 467*6029a424SAlex Williamson quirk->state = NONE; 468*6029a424SAlex Williamson 469*6029a424SAlex Williamson if (old_state == READ && 470*6029a424SAlex Williamson (quirk->offset & ~(PCI_CONFIG_SPACE_SIZE - 1)) == 0x1800) { 471*6029a424SAlex Williamson uint8_t offset = quirk->offset & (PCI_CONFIG_SPACE_SIZE - 1); 472*6029a424SAlex Williamson 473*6029a424SAlex Williamson data = vfio_pci_read_config(&vdev->pdev, offset, size); 474*6029a424SAlex Williamson trace_vfio_quirk_nvidia_3d0_read(vdev->vbasedev.name, 475*6029a424SAlex Williamson offset, size, data); 476c00d61d8SAlex Williamson } 477c00d61d8SAlex Williamson 478c00d61d8SAlex Williamson return data; 479c00d61d8SAlex Williamson } 480c00d61d8SAlex Williamson 481c00d61d8SAlex Williamson static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr, 482c00d61d8SAlex Williamson uint64_t data, unsigned size) 483c00d61d8SAlex Williamson { 484*6029a424SAlex Williamson VFIONvidia3d0Quirk *quirk = opaque; 485c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 486*6029a424SAlex Williamson VFIONvidia3d0State old_state = quirk->state; 487c00d61d8SAlex Williamson 488*6029a424SAlex Williamson quirk->state = NONE; 489*6029a424SAlex Williamson 490*6029a424SAlex Williamson if (old_state == SELECT) { 491*6029a424SAlex Williamson quirk->offset = (uint32_t)data; 492*6029a424SAlex Williamson quirk->state = WINDOW; 493*6029a424SAlex Williamson trace_vfio_quirk_nvidia_3d0_state(vdev->vbasedev.name, 494*6029a424SAlex Williamson nv3d0_states[quirk->state]); 495*6029a424SAlex Williamson } else if (old_state == WRITE) { 496*6029a424SAlex Williamson if ((quirk->offset & ~(PCI_CONFIG_SPACE_SIZE - 1)) == 0x1800) { 497*6029a424SAlex Williamson uint8_t offset = quirk->offset & (PCI_CONFIG_SPACE_SIZE - 1); 498*6029a424SAlex Williamson 499*6029a424SAlex Williamson vfio_pci_write_config(&vdev->pdev, offset, data, size); 500*6029a424SAlex Williamson trace_vfio_quirk_nvidia_3d0_write(vdev->vbasedev.name, 501*6029a424SAlex Williamson offset, data, size); 502c00d61d8SAlex Williamson return; 503c00d61d8SAlex Williamson } 504c00d61d8SAlex Williamson } 505c00d61d8SAlex Williamson 506c00d61d8SAlex Williamson vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], 507*6029a424SAlex Williamson addr + 0x10, data, size); 508c00d61d8SAlex Williamson } 509c00d61d8SAlex Williamson 510c00d61d8SAlex Williamson static const MemoryRegionOps vfio_nvidia_3d0_quirk = { 511c00d61d8SAlex Williamson .read = vfio_nvidia_3d0_quirk_read, 512c00d61d8SAlex Williamson .write = vfio_nvidia_3d0_quirk_write, 513c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 514c00d61d8SAlex Williamson }; 515c00d61d8SAlex Williamson 516c00d61d8SAlex Williamson static void vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice *vdev) 517c00d61d8SAlex Williamson { 518c00d61d8SAlex Williamson VFIOQuirk *quirk; 519*6029a424SAlex Williamson VFIONvidia3d0Quirk *data; 520c00d61d8SAlex Williamson 521*6029a424SAlex Williamson if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) || 522c00d61d8SAlex Williamson !vdev->bars[1].region.size) { 523c00d61d8SAlex Williamson return; 524c00d61d8SAlex Williamson } 525c00d61d8SAlex Williamson 526c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 527*6029a424SAlex Williamson quirk->data = data = g_malloc0(sizeof(*data)); 528*6029a424SAlex Williamson quirk->mem = g_malloc0_n(sizeof(MemoryRegion), 2); 529*6029a424SAlex Williamson quirk->nr_mem = 2; 530*6029a424SAlex Williamson data->vdev = vdev; 531c00d61d8SAlex Williamson 532*6029a424SAlex Williamson memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_nvidia_3d4_quirk, 533*6029a424SAlex Williamson data, "vfio-nvidia-3d4-quirk", 2); 534c00d61d8SAlex Williamson memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 535*6029a424SAlex Williamson 0x14 /* 0x3c0 + 0x14 */, &quirk->mem[0]); 536*6029a424SAlex Williamson 537*6029a424SAlex Williamson memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_nvidia_3d0_quirk, 538*6029a424SAlex Williamson data, "vfio-nvidia-3d0-quirk", 2); 539*6029a424SAlex Williamson memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 540*6029a424SAlex Williamson 0x10 /* 0x3c0 + 0x10 */, &quirk->mem[1]); 541c00d61d8SAlex Williamson 542c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, 543c00d61d8SAlex Williamson quirk, next); 544c00d61d8SAlex Williamson 545*6029a424SAlex Williamson trace_vfio_quirk_nvidia_3d0_probe(vdev->vbasedev.name); 546c00d61d8SAlex Williamson } 547c00d61d8SAlex Williamson 548c00d61d8SAlex Williamson /* 549c00d61d8SAlex Williamson * The second quirk is documented in envytools. The I/O port BAR5 is just 550c00d61d8SAlex Williamson * a set of address/data ports to the MMIO BARs. The BAR we care about is 551c00d61d8SAlex Williamson * again BAR0. This backdoor is apparently a bit newer than the one above 552c00d61d8SAlex Williamson * so we need to not only trap 256 bytes @0x1800, but all of PCI config 553c00d61d8SAlex Williamson * space, including extended space is available at the 4k @0x88000. 554c00d61d8SAlex Williamson */ 555c00d61d8SAlex Williamson enum { 556c00d61d8SAlex Williamson NV_BAR5_ADDRESS = 0x1, 557c00d61d8SAlex Williamson NV_BAR5_ENABLE = 0x2, 558c00d61d8SAlex Williamson NV_BAR5_MASTER = 0x4, 559c00d61d8SAlex Williamson NV_BAR5_VALID = 0x7, 560c00d61d8SAlex Williamson }; 561c00d61d8SAlex Williamson 562c00d61d8SAlex Williamson static void vfio_nvidia_bar5_window_quirk_write(void *opaque, hwaddr addr, 563c00d61d8SAlex Williamson uint64_t data, unsigned size) 564c00d61d8SAlex Williamson { 5658c4f2348SAlex Williamson VFIOLegacyQuirk *quirk = opaque; 566c00d61d8SAlex Williamson 567c00d61d8SAlex Williamson switch (addr) { 568c00d61d8SAlex Williamson case 0x0: 569c00d61d8SAlex Williamson if (data & 0x1) { 570c00d61d8SAlex Williamson quirk->data.flags |= NV_BAR5_MASTER; 571c00d61d8SAlex Williamson } else { 572c00d61d8SAlex Williamson quirk->data.flags &= ~NV_BAR5_MASTER; 573c00d61d8SAlex Williamson } 574c00d61d8SAlex Williamson break; 575c00d61d8SAlex Williamson case 0x4: 576c00d61d8SAlex Williamson if (data & 0x1) { 577c00d61d8SAlex Williamson quirk->data.flags |= NV_BAR5_ENABLE; 578c00d61d8SAlex Williamson } else { 579c00d61d8SAlex Williamson quirk->data.flags &= ~NV_BAR5_ENABLE; 580c00d61d8SAlex Williamson } 581c00d61d8SAlex Williamson break; 582c00d61d8SAlex Williamson case 0x8: 583c00d61d8SAlex Williamson if (quirk->data.flags & NV_BAR5_MASTER) { 584c00d61d8SAlex Williamson if ((data & ~0xfff) == 0x88000) { 585c00d61d8SAlex Williamson quirk->data.flags |= NV_BAR5_ADDRESS; 586c00d61d8SAlex Williamson quirk->data.address_val = data & 0xfff; 587c00d61d8SAlex Williamson } else if ((data & ~0xff) == 0x1800) { 588c00d61d8SAlex Williamson quirk->data.flags |= NV_BAR5_ADDRESS; 589c00d61d8SAlex Williamson quirk->data.address_val = data & 0xff; 590c00d61d8SAlex Williamson } else { 591c00d61d8SAlex Williamson quirk->data.flags &= ~NV_BAR5_ADDRESS; 592c00d61d8SAlex Williamson } 593c00d61d8SAlex Williamson } 594c00d61d8SAlex Williamson break; 595c00d61d8SAlex Williamson } 596c00d61d8SAlex Williamson 597c00d61d8SAlex Williamson vfio_generic_window_quirk_write(opaque, addr, data, size); 598c00d61d8SAlex Williamson } 599c00d61d8SAlex Williamson 600c00d61d8SAlex Williamson static const MemoryRegionOps vfio_nvidia_bar5_window_quirk = { 601c00d61d8SAlex Williamson .read = vfio_generic_window_quirk_read, 602c00d61d8SAlex Williamson .write = vfio_nvidia_bar5_window_quirk_write, 603c00d61d8SAlex Williamson .valid.min_access_size = 4, 604c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 605c00d61d8SAlex Williamson }; 606c00d61d8SAlex Williamson 607c00d61d8SAlex Williamson static void vfio_probe_nvidia_bar5_window_quirk(VFIOPCIDevice *vdev, int nr) 608c00d61d8SAlex Williamson { 609c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 610c00d61d8SAlex Williamson VFIOQuirk *quirk; 6118c4f2348SAlex Williamson VFIOLegacyQuirk *legacy; 612c00d61d8SAlex Williamson 613c00d61d8SAlex Williamson if (!vdev->has_vga || nr != 5 || 614c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) { 615c00d61d8SAlex Williamson return; 616c00d61d8SAlex Williamson } 617c00d61d8SAlex Williamson 618c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 6198c4f2348SAlex Williamson quirk->data = legacy = g_malloc0(sizeof(*legacy)); 6208c4f2348SAlex Williamson quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1); 6218c4f2348SAlex Williamson quirk->nr_mem = 1; 6228c4f2348SAlex Williamson legacy->vdev = vdev; 6238c4f2348SAlex Williamson legacy->data.read_flags = legacy->data.write_flags = NV_BAR5_VALID; 6248c4f2348SAlex Williamson legacy->data.address_offset = 0x8; 6258c4f2348SAlex Williamson legacy->data.address_size = 0; /* actually 4, but avoids generic code */ 6268c4f2348SAlex Williamson legacy->data.data_offset = 0xc; 6278c4f2348SAlex Williamson legacy->data.data_size = 4; 6288c4f2348SAlex Williamson legacy->data.bar = nr; 629c00d61d8SAlex Williamson 6308c4f2348SAlex Williamson memory_region_init_io(quirk->mem, OBJECT(vdev), 6318c4f2348SAlex Williamson &vfio_nvidia_bar5_window_quirk, legacy, 632c00d61d8SAlex Williamson "vfio-nvidia-bar5-window-quirk", 16); 633c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 6348c4f2348SAlex Williamson 0, quirk->mem, 1); 635c00d61d8SAlex Williamson 636c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 637c00d61d8SAlex Williamson 638c00d61d8SAlex Williamson trace_vfio_probe_nvidia_bar5_window_quirk(vdev->vbasedev.name); 639c00d61d8SAlex Williamson } 640c00d61d8SAlex Williamson 641c00d61d8SAlex Williamson static void vfio_nvidia_88000_quirk_write(void *opaque, hwaddr addr, 642c00d61d8SAlex Williamson uint64_t data, unsigned size) 643c00d61d8SAlex Williamson { 6448c4f2348SAlex Williamson VFIOLegacyQuirk *quirk = opaque; 645c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 646c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 647c00d61d8SAlex Williamson hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK; 648c00d61d8SAlex Williamson 649c00d61d8SAlex Williamson vfio_generic_quirk_write(opaque, addr, data, size); 650c00d61d8SAlex Williamson 651c00d61d8SAlex Williamson /* 652c00d61d8SAlex Williamson * Nvidia seems to acknowledge MSI interrupts by writing 0xff to the 653c00d61d8SAlex Williamson * MSI capability ID register. Both the ID and next register are 654c00d61d8SAlex Williamson * read-only, so we allow writes covering either of those to real hw. 655c00d61d8SAlex Williamson * NB - only fixed for the 0x88000 MMIO window. 656c00d61d8SAlex Williamson */ 657c00d61d8SAlex Williamson if ((pdev->cap_present & QEMU_PCI_CAP_MSI) && 658c00d61d8SAlex Williamson vfio_range_contained(addr, size, pdev->msi_cap, PCI_MSI_FLAGS)) { 659c00d61d8SAlex Williamson vfio_region_write(&vdev->bars[quirk->data.bar].region, 660c00d61d8SAlex Williamson addr + base, data, size); 661c00d61d8SAlex Williamson } 662c00d61d8SAlex Williamson } 663c00d61d8SAlex Williamson 664c00d61d8SAlex Williamson static const MemoryRegionOps vfio_nvidia_88000_quirk = { 665c00d61d8SAlex Williamson .read = vfio_generic_quirk_read, 666c00d61d8SAlex Williamson .write = vfio_nvidia_88000_quirk_write, 667c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 668c00d61d8SAlex Williamson }; 669c00d61d8SAlex Williamson 670c00d61d8SAlex Williamson /* 671c00d61d8SAlex Williamson * Finally, BAR0 itself. We want to redirect any accesses to either 672c00d61d8SAlex Williamson * 0x1800 or 0x88000 through the PCI config space access functions. 673c00d61d8SAlex Williamson * 674c00d61d8SAlex Williamson * NB - quirk at a page granularity or else they don't seem to work when 675c00d61d8SAlex Williamson * BARs are mmap'd 676c00d61d8SAlex Williamson * 677c00d61d8SAlex Williamson * Here's offset 0x88000... 678c00d61d8SAlex Williamson */ 679c00d61d8SAlex Williamson static void vfio_probe_nvidia_bar0_88000_quirk(VFIOPCIDevice *vdev, int nr) 680c00d61d8SAlex Williamson { 681c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 682c00d61d8SAlex Williamson VFIOQuirk *quirk; 6838c4f2348SAlex Williamson VFIOLegacyQuirk *legacy; 684c00d61d8SAlex Williamson uint16_t vendor, class; 685c00d61d8SAlex Williamson 686c00d61d8SAlex Williamson vendor = pci_get_word(pdev->config + PCI_VENDOR_ID); 687c00d61d8SAlex Williamson class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); 688c00d61d8SAlex Williamson 689c00d61d8SAlex Williamson if (nr != 0 || vendor != PCI_VENDOR_ID_NVIDIA || 690c00d61d8SAlex Williamson class != PCI_CLASS_DISPLAY_VGA) { 691c00d61d8SAlex Williamson return; 692c00d61d8SAlex Williamson } 693c00d61d8SAlex Williamson 694c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 6958c4f2348SAlex Williamson quirk->data = legacy = g_malloc0(sizeof(*legacy)); 6968c4f2348SAlex Williamson quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1); 6978c4f2348SAlex Williamson quirk->nr_mem = 1; 6988c4f2348SAlex Williamson legacy->vdev = vdev; 6998c4f2348SAlex Williamson legacy->data.flags = legacy->data.read_flags = legacy->data.write_flags = 1; 7008c4f2348SAlex Williamson legacy->data.address_match = 0x88000; 7018c4f2348SAlex Williamson legacy->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; 7028c4f2348SAlex Williamson legacy->data.bar = nr; 703c00d61d8SAlex Williamson 7048c4f2348SAlex Williamson memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_nvidia_88000_quirk, 7058c4f2348SAlex Williamson legacy, "vfio-nvidia-bar0-88000-quirk", 7068c4f2348SAlex Williamson TARGET_PAGE_ALIGN(legacy->data.address_mask + 1)); 707c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 7088c4f2348SAlex Williamson legacy->data.address_match & TARGET_PAGE_MASK, 7098c4f2348SAlex Williamson quirk->mem, 1); 710c00d61d8SAlex Williamson 711c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 712c00d61d8SAlex Williamson 713c00d61d8SAlex Williamson trace_vfio_probe_nvidia_bar0_88000_quirk(vdev->vbasedev.name); 714c00d61d8SAlex Williamson } 715c00d61d8SAlex Williamson 716c00d61d8SAlex Williamson /* 717c00d61d8SAlex Williamson * And here's the same for BAR0 offset 0x1800... 718c00d61d8SAlex Williamson */ 719c00d61d8SAlex Williamson static void vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr) 720c00d61d8SAlex Williamson { 721c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 722c00d61d8SAlex Williamson VFIOQuirk *quirk; 7238c4f2348SAlex Williamson VFIOLegacyQuirk *legacy; 724c00d61d8SAlex Williamson 725c00d61d8SAlex Williamson if (!vdev->has_vga || nr != 0 || 726c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) { 727c00d61d8SAlex Williamson return; 728c00d61d8SAlex Williamson } 729c00d61d8SAlex Williamson 730c00d61d8SAlex Williamson /* Log the chipset ID */ 731c00d61d8SAlex Williamson trace_vfio_probe_nvidia_bar0_1800_quirk_id( 732c00d61d8SAlex Williamson (unsigned int)(vfio_region_read(&vdev->bars[0].region, 0, 4) >> 20) 733c00d61d8SAlex Williamson & 0xff); 734c00d61d8SAlex Williamson 735c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 7368c4f2348SAlex Williamson quirk->data = legacy = g_malloc0(sizeof(*legacy)); 7378c4f2348SAlex Williamson quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1); 7388c4f2348SAlex Williamson quirk->nr_mem = 1; 7398c4f2348SAlex Williamson legacy->vdev = vdev; 7408c4f2348SAlex Williamson legacy->data.flags = legacy->data.read_flags = legacy->data.write_flags = 1; 7418c4f2348SAlex Williamson legacy->data.address_match = 0x1800; 7428c4f2348SAlex Williamson legacy->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1; 7438c4f2348SAlex Williamson legacy->data.bar = nr; 744c00d61d8SAlex Williamson 7458c4f2348SAlex Williamson memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_generic_quirk, legacy, 746c00d61d8SAlex Williamson "vfio-nvidia-bar0-1800-quirk", 7478c4f2348SAlex Williamson TARGET_PAGE_ALIGN(legacy->data.address_mask + 1)); 748c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 7498c4f2348SAlex Williamson legacy->data.address_match & TARGET_PAGE_MASK, 7508c4f2348SAlex Williamson quirk->mem, 1); 751c00d61d8SAlex Williamson 752c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 753c00d61d8SAlex Williamson 754c00d61d8SAlex Williamson trace_vfio_probe_nvidia_bar0_1800_quirk(vdev->vbasedev.name); 755c00d61d8SAlex Williamson } 756c00d61d8SAlex Williamson 757c00d61d8SAlex Williamson /* 758c00d61d8SAlex Williamson * TODO - Some Nvidia devices provide config access to their companion HDA 759c00d61d8SAlex Williamson * device and even to their parent bridge via these config space mirrors. 760c00d61d8SAlex Williamson * Add quirks for those regions. 761c00d61d8SAlex Williamson */ 762c00d61d8SAlex Williamson 763c00d61d8SAlex Williamson #define PCI_VENDOR_ID_REALTEK 0x10ec 764c00d61d8SAlex Williamson 765c00d61d8SAlex Williamson /* 766c00d61d8SAlex Williamson * RTL8168 devices have a backdoor that can access the MSI-X table. At BAR2 767c00d61d8SAlex Williamson * offset 0x70 there is a dword data register, offset 0x74 is a dword address 768c00d61d8SAlex Williamson * register. According to the Linux r8169 driver, the MSI-X table is addressed 769c00d61d8SAlex Williamson * when the "type" portion of the address register is set to 0x1. This appears 770c00d61d8SAlex Williamson * to be bits 16:30. Bit 31 is both a write indicator and some sort of 771c00d61d8SAlex Williamson * "address latched" indicator. Bits 12:15 are a mask field, which we can 772c00d61d8SAlex Williamson * ignore because the MSI-X table should always be accessed as a dword (full 773c00d61d8SAlex Williamson * mask). Bits 0:11 is offset within the type. 774c00d61d8SAlex Williamson * 775c00d61d8SAlex Williamson * Example trace: 776c00d61d8SAlex Williamson * 777c00d61d8SAlex Williamson * Read from MSI-X table offset 0 778c00d61d8SAlex Williamson * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x74, 0x1f000, 4) // store read addr 779c00d61d8SAlex Williamson * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x74, 4) = 0x8001f000 // latch 780c00d61d8SAlex Williamson * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x70, 4) = 0xfee00398 // read data 781c00d61d8SAlex Williamson * 782c00d61d8SAlex Williamson * Write 0xfee00000 to MSI-X table offset 0 783c00d61d8SAlex Williamson * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x70, 0xfee00000, 4) // write data 784c00d61d8SAlex Williamson * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x74, 0x8001f000, 4) // do write 785c00d61d8SAlex Williamson * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x74, 4) = 0x1f000 // complete 786c00d61d8SAlex Williamson */ 787c00d61d8SAlex Williamson static uint64_t vfio_rtl8168_window_quirk_read(void *opaque, 788c00d61d8SAlex Williamson hwaddr addr, unsigned size) 789c00d61d8SAlex Williamson { 7908c4f2348SAlex Williamson VFIOLegacyQuirk *quirk = opaque; 791c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 792c00d61d8SAlex Williamson uint64_t val = 0; 793c00d61d8SAlex Williamson 794c00d61d8SAlex Williamson if (!quirk->data.flags) { /* Non-MSI-X table access */ 795c00d61d8SAlex Williamson return vfio_region_read(&vdev->bars[quirk->data.bar].region, 796c00d61d8SAlex Williamson addr + 0x70, size); 797c00d61d8SAlex Williamson } 798c00d61d8SAlex Williamson 799c00d61d8SAlex Williamson switch (addr) { 800c00d61d8SAlex Williamson case 4: /* address */ 801c00d61d8SAlex Williamson val = quirk->data.address_match ^ 0x80000000U; /* latch/complete */ 802c00d61d8SAlex Williamson break; 803c00d61d8SAlex Williamson case 0: /* data */ 804c00d61d8SAlex Williamson if ((vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) { 805c00d61d8SAlex Williamson memory_region_dispatch_read(&vdev->pdev.msix_table_mmio, 806c00d61d8SAlex Williamson (hwaddr)(quirk->data.address_match & 0xfff), 807c00d61d8SAlex Williamson &val, size, MEMTXATTRS_UNSPECIFIED); 808c00d61d8SAlex Williamson } 809c00d61d8SAlex Williamson break; 810c00d61d8SAlex Williamson } 811c00d61d8SAlex Williamson 812c00d61d8SAlex Williamson trace_vfio_rtl8168_quirk_read(vdev->vbasedev.name, 813c00d61d8SAlex Williamson addr ? "address" : "data", val); 814c00d61d8SAlex Williamson return val; 815c00d61d8SAlex Williamson } 816c00d61d8SAlex Williamson 817c00d61d8SAlex Williamson static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr, 818c00d61d8SAlex Williamson uint64_t data, unsigned size) 819c00d61d8SAlex Williamson { 8208c4f2348SAlex Williamson VFIOLegacyQuirk *quirk = opaque; 821c00d61d8SAlex Williamson VFIOPCIDevice *vdev = quirk->vdev; 822c00d61d8SAlex Williamson 823c00d61d8SAlex Williamson switch (addr) { 824c00d61d8SAlex Williamson case 4: /* address */ 825c00d61d8SAlex Williamson if ((data & 0x7fff0000) == 0x10000) { /* MSI-X table */ 826c00d61d8SAlex Williamson quirk->data.flags = 1; /* Activate reads */ 827c00d61d8SAlex Williamson quirk->data.address_match = data; 828c00d61d8SAlex Williamson 829c00d61d8SAlex Williamson trace_vfio_rtl8168_quirk_write(vdev->vbasedev.name, data); 830c00d61d8SAlex Williamson 831c00d61d8SAlex Williamson if (data & 0x80000000U) { /* Do write */ 832c00d61d8SAlex Williamson if (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) { 833c00d61d8SAlex Williamson hwaddr offset = data & 0xfff; 834c00d61d8SAlex Williamson uint64_t val = quirk->data.address_mask; 835c00d61d8SAlex Williamson 836c00d61d8SAlex Williamson trace_vfio_rtl8168_quirk_msix(vdev->vbasedev.name, 837c00d61d8SAlex Williamson (uint16_t)offset, val); 838c00d61d8SAlex Williamson 839c00d61d8SAlex Williamson /* Write to the proper guest MSI-X table instead */ 840c00d61d8SAlex Williamson memory_region_dispatch_write(&vdev->pdev.msix_table_mmio, 841c00d61d8SAlex Williamson offset, val, size, 842c00d61d8SAlex Williamson MEMTXATTRS_UNSPECIFIED); 843c00d61d8SAlex Williamson } 844c00d61d8SAlex Williamson return; /* Do not write guest MSI-X data to hardware */ 845c00d61d8SAlex Williamson } 846c00d61d8SAlex Williamson } else { 847c00d61d8SAlex Williamson quirk->data.flags = 0; /* De-activate reads, non-MSI-X */ 848c00d61d8SAlex Williamson } 849c00d61d8SAlex Williamson break; 850c00d61d8SAlex Williamson case 0: /* data */ 851c00d61d8SAlex Williamson quirk->data.address_mask = data; 852c00d61d8SAlex Williamson break; 853c00d61d8SAlex Williamson } 854c00d61d8SAlex Williamson 855c00d61d8SAlex Williamson vfio_region_write(&vdev->bars[quirk->data.bar].region, 856c00d61d8SAlex Williamson addr + 0x70, data, size); 857c00d61d8SAlex Williamson } 858c00d61d8SAlex Williamson 859c00d61d8SAlex Williamson static const MemoryRegionOps vfio_rtl8168_window_quirk = { 860c00d61d8SAlex Williamson .read = vfio_rtl8168_window_quirk_read, 861c00d61d8SAlex Williamson .write = vfio_rtl8168_window_quirk_write, 862c00d61d8SAlex Williamson .valid = { 863c00d61d8SAlex Williamson .min_access_size = 4, 864c00d61d8SAlex Williamson .max_access_size = 4, 865c00d61d8SAlex Williamson .unaligned = false, 866c00d61d8SAlex Williamson }, 867c00d61d8SAlex Williamson .endianness = DEVICE_LITTLE_ENDIAN, 868c00d61d8SAlex Williamson }; 869c00d61d8SAlex Williamson 870c00d61d8SAlex Williamson static void vfio_probe_rtl8168_bar2_window_quirk(VFIOPCIDevice *vdev, int nr) 871c00d61d8SAlex Williamson { 872c00d61d8SAlex Williamson PCIDevice *pdev = &vdev->pdev; 873c00d61d8SAlex Williamson VFIOQuirk *quirk; 8748c4f2348SAlex Williamson VFIOLegacyQuirk *legacy; 875c00d61d8SAlex Williamson 876c00d61d8SAlex Williamson if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_REALTEK || 877c00d61d8SAlex Williamson pci_get_word(pdev->config + PCI_DEVICE_ID) != 0x8168 || nr != 2) { 878c00d61d8SAlex Williamson return; 879c00d61d8SAlex Williamson } 880c00d61d8SAlex Williamson 881c00d61d8SAlex Williamson quirk = g_malloc0(sizeof(*quirk)); 8828c4f2348SAlex Williamson quirk->data = legacy = g_malloc0(sizeof(*legacy)); 8838c4f2348SAlex Williamson quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1); 8848c4f2348SAlex Williamson quirk->nr_mem = 1; 8858c4f2348SAlex Williamson legacy->vdev = vdev; 8868c4f2348SAlex Williamson legacy->data.bar = nr; 887c00d61d8SAlex Williamson 8888c4f2348SAlex Williamson memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_rtl8168_window_quirk, 8898c4f2348SAlex Williamson legacy, "vfio-rtl8168-window-quirk", 8); 890c00d61d8SAlex Williamson memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 8918c4f2348SAlex Williamson 0x70, quirk->mem, 1); 892c00d61d8SAlex Williamson 893c00d61d8SAlex Williamson QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); 894c00d61d8SAlex Williamson 895c00d61d8SAlex Williamson trace_vfio_rtl8168_quirk_enable(vdev->vbasedev.name); 896c00d61d8SAlex Williamson } 897c00d61d8SAlex Williamson 898c00d61d8SAlex Williamson /* 899c00d61d8SAlex Williamson * Common quirk probe entry points. 900c00d61d8SAlex Williamson */ 901c00d61d8SAlex Williamson void vfio_vga_quirk_setup(VFIOPCIDevice *vdev) 902c00d61d8SAlex Williamson { 903c00d61d8SAlex Williamson vfio_vga_probe_ati_3c3_quirk(vdev); 904c00d61d8SAlex Williamson vfio_vga_probe_nvidia_3d0_quirk(vdev); 905c00d61d8SAlex Williamson } 906c00d61d8SAlex Williamson 907c00d61d8SAlex Williamson void vfio_vga_quirk_teardown(VFIOPCIDevice *vdev) 908c00d61d8SAlex Williamson { 909c00d61d8SAlex Williamson VFIOQuirk *quirk; 9108c4f2348SAlex Williamson int i, j; 911c00d61d8SAlex Williamson 912c00d61d8SAlex Williamson for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) { 913c00d61d8SAlex Williamson QLIST_FOREACH(quirk, &vdev->vga.region[i].quirks, next) { 9148c4f2348SAlex Williamson for (j = 0; j < quirk->nr_mem; j++) { 9158c4f2348SAlex Williamson memory_region_del_subregion(&vdev->vga.region[i].mem, 9168c4f2348SAlex Williamson &quirk->mem[j]); 9178c4f2348SAlex Williamson } 918c00d61d8SAlex Williamson } 919c00d61d8SAlex Williamson } 920c00d61d8SAlex Williamson } 921c00d61d8SAlex Williamson 922c00d61d8SAlex Williamson void vfio_vga_quirk_free(VFIOPCIDevice *vdev) 923c00d61d8SAlex Williamson { 9248c4f2348SAlex Williamson int i, j; 925c00d61d8SAlex Williamson 926c00d61d8SAlex Williamson for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) { 927c00d61d8SAlex Williamson while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) { 928c00d61d8SAlex Williamson VFIOQuirk *quirk = QLIST_FIRST(&vdev->vga.region[i].quirks); 929c00d61d8SAlex Williamson QLIST_REMOVE(quirk, next); 9308c4f2348SAlex Williamson for (j = 0; j < quirk->nr_mem; j++) { 9318c4f2348SAlex Williamson object_unparent(OBJECT(&quirk->mem[j])); 9328c4f2348SAlex Williamson } 9338c4f2348SAlex Williamson g_free(quirk->mem); 9348c4f2348SAlex Williamson g_free(quirk->data); 935c00d61d8SAlex Williamson g_free(quirk); 936c00d61d8SAlex Williamson } 937c00d61d8SAlex Williamson } 938c00d61d8SAlex Williamson } 939c00d61d8SAlex Williamson 940c00d61d8SAlex Williamson void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr) 941c00d61d8SAlex Williamson { 942c00d61d8SAlex Williamson vfio_probe_ati_bar4_window_quirk(vdev, nr); 943c00d61d8SAlex Williamson vfio_probe_ati_bar2_4000_quirk(vdev, nr); 944c00d61d8SAlex Williamson vfio_probe_nvidia_bar5_window_quirk(vdev, nr); 945c00d61d8SAlex Williamson vfio_probe_nvidia_bar0_88000_quirk(vdev, nr); 946c00d61d8SAlex Williamson vfio_probe_nvidia_bar0_1800_quirk(vdev, nr); 947c00d61d8SAlex Williamson vfio_probe_rtl8168_bar2_window_quirk(vdev, nr); 948c00d61d8SAlex Williamson } 949c00d61d8SAlex Williamson 950c00d61d8SAlex Williamson void vfio_bar_quirk_teardown(VFIOPCIDevice *vdev, int nr) 951c00d61d8SAlex Williamson { 952c00d61d8SAlex Williamson VFIOBAR *bar = &vdev->bars[nr]; 953c00d61d8SAlex Williamson VFIOQuirk *quirk; 9548c4f2348SAlex Williamson int i; 955c00d61d8SAlex Williamson 956c00d61d8SAlex Williamson QLIST_FOREACH(quirk, &bar->quirks, next) { 9578c4f2348SAlex Williamson for (i = 0; i < quirk->nr_mem; i++) { 9588c4f2348SAlex Williamson memory_region_del_subregion(&bar->region.mem, &quirk->mem[i]); 9598c4f2348SAlex Williamson } 960c00d61d8SAlex Williamson } 961c00d61d8SAlex Williamson } 962c00d61d8SAlex Williamson 963c00d61d8SAlex Williamson void vfio_bar_quirk_free(VFIOPCIDevice *vdev, int nr) 964c00d61d8SAlex Williamson { 965c00d61d8SAlex Williamson VFIOBAR *bar = &vdev->bars[nr]; 9668c4f2348SAlex Williamson int i; 967c00d61d8SAlex Williamson 968c00d61d8SAlex Williamson while (!QLIST_EMPTY(&bar->quirks)) { 969c00d61d8SAlex Williamson VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks); 970c00d61d8SAlex Williamson QLIST_REMOVE(quirk, next); 9718c4f2348SAlex Williamson for (i = 0; i < quirk->nr_mem; i++) { 9728c4f2348SAlex Williamson object_unparent(OBJECT(&quirk->mem[i])); 9738c4f2348SAlex Williamson } 9748c4f2348SAlex Williamson g_free(quirk->mem); 9758c4f2348SAlex Williamson g_free(quirk->data); 976c00d61d8SAlex Williamson g_free(quirk); 977c00d61d8SAlex Williamson } 978c00d61d8SAlex Williamson } 979