]>
Commit | Line | Data |
---|---|---|
c00d61d8 AW |
1 | /* |
2 | * device quirks for PCI devices | |
3 | * | |
4 | * Copyright Red Hat, Inc. 2012-2015 | |
5 | * | |
6 | * Authors: | |
7 | * Alex Williamson <[email protected]> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
10 | * the COPYING file in the top-level directory. | |
11 | */ | |
12 | ||
13 | #include "pci.h" | |
14 | #include "trace.h" | |
15 | #include "qemu/range.h" | |
16 | ||
056dfcb6 AW |
17 | /* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */ |
18 | static bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device) | |
19 | { | |
ff635e37 AW |
20 | return (vendor == PCI_ANY_ID || vendor == vdev->vendor_id) && |
21 | (device == PCI_ANY_ID || device == vdev->device_id); | |
056dfcb6 AW |
22 | } |
23 | ||
0d38fb1c AW |
24 | static bool vfio_is_vga(VFIOPCIDevice *vdev) |
25 | { | |
26 | PCIDevice *pdev = &vdev->pdev; | |
27 | uint16_t class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); | |
28 | ||
29 | return class == PCI_CLASS_DISPLAY_VGA; | |
30 | } | |
31 | ||
c00d61d8 AW |
32 | /* |
33 | * List of device ids/vendor ids for which to disable | |
34 | * option rom loading. This avoids the guest hangs during rom | |
35 | * execution as noticed with the BCM 57810 card for lack of a | |
36 | * more better way to handle such issues. | |
37 | * The user can still override by specifying a romfile or | |
38 | * rombar=1. | |
39 | * Please see https://bugs.launchpad.net/qemu/+bug/1284874 | |
40 | * for an analysis of the 57810 card hang. When adding | |
41 | * a new vendor id/device id combination below, please also add | |
42 | * your card/environment details and information that could | |
43 | * help in debugging to the bug tracking this issue | |
44 | */ | |
056dfcb6 AW |
45 | static const struct { |
46 | uint32_t vendor; | |
47 | uint32_t device; | |
48 | } romblacklist[] = { | |
49 | { 0x14e4, 0x168e }, /* Broadcom BCM 57810 */ | |
c00d61d8 AW |
50 | }; |
51 | ||
52 | bool vfio_blacklist_opt_rom(VFIOPCIDevice *vdev) | |
53 | { | |
056dfcb6 | 54 | int i; |
c00d61d8 | 55 | |
056dfcb6 AW |
56 | for (i = 0 ; i < ARRAY_SIZE(romblacklist); i++) { |
57 | if (vfio_pci_is(vdev, romblacklist[i].vendor, romblacklist[i].device)) { | |
58 | trace_vfio_quirk_rom_blacklisted(vdev->vbasedev.name, | |
59 | romblacklist[i].vendor, | |
60 | romblacklist[i].device); | |
61 | return true; | |
c00d61d8 | 62 | } |
c00d61d8 | 63 | } |
c00d61d8 AW |
64 | return false; |
65 | } | |
66 | ||
67 | /* | |
0e54f24a | 68 | * Device specific region quirks (mostly backdoors to PCI config space) |
c00d61d8 AW |
69 | */ |
70 | ||
0e54f24a AW |
71 | /* |
72 | * The generic window quirks operate on an address and data register, | |
73 | * vfio_generic_window_address_quirk handles the address register and | |
74 | * vfio_generic_window_data_quirk handles the data register. These ops | |
75 | * pass reads and writes through to hardware until a value matching the | |
76 | * stored address match/mask is written. When this occurs, the data | |
77 | * register access emulated PCI config space for the device rather than | |
78 | * passing through accesses. This enables devices where PCI config space | |
79 | * is accessible behind a window register to maintain the virtualization | |
80 | * provided through vfio. | |
81 | */ | |
82 | typedef struct VFIOConfigWindowMatch { | |
83 | uint32_t match; | |
84 | uint32_t mask; | |
85 | } VFIOConfigWindowMatch; | |
86 | ||
87 | typedef struct VFIOConfigWindowQuirk { | |
88 | struct VFIOPCIDevice *vdev; | |
89 | ||
90 | uint32_t address_val; | |
91 | ||
92 | uint32_t address_offset; | |
93 | uint32_t data_offset; | |
94 | ||
95 | bool window_enabled; | |
96 | uint8_t bar; | |
97 | ||
98 | MemoryRegion *addr_mem; | |
99 | MemoryRegion *data_mem; | |
100 | ||
101 | uint32_t nr_matches; | |
102 | VFIOConfigWindowMatch matches[]; | |
103 | } VFIOConfigWindowQuirk; | |
104 | ||
105 | static uint64_t vfio_generic_window_quirk_address_read(void *opaque, | |
106 | hwaddr addr, | |
107 | unsigned size) | |
108 | { | |
109 | VFIOConfigWindowQuirk *window = opaque; | |
110 | VFIOPCIDevice *vdev = window->vdev; | |
111 | ||
112 | return vfio_region_read(&vdev->bars[window->bar].region, | |
113 | addr + window->address_offset, size); | |
114 | } | |
115 | ||
116 | static void vfio_generic_window_quirk_address_write(void *opaque, hwaddr addr, | |
117 | uint64_t data, | |
118 | unsigned size) | |
119 | { | |
120 | VFIOConfigWindowQuirk *window = opaque; | |
121 | VFIOPCIDevice *vdev = window->vdev; | |
122 | int i; | |
123 | ||
124 | window->window_enabled = false; | |
125 | ||
126 | vfio_region_write(&vdev->bars[window->bar].region, | |
127 | addr + window->address_offset, data, size); | |
128 | ||
129 | for (i = 0; i < window->nr_matches; i++) { | |
130 | if ((data & ~window->matches[i].mask) == window->matches[i].match) { | |
131 | window->window_enabled = true; | |
132 | window->address_val = data & window->matches[i].mask; | |
133 | trace_vfio_quirk_generic_window_address_write(vdev->vbasedev.name, | |
134 | memory_region_name(window->addr_mem), data); | |
135 | break; | |
136 | } | |
137 | } | |
138 | } | |
139 | ||
140 | static const MemoryRegionOps vfio_generic_window_address_quirk = { | |
141 | .read = vfio_generic_window_quirk_address_read, | |
142 | .write = vfio_generic_window_quirk_address_write, | |
143 | .endianness = DEVICE_LITTLE_ENDIAN, | |
144 | }; | |
145 | ||
146 | static uint64_t vfio_generic_window_quirk_data_read(void *opaque, | |
147 | hwaddr addr, unsigned size) | |
148 | { | |
149 | VFIOConfigWindowQuirk *window = opaque; | |
150 | VFIOPCIDevice *vdev = window->vdev; | |
151 | uint64_t data; | |
152 | ||
153 | /* Always read data reg, discard if window enabled */ | |
154 | data = vfio_region_read(&vdev->bars[window->bar].region, | |
155 | addr + window->data_offset, size); | |
156 | ||
157 | if (window->window_enabled) { | |
158 | data = vfio_pci_read_config(&vdev->pdev, window->address_val, size); | |
159 | trace_vfio_quirk_generic_window_data_read(vdev->vbasedev.name, | |
160 | memory_region_name(window->data_mem), data); | |
161 | } | |
162 | ||
163 | return data; | |
164 | } | |
165 | ||
166 | static void vfio_generic_window_quirk_data_write(void *opaque, hwaddr addr, | |
167 | uint64_t data, unsigned size) | |
168 | { | |
169 | VFIOConfigWindowQuirk *window = opaque; | |
170 | VFIOPCIDevice *vdev = window->vdev; | |
171 | ||
172 | if (window->window_enabled) { | |
173 | vfio_pci_write_config(&vdev->pdev, window->address_val, data, size); | |
174 | trace_vfio_quirk_generic_window_data_write(vdev->vbasedev.name, | |
175 | memory_region_name(window->data_mem), data); | |
176 | return; | |
177 | } | |
178 | ||
179 | vfio_region_write(&vdev->bars[window->bar].region, | |
180 | addr + window->data_offset, data, size); | |
181 | } | |
182 | ||
183 | static const MemoryRegionOps vfio_generic_window_data_quirk = { | |
184 | .read = vfio_generic_window_quirk_data_read, | |
185 | .write = vfio_generic_window_quirk_data_write, | |
186 | .endianness = DEVICE_LITTLE_ENDIAN, | |
187 | }; | |
188 | ||
0d38fb1c AW |
189 | /* |
190 | * The generic mirror quirk handles devices which expose PCI config space | |
191 | * through a region within a BAR. When enabled, reads and writes are | |
192 | * redirected through to emulated PCI config space. XXX if PCI config space | |
193 | * used memory regions, this could just be an alias. | |
194 | */ | |
195 | typedef struct VFIOConfigMirrorQuirk { | |
196 | struct VFIOPCIDevice *vdev; | |
197 | uint32_t offset; | |
198 | uint8_t bar; | |
199 | MemoryRegion *mem; | |
200 | } VFIOConfigMirrorQuirk; | |
201 | ||
202 | static uint64_t vfio_generic_quirk_mirror_read(void *opaque, | |
203 | hwaddr addr, unsigned size) | |
204 | { | |
205 | VFIOConfigMirrorQuirk *mirror = opaque; | |
206 | VFIOPCIDevice *vdev = mirror->vdev; | |
207 | uint64_t data; | |
208 | ||
209 | /* Read and discard in case the hardware cares */ | |
210 | (void)vfio_region_read(&vdev->bars[mirror->bar].region, | |
211 | addr + mirror->offset, size); | |
212 | ||
213 | data = vfio_pci_read_config(&vdev->pdev, addr, size); | |
214 | trace_vfio_quirk_generic_mirror_read(vdev->vbasedev.name, | |
215 | memory_region_name(mirror->mem), | |
216 | addr, data); | |
217 | return data; | |
218 | } | |
219 | ||
220 | static void vfio_generic_quirk_mirror_write(void *opaque, hwaddr addr, | |
221 | uint64_t data, unsigned size) | |
222 | { | |
223 | VFIOConfigMirrorQuirk *mirror = opaque; | |
224 | VFIOPCIDevice *vdev = mirror->vdev; | |
225 | ||
226 | vfio_pci_write_config(&vdev->pdev, addr, data, size); | |
227 | trace_vfio_quirk_generic_mirror_write(vdev->vbasedev.name, | |
228 | memory_region_name(mirror->mem), | |
229 | addr, data); | |
230 | } | |
231 | ||
232 | static const MemoryRegionOps vfio_generic_mirror_quirk = { | |
233 | .read = vfio_generic_quirk_mirror_read, | |
234 | .write = vfio_generic_quirk_mirror_write, | |
235 | .endianness = DEVICE_LITTLE_ENDIAN, | |
236 | }; | |
237 | ||
c00d61d8 AW |
238 | /* Is range1 fully contained within range2? */ |
239 | static bool vfio_range_contained(uint64_t first1, uint64_t len1, | |
240 | uint64_t first2, uint64_t len2) { | |
241 | return (first1 >= first2 && first1 + len1 <= first2 + len2); | |
242 | } | |
243 | ||
c00d61d8 AW |
244 | #define PCI_VENDOR_ID_ATI 0x1002 |
245 | ||
246 | /* | |
247 | * Radeon HD cards (HD5450 & HD7850) report the upper byte of the I/O port BAR | |
248 | * through VGA register 0x3c3. On newer cards, the I/O port BAR is always | |
249 | * BAR4 (older cards like the X550 used BAR1, but we don't care to support | |
250 | * those). Note that on bare metal, a read of 0x3c3 doesn't always return the | |
251 | * I/O port BAR address. Originally this was coded to return the virtual BAR | |
252 | * address only if the physical register read returns the actual BAR address, | |
253 | * but users have reported greater success if we return the virtual address | |
254 | * unconditionally. | |
255 | */ | |
256 | static uint64_t vfio_ati_3c3_quirk_read(void *opaque, | |
257 | hwaddr addr, unsigned size) | |
258 | { | |
b946d286 | 259 | VFIOPCIDevice *vdev = opaque; |
c00d61d8 | 260 | uint64_t data = vfio_pci_read_config(&vdev->pdev, |
b946d286 AW |
261 | PCI_BASE_ADDRESS_4 + 1, size); |
262 | ||
263 | trace_vfio_quirk_ati_3c3_read(vdev->vbasedev.name, data); | |
c00d61d8 AW |
264 | |
265 | return data; | |
266 | } | |
267 | ||
268 | static const MemoryRegionOps vfio_ati_3c3_quirk = { | |
269 | .read = vfio_ati_3c3_quirk_read, | |
270 | .endianness = DEVICE_LITTLE_ENDIAN, | |
271 | }; | |
272 | ||
273 | static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice *vdev) | |
274 | { | |
c00d61d8 | 275 | VFIOQuirk *quirk; |
c00d61d8 AW |
276 | |
277 | /* | |
278 | * As long as the BAR is >= 256 bytes it will be aligned such that the | |
279 | * lower byte is always zero. Filter out anything else, if it exists. | |
280 | */ | |
b946d286 AW |
281 | if (!vfio_pci_is(vdev, PCI_VENDOR_ID_ATI, PCI_ANY_ID) || |
282 | !vdev->bars[4].ioport || vdev->bars[4].region.size < 256) { | |
c00d61d8 AW |
283 | return; |
284 | } | |
285 | ||
286 | quirk = g_malloc0(sizeof(*quirk)); | |
9d146b2e | 287 | quirk->mem = g_malloc0(sizeof(MemoryRegion)); |
8c4f2348 | 288 | quirk->nr_mem = 1; |
c00d61d8 | 289 | |
b946d286 | 290 | memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, vdev, |
c00d61d8 AW |
291 | "vfio-ati-3c3-quirk", 1); |
292 | memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, | |
8c4f2348 | 293 | 3 /* offset 3 bytes from 0x3c0 */, quirk->mem); |
c00d61d8 AW |
294 | |
295 | QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, | |
296 | quirk, next); | |
297 | ||
b946d286 | 298 | trace_vfio_quirk_ati_3c3_probe(vdev->vbasedev.name); |
c00d61d8 AW |
299 | } |
300 | ||
301 | /* | |
0e54f24a | 302 | * Newer ATI/AMD devices, including HD5450 and HD7850, have a mirror to PCI |
c00d61d8 AW |
303 | * config space through MMIO BAR2 at offset 0x4000. Nothing seems to access |
304 | * the MMIO space directly, but a window to this space is provided through | |
305 | * I/O port BAR4. Offset 0x0 is the address register and offset 0x4 is the | |
306 | * data register. When the address is programmed to a range of 0x4000-0x4fff | |
307 | * PCI configuration space is available. Experimentation seems to indicate | |
0e54f24a | 308 | * that read-only may be provided by hardware. |
c00d61d8 | 309 | */ |
0e54f24a | 310 | static void vfio_probe_ati_bar4_quirk(VFIOPCIDevice *vdev, int nr) |
c00d61d8 | 311 | { |
c00d61d8 | 312 | VFIOQuirk *quirk; |
0e54f24a | 313 | VFIOConfigWindowQuirk *window; |
c00d61d8 | 314 | |
0e54f24a AW |
315 | /* This windows doesn't seem to be used except by legacy VGA code */ |
316 | if (!vfio_pci_is(vdev, PCI_VENDOR_ID_ATI, PCI_ANY_ID) || | |
317 | !vdev->has_vga || nr != 4) { | |
c00d61d8 AW |
318 | return; |
319 | } | |
320 | ||
321 | quirk = g_malloc0(sizeof(*quirk)); | |
9d146b2e | 322 | quirk->mem = g_malloc0(sizeof(MemoryRegion) * 2); |
0e54f24a AW |
323 | quirk->nr_mem = 2; |
324 | window = quirk->data = g_malloc0(sizeof(*window) + | |
325 | sizeof(VFIOConfigWindowMatch)); | |
326 | window->vdev = vdev; | |
327 | window->address_offset = 0; | |
328 | window->data_offset = 4; | |
329 | window->nr_matches = 1; | |
330 | window->matches[0].match = 0x4000; | |
331 | window->matches[0].mask = PCIE_CONFIG_SPACE_SIZE - 1; | |
332 | window->bar = nr; | |
333 | window->addr_mem = &quirk->mem[0]; | |
334 | window->data_mem = &quirk->mem[1]; | |
335 | ||
336 | memory_region_init_io(window->addr_mem, OBJECT(vdev), | |
337 | &vfio_generic_window_address_quirk, window, | |
338 | "vfio-ati-bar4-window-address-quirk", 4); | |
339 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, | |
340 | window->address_offset, | |
341 | window->addr_mem, 1); | |
8c4f2348 | 342 | |
0e54f24a AW |
343 | memory_region_init_io(window->data_mem, OBJECT(vdev), |
344 | &vfio_generic_window_data_quirk, window, | |
345 | "vfio-ati-bar4-window-data-quirk", 4); | |
c00d61d8 | 346 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, |
0e54f24a AW |
347 | window->data_offset, |
348 | window->data_mem, 1); | |
c00d61d8 AW |
349 | |
350 | QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); | |
351 | ||
0e54f24a | 352 | trace_vfio_quirk_ati_bar4_probe(vdev->vbasedev.name); |
c00d61d8 AW |
353 | } |
354 | ||
355 | /* | |
0d38fb1c | 356 | * Trap the BAR2 MMIO mirror to config space as well. |
c00d61d8 | 357 | */ |
0d38fb1c | 358 | static void vfio_probe_ati_bar2_quirk(VFIOPCIDevice *vdev, int nr) |
c00d61d8 | 359 | { |
c00d61d8 | 360 | VFIOQuirk *quirk; |
0d38fb1c | 361 | VFIOConfigMirrorQuirk *mirror; |
c00d61d8 AW |
362 | |
363 | /* Only enable on newer devices where BAR2 is 64bit */ | |
0d38fb1c AW |
364 | if (!vfio_pci_is(vdev, PCI_VENDOR_ID_ATI, PCI_ANY_ID) || |
365 | !vdev->has_vga || nr != 2 || !vdev->bars[2].mem64) { | |
c00d61d8 AW |
366 | return; |
367 | } | |
368 | ||
369 | quirk = g_malloc0(sizeof(*quirk)); | |
0d38fb1c | 370 | mirror = quirk->data = g_malloc0(sizeof(*mirror)); |
9d146b2e | 371 | mirror->mem = quirk->mem = g_malloc0(sizeof(MemoryRegion)); |
8c4f2348 | 372 | quirk->nr_mem = 1; |
0d38fb1c AW |
373 | mirror->vdev = vdev; |
374 | mirror->offset = 0x4000; | |
375 | mirror->bar = nr; | |
376 | ||
377 | memory_region_init_io(mirror->mem, OBJECT(vdev), | |
378 | &vfio_generic_mirror_quirk, mirror, | |
379 | "vfio-ati-bar2-4000-quirk", PCI_CONFIG_SPACE_SIZE); | |
c00d61d8 | 380 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, |
0d38fb1c | 381 | mirror->offset, mirror->mem, 1); |
c00d61d8 AW |
382 | |
383 | QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); | |
384 | ||
0d38fb1c | 385 | trace_vfio_quirk_ati_bar2_probe(vdev->vbasedev.name); |
c00d61d8 AW |
386 | } |
387 | ||
388 | /* | |
389 | * Older ATI/AMD cards like the X550 have a similar window to that above. | |
390 | * I/O port BAR1 provides a window to a mirror of PCI config space located | |
391 | * in BAR2 at offset 0xf00. We don't care to support such older cards, but | |
392 | * note it for future reference. | |
393 | */ | |
394 | ||
395 | #define PCI_VENDOR_ID_NVIDIA 0x10de | |
396 | ||
397 | /* | |
398 | * Nvidia has several different methods to get to config space, the | |
399 | * nouveu project has several of these documented here: | |
400 | * https://github.com/pathscale/envytools/tree/master/hwdocs | |
401 | * | |
402 | * The first quirk is actually not documented in envytools and is found | |
403 | * on 10de:01d1 (NVIDIA Corporation G72 [GeForce 7300 LE]). This is an | |
404 | * NV46 chipset. The backdoor uses the legacy VGA I/O ports to access | |
405 | * the mirror of PCI config space found at BAR0 offset 0x1800. The access | |
406 | * sequence first writes 0x338 to I/O port 0x3d4. The target offset is | |
407 | * then written to 0x3d0. Finally 0x538 is written for a read and 0x738 | |
408 | * is written for a write to 0x3d4. The BAR0 offset is then accessible | |
409 | * through 0x3d0. This quirk doesn't seem to be necessary on newer cards | |
410 | * that use the I/O port BAR5 window but it doesn't hurt to leave it. | |
411 | */ | |
6029a424 AW |
412 | typedef enum {NONE = 0, SELECT, WINDOW, READ, WRITE} VFIONvidia3d0State; |
413 | static const char *nv3d0_states[] = { "NONE", "SELECT", | |
414 | "WINDOW", "READ", "WRITE" }; | |
c00d61d8 | 415 | |
6029a424 AW |
416 | typedef struct VFIONvidia3d0Quirk { |
417 | VFIOPCIDevice *vdev; | |
418 | VFIONvidia3d0State state; | |
419 | uint32_t offset; | |
420 | } VFIONvidia3d0Quirk; | |
421 | ||
422 | static uint64_t vfio_nvidia_3d4_quirk_read(void *opaque, | |
c00d61d8 AW |
423 | hwaddr addr, unsigned size) |
424 | { | |
6029a424 | 425 | VFIONvidia3d0Quirk *quirk = opaque; |
c00d61d8 | 426 | VFIOPCIDevice *vdev = quirk->vdev; |
c00d61d8 | 427 | |
6029a424 | 428 | quirk->state = NONE; |
c00d61d8 | 429 | |
6029a424 AW |
430 | return vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], |
431 | addr + 0x14, size); | |
c00d61d8 AW |
432 | } |
433 | ||
6029a424 | 434 | static void vfio_nvidia_3d4_quirk_write(void *opaque, hwaddr addr, |
c00d61d8 AW |
435 | uint64_t data, unsigned size) |
436 | { | |
6029a424 | 437 | VFIONvidia3d0Quirk *quirk = opaque; |
c00d61d8 | 438 | VFIOPCIDevice *vdev = quirk->vdev; |
6029a424 | 439 | VFIONvidia3d0State old_state = quirk->state; |
c00d61d8 | 440 | |
6029a424 AW |
441 | quirk->state = NONE; |
442 | ||
443 | switch (data) { | |
444 | case 0x338: | |
445 | if (old_state == NONE) { | |
446 | quirk->state = SELECT; | |
447 | trace_vfio_quirk_nvidia_3d0_state(vdev->vbasedev.name, | |
448 | nv3d0_states[quirk->state]); | |
c00d61d8 AW |
449 | } |
450 | break; | |
6029a424 AW |
451 | case 0x538: |
452 | if (old_state == WINDOW) { | |
453 | quirk->state = READ; | |
454 | trace_vfio_quirk_nvidia_3d0_state(vdev->vbasedev.name, | |
455 | nv3d0_states[quirk->state]); | |
c00d61d8 AW |
456 | } |
457 | break; | |
6029a424 AW |
458 | case 0x738: |
459 | if (old_state == WINDOW) { | |
460 | quirk->state = WRITE; | |
461 | trace_vfio_quirk_nvidia_3d0_state(vdev->vbasedev.name, | |
462 | nv3d0_states[quirk->state]); | |
c00d61d8 AW |
463 | } |
464 | break; | |
6029a424 AW |
465 | } |
466 | ||
467 | vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], | |
468 | addr + 0x14, data, size); | |
469 | } | |
470 | ||
471 | static const MemoryRegionOps vfio_nvidia_3d4_quirk = { | |
472 | .read = vfio_nvidia_3d4_quirk_read, | |
473 | .write = vfio_nvidia_3d4_quirk_write, | |
474 | .endianness = DEVICE_LITTLE_ENDIAN, | |
475 | }; | |
476 | ||
477 | static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque, | |
478 | hwaddr addr, unsigned size) | |
479 | { | |
480 | VFIONvidia3d0Quirk *quirk = opaque; | |
481 | VFIOPCIDevice *vdev = quirk->vdev; | |
482 | VFIONvidia3d0State old_state = quirk->state; | |
483 | uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], | |
484 | addr + 0x10, size); | |
485 | ||
486 | quirk->state = NONE; | |
487 | ||
488 | if (old_state == READ && | |
489 | (quirk->offset & ~(PCI_CONFIG_SPACE_SIZE - 1)) == 0x1800) { | |
490 | uint8_t offset = quirk->offset & (PCI_CONFIG_SPACE_SIZE - 1); | |
491 | ||
492 | data = vfio_pci_read_config(&vdev->pdev, offset, size); | |
493 | trace_vfio_quirk_nvidia_3d0_read(vdev->vbasedev.name, | |
494 | offset, size, data); | |
495 | } | |
496 | ||
497 | return data; | |
498 | } | |
499 | ||
500 | static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr, | |
501 | uint64_t data, unsigned size) | |
502 | { | |
503 | VFIONvidia3d0Quirk *quirk = opaque; | |
504 | VFIOPCIDevice *vdev = quirk->vdev; | |
505 | VFIONvidia3d0State old_state = quirk->state; | |
506 | ||
507 | quirk->state = NONE; | |
508 | ||
509 | if (old_state == SELECT) { | |
510 | quirk->offset = (uint32_t)data; | |
511 | quirk->state = WINDOW; | |
512 | trace_vfio_quirk_nvidia_3d0_state(vdev->vbasedev.name, | |
513 | nv3d0_states[quirk->state]); | |
514 | } else if (old_state == WRITE) { | |
515 | if ((quirk->offset & ~(PCI_CONFIG_SPACE_SIZE - 1)) == 0x1800) { | |
516 | uint8_t offset = quirk->offset & (PCI_CONFIG_SPACE_SIZE - 1); | |
517 | ||
518 | vfio_pci_write_config(&vdev->pdev, offset, data, size); | |
519 | trace_vfio_quirk_nvidia_3d0_write(vdev->vbasedev.name, | |
520 | offset, data, size); | |
c00d61d8 AW |
521 | return; |
522 | } | |
c00d61d8 AW |
523 | } |
524 | ||
525 | vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], | |
6029a424 | 526 | addr + 0x10, data, size); |
c00d61d8 AW |
527 | } |
528 | ||
529 | static const MemoryRegionOps vfio_nvidia_3d0_quirk = { | |
530 | .read = vfio_nvidia_3d0_quirk_read, | |
531 | .write = vfio_nvidia_3d0_quirk_write, | |
532 | .endianness = DEVICE_LITTLE_ENDIAN, | |
533 | }; | |
534 | ||
535 | static void vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice *vdev) | |
536 | { | |
c00d61d8 | 537 | VFIOQuirk *quirk; |
6029a424 | 538 | VFIONvidia3d0Quirk *data; |
c00d61d8 | 539 | |
6029a424 | 540 | if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) || |
c00d61d8 AW |
541 | !vdev->bars[1].region.size) { |
542 | return; | |
543 | } | |
544 | ||
545 | quirk = g_malloc0(sizeof(*quirk)); | |
6029a424 | 546 | quirk->data = data = g_malloc0(sizeof(*data)); |
9d146b2e | 547 | quirk->mem = g_malloc0(sizeof(MemoryRegion) * 2); |
6029a424 AW |
548 | quirk->nr_mem = 2; |
549 | data->vdev = vdev; | |
550 | ||
551 | memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_nvidia_3d4_quirk, | |
552 | data, "vfio-nvidia-3d4-quirk", 2); | |
553 | memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, | |
554 | 0x14 /* 0x3c0 + 0x14 */, &quirk->mem[0]); | |
8c4f2348 | 555 | |
6029a424 AW |
556 | memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_nvidia_3d0_quirk, |
557 | data, "vfio-nvidia-3d0-quirk", 2); | |
c00d61d8 | 558 | memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, |
6029a424 | 559 | 0x10 /* 0x3c0 + 0x10 */, &quirk->mem[1]); |
c00d61d8 AW |
560 | |
561 | QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, | |
562 | quirk, next); | |
563 | ||
6029a424 | 564 | trace_vfio_quirk_nvidia_3d0_probe(vdev->vbasedev.name); |
c00d61d8 AW |
565 | } |
566 | ||
567 | /* | |
568 | * The second quirk is documented in envytools. The I/O port BAR5 is just | |
569 | * a set of address/data ports to the MMIO BARs. The BAR we care about is | |
570 | * again BAR0. This backdoor is apparently a bit newer than the one above | |
571 | * so we need to not only trap 256 bytes @0x1800, but all of PCI config | |
572 | * space, including extended space is available at the 4k @0x88000. | |
573 | */ | |
0e54f24a AW |
574 | typedef struct VFIONvidiaBAR5Quirk { |
575 | uint32_t master; | |
576 | uint32_t enable; | |
577 | MemoryRegion *addr_mem; | |
578 | MemoryRegion *data_mem; | |
579 | bool enabled; | |
580 | VFIOConfigWindowQuirk window; /* last for match data */ | |
581 | } VFIONvidiaBAR5Quirk; | |
582 | ||
583 | static void vfio_nvidia_bar5_enable(VFIONvidiaBAR5Quirk *bar5) | |
584 | { | |
585 | VFIOPCIDevice *vdev = bar5->window.vdev; | |
586 | ||
587 | if (((bar5->master & bar5->enable) & 0x1) == bar5->enabled) { | |
588 | return; | |
589 | } | |
590 | ||
591 | bar5->enabled = !bar5->enabled; | |
592 | trace_vfio_quirk_nvidia_bar5_state(vdev->vbasedev.name, | |
593 | bar5->enabled ? "Enable" : "Disable"); | |
594 | memory_region_set_enabled(bar5->addr_mem, bar5->enabled); | |
595 | memory_region_set_enabled(bar5->data_mem, bar5->enabled); | |
596 | } | |
597 | ||
598 | static uint64_t vfio_nvidia_bar5_quirk_master_read(void *opaque, | |
599 | hwaddr addr, unsigned size) | |
600 | { | |
601 | VFIONvidiaBAR5Quirk *bar5 = opaque; | |
602 | VFIOPCIDevice *vdev = bar5->window.vdev; | |
603 | ||
604 | return vfio_region_read(&vdev->bars[5].region, addr, size); | |
605 | } | |
606 | ||
607 | static void vfio_nvidia_bar5_quirk_master_write(void *opaque, hwaddr addr, | |
608 | uint64_t data, unsigned size) | |
609 | { | |
610 | VFIONvidiaBAR5Quirk *bar5 = opaque; | |
611 | VFIOPCIDevice *vdev = bar5->window.vdev; | |
612 | ||
613 | vfio_region_write(&vdev->bars[5].region, addr, data, size); | |
614 | ||
615 | bar5->master = data; | |
616 | vfio_nvidia_bar5_enable(bar5); | |
617 | } | |
618 | ||
619 | static const MemoryRegionOps vfio_nvidia_bar5_quirk_master = { | |
620 | .read = vfio_nvidia_bar5_quirk_master_read, | |
621 | .write = vfio_nvidia_bar5_quirk_master_write, | |
622 | .endianness = DEVICE_LITTLE_ENDIAN, | |
c00d61d8 AW |
623 | }; |
624 | ||
0e54f24a AW |
625 | static uint64_t vfio_nvidia_bar5_quirk_enable_read(void *opaque, |
626 | hwaddr addr, unsigned size) | |
627 | { | |
628 | VFIONvidiaBAR5Quirk *bar5 = opaque; | |
629 | VFIOPCIDevice *vdev = bar5->window.vdev; | |
630 | ||
631 | return vfio_region_read(&vdev->bars[5].region, addr + 4, size); | |
632 | } | |
633 | ||
634 | static void vfio_nvidia_bar5_quirk_enable_write(void *opaque, hwaddr addr, | |
c00d61d8 AW |
635 | uint64_t data, unsigned size) |
636 | { | |
0e54f24a AW |
637 | VFIONvidiaBAR5Quirk *bar5 = opaque; |
638 | VFIOPCIDevice *vdev = bar5->window.vdev; | |
c00d61d8 | 639 | |
0e54f24a | 640 | vfio_region_write(&vdev->bars[5].region, addr + 4, data, size); |
c00d61d8 | 641 | |
0e54f24a AW |
642 | bar5->enable = data; |
643 | vfio_nvidia_bar5_enable(bar5); | |
c00d61d8 AW |
644 | } |
645 | ||
0e54f24a AW |
646 | static const MemoryRegionOps vfio_nvidia_bar5_quirk_enable = { |
647 | .read = vfio_nvidia_bar5_quirk_enable_read, | |
648 | .write = vfio_nvidia_bar5_quirk_enable_write, | |
c00d61d8 AW |
649 | .endianness = DEVICE_LITTLE_ENDIAN, |
650 | }; | |
651 | ||
0e54f24a | 652 | static void vfio_probe_nvidia_bar5_quirk(VFIOPCIDevice *vdev, int nr) |
c00d61d8 | 653 | { |
c00d61d8 | 654 | VFIOQuirk *quirk; |
0e54f24a AW |
655 | VFIONvidiaBAR5Quirk *bar5; |
656 | VFIOConfigWindowQuirk *window; | |
c00d61d8 | 657 | |
0e54f24a AW |
658 | if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) || |
659 | !vdev->has_vga || nr != 5) { | |
c00d61d8 AW |
660 | return; |
661 | } | |
662 | ||
663 | quirk = g_malloc0(sizeof(*quirk)); | |
9d146b2e | 664 | quirk->mem = g_malloc0(sizeof(MemoryRegion) * 4); |
0e54f24a AW |
665 | quirk->nr_mem = 4; |
666 | bar5 = quirk->data = g_malloc0(sizeof(*bar5) + | |
667 | (sizeof(VFIOConfigWindowMatch) * 2)); | |
668 | window = &bar5->window; | |
669 | ||
670 | window->vdev = vdev; | |
671 | window->address_offset = 0x8; | |
672 | window->data_offset = 0xc; | |
673 | window->nr_matches = 2; | |
674 | window->matches[0].match = 0x1800; | |
675 | window->matches[0].mask = PCI_CONFIG_SPACE_SIZE - 1; | |
676 | window->matches[1].match = 0x88000; | |
677 | window->matches[1].mask = PCIE_CONFIG_SPACE_SIZE - 1; | |
678 | window->bar = nr; | |
679 | window->addr_mem = bar5->addr_mem = &quirk->mem[0]; | |
680 | window->data_mem = bar5->data_mem = &quirk->mem[1]; | |
681 | ||
682 | memory_region_init_io(window->addr_mem, OBJECT(vdev), | |
683 | &vfio_generic_window_address_quirk, window, | |
684 | "vfio-nvidia-bar5-window-address-quirk", 4); | |
685 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, | |
686 | window->address_offset, | |
687 | window->addr_mem, 1); | |
688 | memory_region_set_enabled(window->addr_mem, false); | |
689 | ||
690 | memory_region_init_io(window->data_mem, OBJECT(vdev), | |
691 | &vfio_generic_window_data_quirk, window, | |
692 | "vfio-nvidia-bar5-window-data-quirk", 4); | |
693 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, | |
694 | window->data_offset, | |
695 | window->data_mem, 1); | |
696 | memory_region_set_enabled(window->data_mem, false); | |
697 | ||
698 | memory_region_init_io(&quirk->mem[2], OBJECT(vdev), | |
699 | &vfio_nvidia_bar5_quirk_master, bar5, | |
700 | "vfio-nvidia-bar5-master-quirk", 4); | |
701 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, | |
702 | 0, &quirk->mem[2], 1); | |
8c4f2348 | 703 | |
0e54f24a AW |
704 | memory_region_init_io(&quirk->mem[3], OBJECT(vdev), |
705 | &vfio_nvidia_bar5_quirk_enable, bar5, | |
706 | "vfio-nvidia-bar5-enable-quirk", 4); | |
c00d61d8 | 707 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, |
0e54f24a | 708 | 4, &quirk->mem[3], 1); |
c00d61d8 AW |
709 | |
710 | QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); | |
711 | ||
0e54f24a | 712 | trace_vfio_quirk_nvidia_bar5_probe(vdev->vbasedev.name); |
c00d61d8 AW |
713 | } |
714 | ||
0d38fb1c AW |
715 | /* |
716 | * Finally, BAR0 itself. We want to redirect any accesses to either | |
717 | * 0x1800 or 0x88000 through the PCI config space access functions. | |
718 | */ | |
719 | static void vfio_nvidia_quirk_mirror_write(void *opaque, hwaddr addr, | |
720 | uint64_t data, unsigned size) | |
c00d61d8 | 721 | { |
0d38fb1c AW |
722 | VFIOConfigMirrorQuirk *mirror = opaque; |
723 | VFIOPCIDevice *vdev = mirror->vdev; | |
c00d61d8 | 724 | PCIDevice *pdev = &vdev->pdev; |
c00d61d8 | 725 | |
0d38fb1c | 726 | vfio_generic_quirk_mirror_write(opaque, addr, data, size); |
c00d61d8 AW |
727 | |
728 | /* | |
729 | * Nvidia seems to acknowledge MSI interrupts by writing 0xff to the | |
730 | * MSI capability ID register. Both the ID and next register are | |
731 | * read-only, so we allow writes covering either of those to real hw. | |
c00d61d8 AW |
732 | */ |
733 | if ((pdev->cap_present & QEMU_PCI_CAP_MSI) && | |
734 | vfio_range_contained(addr, size, pdev->msi_cap, PCI_MSI_FLAGS)) { | |
0d38fb1c AW |
735 | vfio_region_write(&vdev->bars[mirror->bar].region, |
736 | addr + mirror->offset, data, size); | |
737 | trace_vfio_quirk_nvidia_bar0_msi_ack(vdev->vbasedev.name); | |
c00d61d8 AW |
738 | } |
739 | } | |
740 | ||
0d38fb1c AW |
741 | static const MemoryRegionOps vfio_nvidia_mirror_quirk = { |
742 | .read = vfio_generic_quirk_mirror_read, | |
743 | .write = vfio_nvidia_quirk_mirror_write, | |
c00d61d8 AW |
744 | .endianness = DEVICE_LITTLE_ENDIAN, |
745 | }; | |
746 | ||
0d38fb1c | 747 | static void vfio_probe_nvidia_bar0_quirk(VFIOPCIDevice *vdev, int nr) |
c00d61d8 | 748 | { |
c00d61d8 | 749 | VFIOQuirk *quirk; |
0d38fb1c | 750 | VFIOConfigMirrorQuirk *mirror; |
c00d61d8 | 751 | |
0d38fb1c AW |
752 | if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) || |
753 | !vfio_is_vga(vdev) || nr != 0) { | |
c00d61d8 AW |
754 | return; |
755 | } | |
756 | ||
757 | quirk = g_malloc0(sizeof(*quirk)); | |
0d38fb1c | 758 | mirror = quirk->data = g_malloc0(sizeof(*mirror)); |
9d146b2e | 759 | mirror->mem = quirk->mem = g_malloc0(sizeof(MemoryRegion)); |
8c4f2348 | 760 | quirk->nr_mem = 1; |
0d38fb1c AW |
761 | mirror->vdev = vdev; |
762 | mirror->offset = 0x88000; | |
763 | mirror->bar = nr; | |
764 | ||
765 | memory_region_init_io(mirror->mem, OBJECT(vdev), | |
766 | &vfio_nvidia_mirror_quirk, mirror, | |
767 | "vfio-nvidia-bar0-88000-mirror-quirk", | |
768 | PCIE_CONFIG_SPACE_SIZE); | |
c00d61d8 | 769 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, |
0d38fb1c | 770 | mirror->offset, mirror->mem, 1); |
c00d61d8 AW |
771 | |
772 | QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); | |
773 | ||
0d38fb1c AW |
774 | /* The 0x1800 offset mirror only seems to get used by legacy VGA */ |
775 | if (vdev->has_vga) { | |
776 | quirk = g_malloc0(sizeof(*quirk)); | |
777 | mirror = quirk->data = g_malloc0(sizeof(*mirror)); | |
9d146b2e | 778 | mirror->mem = quirk->mem = g_malloc0(sizeof(MemoryRegion)); |
0d38fb1c AW |
779 | quirk->nr_mem = 1; |
780 | mirror->vdev = vdev; | |
781 | mirror->offset = 0x1800; | |
782 | mirror->bar = nr; | |
783 | ||
784 | memory_region_init_io(mirror->mem, OBJECT(vdev), | |
785 | &vfio_nvidia_mirror_quirk, mirror, | |
786 | "vfio-nvidia-bar0-1800-mirror-quirk", | |
787 | PCI_CONFIG_SPACE_SIZE); | |
788 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, | |
789 | mirror->offset, mirror->mem, 1); | |
790 | ||
791 | QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); | |
c00d61d8 AW |
792 | } |
793 | ||
0d38fb1c | 794 | trace_vfio_quirk_nvidia_bar0_probe(vdev->vbasedev.name); |
c00d61d8 AW |
795 | } |
796 | ||
797 | /* | |
798 | * TODO - Some Nvidia devices provide config access to their companion HDA | |
799 | * device and even to their parent bridge via these config space mirrors. | |
800 | * Add quirks for those regions. | |
801 | */ | |
802 | ||
803 | #define PCI_VENDOR_ID_REALTEK 0x10ec | |
804 | ||
805 | /* | |
806 | * RTL8168 devices have a backdoor that can access the MSI-X table. At BAR2 | |
807 | * offset 0x70 there is a dword data register, offset 0x74 is a dword address | |
808 | * register. According to the Linux r8169 driver, the MSI-X table is addressed | |
809 | * when the "type" portion of the address register is set to 0x1. This appears | |
810 | * to be bits 16:30. Bit 31 is both a write indicator and some sort of | |
811 | * "address latched" indicator. Bits 12:15 are a mask field, which we can | |
812 | * ignore because the MSI-X table should always be accessed as a dword (full | |
813 | * mask). Bits 0:11 is offset within the type. | |
814 | * | |
815 | * Example trace: | |
816 | * | |
817 | * Read from MSI-X table offset 0 | |
818 | * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x74, 0x1f000, 4) // store read addr | |
819 | * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x74, 4) = 0x8001f000 // latch | |
820 | * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x70, 4) = 0xfee00398 // read data | |
821 | * | |
822 | * Write 0xfee00000 to MSI-X table offset 0 | |
823 | * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x70, 0xfee00000, 4) // write data | |
824 | * vfio: vfio_bar_write(0000:05:00.0:BAR2+0x74, 0x8001f000, 4) // do write | |
825 | * vfio: vfio_bar_read(0000:05:00.0:BAR2+0x74, 4) = 0x1f000 // complete | |
826 | */ | |
954258a5 AW |
827 | typedef struct VFIOrtl8168Quirk { |
828 | VFIOPCIDevice *vdev; | |
829 | uint32_t addr; | |
830 | uint32_t data; | |
831 | bool enabled; | |
832 | } VFIOrtl8168Quirk; | |
c00d61d8 | 833 | |
954258a5 AW |
834 | static uint64_t vfio_rtl8168_quirk_address_read(void *opaque, |
835 | hwaddr addr, unsigned size) | |
836 | { | |
837 | VFIOrtl8168Quirk *rtl = opaque; | |
838 | VFIOPCIDevice *vdev = rtl->vdev; | |
839 | uint64_t data = vfio_region_read(&vdev->bars[2].region, addr + 0x74, size); | |
c00d61d8 | 840 | |
954258a5 AW |
841 | if (rtl->enabled) { |
842 | data = rtl->addr ^ 0x80000000U; /* latch/complete */ | |
843 | trace_vfio_quirk_rtl8168_fake_latch(vdev->vbasedev.name, data); | |
c00d61d8 AW |
844 | } |
845 | ||
954258a5 | 846 | return data; |
c00d61d8 AW |
847 | } |
848 | ||
954258a5 AW |
849 | static void vfio_rtl8168_quirk_address_write(void *opaque, hwaddr addr, |
850 | uint64_t data, unsigned size) | |
c00d61d8 | 851 | { |
954258a5 AW |
852 | VFIOrtl8168Quirk *rtl = opaque; |
853 | VFIOPCIDevice *vdev = rtl->vdev; | |
c00d61d8 | 854 | |
954258a5 AW |
855 | rtl->enabled = false; |
856 | ||
857 | if ((data & 0x7fff0000) == 0x10000) { /* MSI-X table */ | |
858 | rtl->enabled = true; | |
859 | rtl->addr = (uint32_t)data; | |
860 | ||
861 | if (data & 0x80000000U) { /* Do write */ | |
862 | if (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) { | |
863 | hwaddr offset = data & 0xfff; | |
864 | uint64_t val = rtl->data; | |
865 | ||
866 | trace_vfio_quirk_rtl8168_msix_write(vdev->vbasedev.name, | |
867 | (uint16_t)offset, val); | |
868 | ||
869 | /* Write to the proper guest MSI-X table instead */ | |
870 | memory_region_dispatch_write(&vdev->pdev.msix_table_mmio, | |
871 | offset, val, size, | |
872 | MEMTXATTRS_UNSPECIFIED); | |
c00d61d8 | 873 | } |
954258a5 | 874 | return; /* Do not write guest MSI-X data to hardware */ |
c00d61d8 | 875 | } |
c00d61d8 AW |
876 | } |
877 | ||
954258a5 | 878 | vfio_region_write(&vdev->bars[2].region, addr + 0x74, data, size); |
c00d61d8 AW |
879 | } |
880 | ||
954258a5 AW |
881 | static const MemoryRegionOps vfio_rtl_address_quirk = { |
882 | .read = vfio_rtl8168_quirk_address_read, | |
883 | .write = vfio_rtl8168_quirk_address_write, | |
c00d61d8 AW |
884 | .valid = { |
885 | .min_access_size = 4, | |
886 | .max_access_size = 4, | |
887 | .unaligned = false, | |
888 | }, | |
889 | .endianness = DEVICE_LITTLE_ENDIAN, | |
890 | }; | |
891 | ||
954258a5 AW |
892 | static uint64_t vfio_rtl8168_quirk_data_read(void *opaque, |
893 | hwaddr addr, unsigned size) | |
894 | { | |
895 | VFIOrtl8168Quirk *rtl = opaque; | |
896 | VFIOPCIDevice *vdev = rtl->vdev; | |
897 | uint64_t data = vfio_region_read(&vdev->bars[2].region, addr + 0x74, size); | |
898 | ||
899 | if (rtl->enabled && (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) { | |
900 | hwaddr offset = rtl->addr & 0xfff; | |
901 | memory_region_dispatch_read(&vdev->pdev.msix_table_mmio, offset, | |
902 | &data, size, MEMTXATTRS_UNSPECIFIED); | |
903 | trace_vfio_quirk_rtl8168_msix_read(vdev->vbasedev.name, offset, data); | |
904 | } | |
905 | ||
906 | return data; | |
907 | } | |
908 | ||
909 | static void vfio_rtl8168_quirk_data_write(void *opaque, hwaddr addr, | |
910 | uint64_t data, unsigned size) | |
911 | { | |
912 | VFIOrtl8168Quirk *rtl = opaque; | |
913 | VFIOPCIDevice *vdev = rtl->vdev; | |
914 | ||
915 | rtl->data = (uint32_t)data; | |
916 | ||
917 | vfio_region_write(&vdev->bars[2].region, addr + 0x70, data, size); | |
918 | } | |
919 | ||
920 | static const MemoryRegionOps vfio_rtl_data_quirk = { | |
921 | .read = vfio_rtl8168_quirk_data_read, | |
922 | .write = vfio_rtl8168_quirk_data_write, | |
923 | .valid = { | |
924 | .min_access_size = 4, | |
925 | .max_access_size = 4, | |
926 | .unaligned = false, | |
927 | }, | |
928 | .endianness = DEVICE_LITTLE_ENDIAN, | |
929 | }; | |
930 | ||
931 | static void vfio_probe_rtl8168_bar2_quirk(VFIOPCIDevice *vdev, int nr) | |
c00d61d8 | 932 | { |
c00d61d8 | 933 | VFIOQuirk *quirk; |
954258a5 | 934 | VFIOrtl8168Quirk *rtl; |
c00d61d8 | 935 | |
954258a5 | 936 | if (!vfio_pci_is(vdev, PCI_VENDOR_ID_REALTEK, 0x8168) || nr != 2) { |
c00d61d8 AW |
937 | return; |
938 | } | |
939 | ||
940 | quirk = g_malloc0(sizeof(*quirk)); | |
9d146b2e | 941 | quirk->mem = g_malloc0(sizeof(MemoryRegion) * 2); |
954258a5 AW |
942 | quirk->nr_mem = 2; |
943 | quirk->data = rtl = g_malloc0(sizeof(*rtl)); | |
944 | rtl->vdev = vdev; | |
945 | ||
946 | memory_region_init_io(&quirk->mem[0], OBJECT(vdev), | |
947 | &vfio_rtl_address_quirk, rtl, | |
948 | "vfio-rtl8168-window-address-quirk", 4); | |
949 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, | |
950 | 0x74, &quirk->mem[0], 1); | |
8c4f2348 | 951 | |
954258a5 AW |
952 | memory_region_init_io(&quirk->mem[1], OBJECT(vdev), |
953 | &vfio_rtl_data_quirk, rtl, | |
954 | "vfio-rtl8168-window-data-quirk", 4); | |
c00d61d8 | 955 | memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, |
954258a5 | 956 | 0x70, &quirk->mem[1], 1); |
c00d61d8 AW |
957 | |
958 | QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); | |
959 | ||
954258a5 | 960 | trace_vfio_quirk_rtl8168_probe(vdev->vbasedev.name); |
c00d61d8 AW |
961 | } |
962 | ||
963 | /* | |
964 | * Common quirk probe entry points. | |
965 | */ | |
966 | void vfio_vga_quirk_setup(VFIOPCIDevice *vdev) | |
967 | { | |
968 | vfio_vga_probe_ati_3c3_quirk(vdev); | |
969 | vfio_vga_probe_nvidia_3d0_quirk(vdev); | |
970 | } | |
971 | ||
972 | void vfio_vga_quirk_teardown(VFIOPCIDevice *vdev) | |
973 | { | |
974 | VFIOQuirk *quirk; | |
8c4f2348 | 975 | int i, j; |
c00d61d8 AW |
976 | |
977 | for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) { | |
978 | QLIST_FOREACH(quirk, &vdev->vga.region[i].quirks, next) { | |
8c4f2348 AW |
979 | for (j = 0; j < quirk->nr_mem; j++) { |
980 | memory_region_del_subregion(&vdev->vga.region[i].mem, | |
981 | &quirk->mem[j]); | |
982 | } | |
c00d61d8 AW |
983 | } |
984 | } | |
985 | } | |
986 | ||
987 | void vfio_vga_quirk_free(VFIOPCIDevice *vdev) | |
988 | { | |
8c4f2348 | 989 | int i, j; |
c00d61d8 AW |
990 | |
991 | for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) { | |
992 | while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) { | |
993 | VFIOQuirk *quirk = QLIST_FIRST(&vdev->vga.region[i].quirks); | |
c00d61d8 | 994 | QLIST_REMOVE(quirk, next); |
8c4f2348 AW |
995 | for (j = 0; j < quirk->nr_mem; j++) { |
996 | object_unparent(OBJECT(&quirk->mem[j])); | |
997 | } | |
998 | g_free(quirk->mem); | |
999 | g_free(quirk->data); | |
c00d61d8 AW |
1000 | g_free(quirk); |
1001 | } | |
1002 | } | |
1003 | } | |
1004 | ||
1005 | void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr) | |
1006 | { | |
0e54f24a | 1007 | vfio_probe_ati_bar4_quirk(vdev, nr); |
0d38fb1c | 1008 | vfio_probe_ati_bar2_quirk(vdev, nr); |
0e54f24a | 1009 | vfio_probe_nvidia_bar5_quirk(vdev, nr); |
0d38fb1c | 1010 | vfio_probe_nvidia_bar0_quirk(vdev, nr); |
954258a5 | 1011 | vfio_probe_rtl8168_bar2_quirk(vdev, nr); |
c00d61d8 AW |
1012 | } |
1013 | ||
1014 | void vfio_bar_quirk_teardown(VFIOPCIDevice *vdev, int nr) | |
1015 | { | |
1016 | VFIOBAR *bar = &vdev->bars[nr]; | |
1017 | VFIOQuirk *quirk; | |
8c4f2348 | 1018 | int i; |
c00d61d8 AW |
1019 | |
1020 | QLIST_FOREACH(quirk, &bar->quirks, next) { | |
8c4f2348 AW |
1021 | for (i = 0; i < quirk->nr_mem; i++) { |
1022 | memory_region_del_subregion(&bar->region.mem, &quirk->mem[i]); | |
1023 | } | |
c00d61d8 AW |
1024 | } |
1025 | } | |
1026 | ||
1027 | void vfio_bar_quirk_free(VFIOPCIDevice *vdev, int nr) | |
1028 | { | |
1029 | VFIOBAR *bar = &vdev->bars[nr]; | |
8c4f2348 | 1030 | int i; |
c00d61d8 AW |
1031 | |
1032 | while (!QLIST_EMPTY(&bar->quirks)) { | |
1033 | VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks); | |
c00d61d8 | 1034 | QLIST_REMOVE(quirk, next); |
8c4f2348 AW |
1035 | for (i = 0; i < quirk->nr_mem; i++) { |
1036 | object_unparent(OBJECT(&quirk->mem[i])); | |
1037 | } | |
1038 | g_free(quirk->mem); | |
1039 | g_free(quirk->data); | |
c00d61d8 AW |
1040 | g_free(quirk); |
1041 | } | |
1042 | } | |
c9c50009 AW |
1043 | |
1044 | /* | |
1045 | * Reset quirks | |
1046 | */ | |
1047 | ||
1048 | /* | |
1049 | * AMD Radeon PCI config reset, based on Linux: | |
1050 | * drivers/gpu/drm/radeon/ci_smc.c:ci_is_smc_running() | |
1051 | * drivers/gpu/drm/radeon/radeon_device.c:radeon_pci_config_reset | |
1052 | * drivers/gpu/drm/radeon/ci_smc.c:ci_reset_smc() | |
1053 | * drivers/gpu/drm/radeon/ci_smc.c:ci_stop_smc_clock() | |
1054 | * IDs: include/drm/drm_pciids.h | |
1055 | * Registers: http://cgit.freedesktop.org/~agd5f/linux/commit/?id=4e2aa447f6f0 | |
1056 | * | |
1057 | * Bonaire and Hawaii GPUs do not respond to a bus reset. This is a bug in the | |
1058 | * hardware that should be fixed on future ASICs. The symptom of this is that | |
1059 | * once the accerlated driver loads, Windows guests will bsod on subsequent | |
1060 | * attmpts to load the driver, such as after VM reset or shutdown/restart. To | |
1061 | * work around this, we do an AMD specific PCI config reset, followed by an SMC | |
1062 | * reset. The PCI config reset only works if SMC firmware is running, so we | |
1063 | * have a dependency on the state of the device as to whether this reset will | |
1064 | * be effective. There are still cases where we won't be able to kick the | |
1065 | * device into working, but this greatly improves the usability overall. The | |
1066 | * config reset magic is relatively common on AMD GPUs, but the setup and SMC | |
1067 | * poking is largely ASIC specific. | |
1068 | */ | |
1069 | static bool vfio_radeon_smc_is_running(VFIOPCIDevice *vdev) | |
1070 | { | |
1071 | uint32_t clk, pc_c; | |
1072 | ||
1073 | /* | |
1074 | * Registers 200h and 204h are index and data registers for accessing | |
1075 | * indirect configuration registers within the device. | |
1076 | */ | |
1077 | vfio_region_write(&vdev->bars[5].region, 0x200, 0x80000004, 4); | |
1078 | clk = vfio_region_read(&vdev->bars[5].region, 0x204, 4); | |
1079 | vfio_region_write(&vdev->bars[5].region, 0x200, 0x80000370, 4); | |
1080 | pc_c = vfio_region_read(&vdev->bars[5].region, 0x204, 4); | |
1081 | ||
1082 | return (!(clk & 1) && (0x20100 <= pc_c)); | |
1083 | } | |
1084 | ||
1085 | /* | |
1086 | * The scope of a config reset is controlled by a mode bit in the misc register | |
1087 | * and a fuse, exposed as a bit in another register. The fuse is the default | |
1088 | * (0 = GFX, 1 = whole GPU), the misc bit is a toggle, with the forumula | |
1089 | * scope = !(misc ^ fuse), where the resulting scope is defined the same as | |
1090 | * the fuse. A truth table therefore tells us that if misc == fuse, we need | |
1091 | * to flip the value of the bit in the misc register. | |
1092 | */ | |
1093 | static void vfio_radeon_set_gfx_only_reset(VFIOPCIDevice *vdev) | |
1094 | { | |
1095 | uint32_t misc, fuse; | |
1096 | bool a, b; | |
1097 | ||
1098 | vfio_region_write(&vdev->bars[5].region, 0x200, 0xc00c0000, 4); | |
1099 | fuse = vfio_region_read(&vdev->bars[5].region, 0x204, 4); | |
1100 | b = fuse & 64; | |
1101 | ||
1102 | vfio_region_write(&vdev->bars[5].region, 0x200, 0xc0000010, 4); | |
1103 | misc = vfio_region_read(&vdev->bars[5].region, 0x204, 4); | |
1104 | a = misc & 2; | |
1105 | ||
1106 | if (a == b) { | |
1107 | vfio_region_write(&vdev->bars[5].region, 0x204, misc ^ 2, 4); | |
1108 | vfio_region_read(&vdev->bars[5].region, 0x204, 4); /* flush */ | |
1109 | } | |
1110 | } | |
1111 | ||
1112 | static int vfio_radeon_reset(VFIOPCIDevice *vdev) | |
1113 | { | |
1114 | PCIDevice *pdev = &vdev->pdev; | |
1115 | int i, ret = 0; | |
1116 | uint32_t data; | |
1117 | ||
1118 | /* Defer to a kernel implemented reset */ | |
1119 | if (vdev->vbasedev.reset_works) { | |
1120 | trace_vfio_quirk_ati_bonaire_reset_skipped(vdev->vbasedev.name); | |
1121 | return -ENODEV; | |
1122 | } | |
1123 | ||
1124 | /* Enable only memory BAR access */ | |
1125 | vfio_pci_write_config(pdev, PCI_COMMAND, PCI_COMMAND_MEMORY, 2); | |
1126 | ||
1127 | /* Reset only works if SMC firmware is loaded and running */ | |
1128 | if (!vfio_radeon_smc_is_running(vdev)) { | |
1129 | ret = -EINVAL; | |
1130 | trace_vfio_quirk_ati_bonaire_reset_no_smc(vdev->vbasedev.name); | |
1131 | goto out; | |
1132 | } | |
1133 | ||
1134 | /* Make sure only the GFX function is reset */ | |
1135 | vfio_radeon_set_gfx_only_reset(vdev); | |
1136 | ||
1137 | /* AMD PCI config reset */ | |
1138 | vfio_pci_write_config(pdev, 0x7c, 0x39d5e86b, 4); | |
1139 | usleep(100); | |
1140 | ||
1141 | /* Read back the memory size to make sure we're out of reset */ | |
1142 | for (i = 0; i < 100000; i++) { | |
1143 | if (vfio_region_read(&vdev->bars[5].region, 0x5428, 4) != 0xffffffff) { | |
1144 | goto reset_smc; | |
1145 | } | |
1146 | usleep(1); | |
1147 | } | |
1148 | ||
1149 | trace_vfio_quirk_ati_bonaire_reset_timeout(vdev->vbasedev.name); | |
1150 | ||
1151 | reset_smc: | |
1152 | /* Reset SMC */ | |
1153 | vfio_region_write(&vdev->bars[5].region, 0x200, 0x80000000, 4); | |
1154 | data = vfio_region_read(&vdev->bars[5].region, 0x204, 4); | |
1155 | data |= 1; | |
1156 | vfio_region_write(&vdev->bars[5].region, 0x204, data, 4); | |
1157 | ||
1158 | /* Disable SMC clock */ | |
1159 | vfio_region_write(&vdev->bars[5].region, 0x200, 0x80000004, 4); | |
1160 | data = vfio_region_read(&vdev->bars[5].region, 0x204, 4); | |
1161 | data |= 1; | |
1162 | vfio_region_write(&vdev->bars[5].region, 0x204, data, 4); | |
1163 | ||
1164 | trace_vfio_quirk_ati_bonaire_reset_done(vdev->vbasedev.name); | |
1165 | ||
1166 | out: | |
1167 | /* Restore PCI command register */ | |
1168 | vfio_pci_write_config(pdev, PCI_COMMAND, 0, 2); | |
1169 | ||
1170 | return ret; | |
1171 | } | |
1172 | ||
1173 | void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev) | |
1174 | { | |
ff635e37 | 1175 | switch (vdev->vendor_id) { |
c9c50009 | 1176 | case 0x1002: |
ff635e37 | 1177 | switch (vdev->device_id) { |
c9c50009 AW |
1178 | /* Bonaire */ |
1179 | case 0x6649: /* Bonaire [FirePro W5100] */ | |
1180 | case 0x6650: | |
1181 | case 0x6651: | |
1182 | case 0x6658: /* Bonaire XTX [Radeon R7 260X] */ | |
1183 | case 0x665c: /* Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] */ | |
1184 | case 0x665d: /* Bonaire [Radeon R7 200 Series] */ | |
1185 | /* Hawaii */ | |
1186 | case 0x67A0: /* Hawaii XT GL [FirePro W9100] */ | |
1187 | case 0x67A1: /* Hawaii PRO GL [FirePro W8100] */ | |
1188 | case 0x67A2: | |
1189 | case 0x67A8: | |
1190 | case 0x67A9: | |
1191 | case 0x67AA: | |
1192 | case 0x67B0: /* Hawaii XT [Radeon R9 290X] */ | |
1193 | case 0x67B1: /* Hawaii PRO [Radeon R9 290] */ | |
1194 | case 0x67B8: | |
1195 | case 0x67B9: | |
1196 | case 0x67BA: | |
1197 | case 0x67BE: | |
1198 | vdev->resetfn = vfio_radeon_reset; | |
1199 | trace_vfio_quirk_ati_bonaire_reset(vdev->vbasedev.name); | |
1200 | break; | |
1201 | } | |
1202 | break; | |
1203 | } | |
1204 | } |