xref: /qemu/hw/vfio/pci-quirks.c (revision c00d61d8fa22b096b15e19ee2fde846ffc1c0b5d)
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