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