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