1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "qemu/units.h"
15#include "qemu/error-report.h"
16#include "qapi/error.h"
17#include "hw/hw.h"
18#include "hw/nvram/fw_cfg.h"
19#include "pci.h"
20#include "trace.h"
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60static int igd_gen(VFIOPCIDevice *vdev)
61{
62 if ((vdev->device_id & 0xfff) == 0xa84) {
63 return 8;
64 }
65
66 switch (vdev->device_id & 0xff00) {
67
68 case 0x0000:
69 case 0x2500:
70 case 0x2700:
71 case 0x2900:
72 case 0x2a00:
73 case 0x2e00:
74 case 0x3500:
75 case 0xa000:
76 return -1;
77
78 case 0x0100:
79 case 0x0400:
80 case 0x0a00:
81 case 0x0c00:
82 case 0x0d00:
83 case 0x0f00:
84 return 6;
85
86 case 0x1600:
87 case 0x1900:
88 case 0x2200:
89 case 0x5900:
90 return 8;
91 }
92
93 return 8;
94}
95
96typedef struct VFIOIGDQuirk {
97 struct VFIOPCIDevice *vdev;
98 uint32_t index;
99 uint32_t bdsm;
100} VFIOIGDQuirk;
101
102#define IGD_GMCH 0x50
103#define IGD_BDSM 0x5c
104
105
106
107
108
109
110
111
112
113
114typedef struct {
115 uint8_t offset;
116 uint8_t len;
117} IGDHostInfo;
118
119static const IGDHostInfo igd_host_bridge_infos[] = {
120 {PCI_REVISION_ID, 2},
121 {PCI_SUBSYSTEM_VENDOR_ID, 2},
122 {PCI_SUBSYSTEM_ID, 2},
123};
124
125static const IGDHostInfo igd_lpc_bridge_infos[] = {
126 {PCI_VENDOR_ID, 2},
127 {PCI_DEVICE_ID, 2},
128 {PCI_REVISION_ID, 2},
129 {PCI_SUBSYSTEM_VENDOR_ID, 2},
130 {PCI_SUBSYSTEM_ID, 2},
131};
132
133static int vfio_pci_igd_copy(VFIOPCIDevice *vdev, PCIDevice *pdev,
134 struct vfio_region_info *info,
135 const IGDHostInfo *list, int len)
136{
137 int i, ret;
138
139 for (i = 0; i < len; i++) {
140 ret = pread(vdev->vbasedev.fd, pdev->config + list[i].offset,
141 list[i].len, info->offset + list[i].offset);
142 if (ret != list[i].len) {
143 error_report("IGD copy failed: %m");
144 return -errno;
145 }
146 }
147
148 return 0;
149}
150
151
152
153
154static int vfio_pci_igd_host_init(VFIOPCIDevice *vdev,
155 struct vfio_region_info *info)
156{
157 PCIBus *bus;
158 PCIDevice *host_bridge;
159 int ret;
160
161 bus = pci_device_root_bus(&vdev->pdev);
162 host_bridge = pci_find_device(bus, 0, PCI_DEVFN(0, 0));
163
164 if (!host_bridge) {
165 error_report("Can't find host bridge");
166 return -ENODEV;
167 }
168
169 ret = vfio_pci_igd_copy(vdev, host_bridge, info, igd_host_bridge_infos,
170 ARRAY_SIZE(igd_host_bridge_infos));
171 if (!ret) {
172 trace_vfio_pci_igd_host_bridge_enabled(vdev->vbasedev.name);
173 }
174
175 return ret;
176}
177
178
179
180
181
182
183
184static void vfio_pci_igd_lpc_bridge_realize(PCIDevice *pdev, Error **errp)
185{
186 if (pdev->devfn != PCI_DEVFN(0x1f, 0)) {
187 error_setg(errp, "VFIO dummy ISA/LPC bridge must have address 1f.0");
188 }
189}
190
191static void vfio_pci_igd_lpc_bridge_class_init(ObjectClass *klass, void *data)
192{
193 DeviceClass *dc = DEVICE_CLASS(klass);
194 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
195
196 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
197 dc->desc = "VFIO dummy ISA/LPC bridge for IGD assignment";
198 dc->hotpluggable = false;
199 k->realize = vfio_pci_igd_lpc_bridge_realize;
200 k->class_id = PCI_CLASS_BRIDGE_ISA;
201}
202
203static const TypeInfo vfio_pci_igd_lpc_bridge_info = {
204 .name = "vfio-pci-igd-lpc-bridge",
205 .parent = TYPE_PCI_DEVICE,
206 .class_init = vfio_pci_igd_lpc_bridge_class_init,
207 .interfaces = (InterfaceInfo[]) {
208 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
209 { },
210 },
211};
212
213static void vfio_pci_igd_register_types(void)
214{
215 type_register_static(&vfio_pci_igd_lpc_bridge_info);
216}
217
218type_init(vfio_pci_igd_register_types)
219
220static int vfio_pci_igd_lpc_init(VFIOPCIDevice *vdev,
221 struct vfio_region_info *info)
222{
223 PCIDevice *lpc_bridge;
224 int ret;
225
226 lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),
227 0, PCI_DEVFN(0x1f, 0));
228 if (!lpc_bridge) {
229 lpc_bridge = pci_create_simple(pci_device_root_bus(&vdev->pdev),
230 PCI_DEVFN(0x1f, 0), "vfio-pci-igd-lpc-bridge");
231 }
232
233 ret = vfio_pci_igd_copy(vdev, lpc_bridge, info, igd_lpc_bridge_infos,
234 ARRAY_SIZE(igd_lpc_bridge_infos));
235 if (!ret) {
236 trace_vfio_pci_igd_lpc_bridge_enabled(vdev->vbasedev.name);
237 }
238
239 return ret;
240}
241
242
243
244
245
246
247
248
249
250static int vfio_igd_gtt_max(VFIOPCIDevice *vdev)
251{
252 uint32_t gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, sizeof(gmch));
253 int ggms, gen = igd_gen(vdev);
254
255 gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, sizeof(gmch));
256 ggms = (gmch >> (gen < 8 ? 8 : 6)) & 0x3;
257 if (gen > 6) {
258 ggms = 1 << ggms;
259 }
260
261 ggms *= MiB;
262
263 return (ggms / (4 * KiB)) * (gen < 8 ? 4 : 8);
264}
265
266
267
268
269
270
271
272
273
274
275
276
277static uint64_t vfio_igd_quirk_data_read(void *opaque,
278 hwaddr addr, unsigned size)
279{
280 VFIOIGDQuirk *igd = opaque;
281 VFIOPCIDevice *vdev = igd->vdev;
282
283 igd->index = ~0;
284
285 return vfio_region_read(&vdev->bars[4].region, addr + 4, size);
286}
287
288static void vfio_igd_quirk_data_write(void *opaque, hwaddr addr,
289 uint64_t data, unsigned size)
290{
291 VFIOIGDQuirk *igd = opaque;
292 VFIOPCIDevice *vdev = igd->vdev;
293 uint64_t val = data;
294 int gen = igd_gen(vdev);
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 if ((igd->index % 4 == 1) && igd->index < vfio_igd_gtt_max(vdev)) {
311 if (gen < 8 || (igd->index % 8 == 1)) {
312 uint32_t base;
313
314 base = pci_get_long(vdev->pdev.config + IGD_BDSM);
315 if (!base) {
316 hw_error("vfio-igd: Guest attempted to program IGD GTT before "
317 "BIOS reserved stolen memory. Unsupported BIOS?");
318 }
319
320 val = data - igd->bdsm + base;
321 } else {
322 val = 0;
323 }
324
325 trace_vfio_pci_igd_bar4_write(vdev->vbasedev.name,
326 igd->index, data, val);
327 }
328
329 vfio_region_write(&vdev->bars[4].region, addr + 4, val, size);
330
331 igd->index = ~0;
332}
333
334static const MemoryRegionOps vfio_igd_data_quirk = {
335 .read = vfio_igd_quirk_data_read,
336 .write = vfio_igd_quirk_data_write,
337 .endianness = DEVICE_LITTLE_ENDIAN,
338};
339
340static uint64_t vfio_igd_quirk_index_read(void *opaque,
341 hwaddr addr, unsigned size)
342{
343 VFIOIGDQuirk *igd = opaque;
344 VFIOPCIDevice *vdev = igd->vdev;
345
346 igd->index = ~0;
347
348 return vfio_region_read(&vdev->bars[4].region, addr, size);
349}
350
351static void vfio_igd_quirk_index_write(void *opaque, hwaddr addr,
352 uint64_t data, unsigned size)
353{
354 VFIOIGDQuirk *igd = opaque;
355 VFIOPCIDevice *vdev = igd->vdev;
356
357 igd->index = data;
358
359 vfio_region_write(&vdev->bars[4].region, addr, data, size);
360}
361
362static const MemoryRegionOps vfio_igd_index_quirk = {
363 .read = vfio_igd_quirk_index_read,
364 .write = vfio_igd_quirk_index_write,
365 .endianness = DEVICE_LITTLE_ENDIAN,
366};
367
368void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
369{
370 struct vfio_region_info *rom = NULL, *opregion = NULL,
371 *host = NULL, *lpc = NULL;
372 VFIOQuirk *quirk;
373 VFIOIGDQuirk *igd;
374 PCIDevice *lpc_bridge;
375 int i, ret, ggms_mb, gms_mb = 0, gen;
376 uint64_t *bdsm_size;
377 uint32_t gmch;
378 uint16_t cmd_orig, cmd;
379 Error *err = NULL;
380
381
382
383
384
385
386 if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||
387 !vfio_is_vga(vdev) || nr != 4 ||
388 &vdev->pdev != pci_find_device(pci_device_root_bus(&vdev->pdev),
389 0, PCI_DEVFN(0x2, 0))) {
390 return;
391 }
392
393
394
395
396
397
398 lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),
399 0, PCI_DEVFN(0x1f, 0));
400 if (lpc_bridge && !object_dynamic_cast(OBJECT(lpc_bridge),
401 "vfio-pci-igd-lpc-bridge")) {
402 error_report("IGD device %s cannot support legacy mode due to existing "
403 "devices at address 1f.0", vdev->vbasedev.name);
404 return;
405 }
406
407
408
409
410
411
412 gen = igd_gen(vdev);
413 if (gen != 6 && gen != 8) {
414 error_report("IGD device %s is unsupported in legacy mode, "
415 "try SandyBridge or newer", vdev->vbasedev.name);
416 return;
417 }
418
419
420
421
422
423
424 ret = vfio_get_region_info(&vdev->vbasedev,
425 VFIO_PCI_ROM_REGION_INDEX, &rom);
426 if ((ret || !rom->size) && !vdev->pdev.romfile) {
427 error_report("IGD device %s has no ROM, legacy mode disabled",
428 vdev->vbasedev.name);
429 goto out;
430 }
431
432
433
434
435
436 if (vdev->pdev.qdev.hotplugged) {
437 error_report("IGD device %s hotplugged, ROM disabled, "
438 "legacy mode disabled", vdev->vbasedev.name);
439 vdev->rom_read_failed = true;
440 goto out;
441 }
442
443
444
445
446
447 ret = vfio_get_dev_region_info(&vdev->vbasedev,
448 VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
449 VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
450 if (ret) {
451 error_report("IGD device %s does not support OpRegion access,"
452 "legacy mode disabled", vdev->vbasedev.name);
453 goto out;
454 }
455
456 ret = vfio_get_dev_region_info(&vdev->vbasedev,
457 VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
458 VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG, &host);
459 if (ret) {
460 error_report("IGD device %s does not support host bridge access,"
461 "legacy mode disabled", vdev->vbasedev.name);
462 goto out;
463 }
464
465 ret = vfio_get_dev_region_info(&vdev->vbasedev,
466 VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
467 VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG, &lpc);
468 if (ret) {
469 error_report("IGD device %s does not support LPC bridge access,"
470 "legacy mode disabled", vdev->vbasedev.name);
471 goto out;
472 }
473
474 gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, 4);
475
476
477
478
479
480
481 if (!(gmch & 0x2) && !vdev->vga && vfio_populate_vga(vdev, &err)) {
482 error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
483 error_report("IGD device %s failed to enable VGA access, "
484 "legacy mode disabled", vdev->vbasedev.name);
485 goto out;
486 }
487
488
489 ret = vfio_pci_igd_lpc_init(vdev, lpc);
490 if (ret) {
491 error_report("IGD device %s failed to create LPC bridge, "
492 "legacy mode disabled", vdev->vbasedev.name);
493 goto out;
494 }
495
496
497 ret = vfio_pci_igd_host_init(vdev, host);
498 if (ret) {
499 error_report("IGD device %s failed to modify host bridge, "
500 "legacy mode disabled", vdev->vbasedev.name);
501 goto out;
502 }
503
504
505 ret = vfio_pci_igd_opregion_init(vdev, opregion, &err);
506 if (ret) {
507 error_append_hint(&err, "IGD legacy mode disabled\n");
508 error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
509 goto out;
510 }
511
512
513 quirk = vfio_quirk_alloc(2);
514 igd = quirk->data = g_malloc0(sizeof(*igd));
515 igd->vdev = vdev;
516 igd->index = ~0;
517 igd->bdsm = vfio_pci_read_config(&vdev->pdev, IGD_BDSM, 4);
518 igd->bdsm &= ~((1 * MiB) - 1);
519
520 memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_igd_index_quirk,
521 igd, "vfio-igd-index-quirk", 4);
522 memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,
523 0, &quirk->mem[0], 1);
524
525 memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_igd_data_quirk,
526 igd, "vfio-igd-data-quirk", 4);
527 memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,
528 4, &quirk->mem[1], 1);
529
530 QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
531
532
533 ggms_mb = (gmch >> (gen < 8 ? 8 : 6)) & 0x3;
534 if (gen > 6) {
535 ggms_mb = 1 << ggms_mb;
536 }
537
538
539
540
541
542
543
544 gmch &= ~((gen < 8 ? 0x1f : 0xff) << (gen < 8 ? 3 : 8));
545
546 if (vdev->igd_gms) {
547 if (vdev->igd_gms <= 0x10) {
548 gms_mb = vdev->igd_gms * 32;
549 gmch |= vdev->igd_gms << (gen < 8 ? 3 : 8);
550 } else {
551 error_report("Unsupported IGD GMS value 0x%x", vdev->igd_gms);
552 vdev->igd_gms = 0;
553 }
554 }
555
556
557
558
559
560
561
562
563
564 bdsm_size = g_malloc(sizeof(*bdsm_size));
565 *bdsm_size = cpu_to_le64((ggms_mb + gms_mb) * MiB);
566 fw_cfg_add_file(fw_cfg_find(), "etc/igd-bdsm-size",
567 bdsm_size, sizeof(*bdsm_size));
568
569
570 pci_set_long(vdev->pdev.config + IGD_GMCH, gmch);
571 pci_set_long(vdev->pdev.wmask + IGD_GMCH, 0);
572 pci_set_long(vdev->emulated_config_bits + IGD_GMCH, ~0);
573
574
575 pci_set_long(vdev->pdev.config + IGD_BDSM, 0);
576 pci_set_long(vdev->pdev.wmask + IGD_BDSM, ~0);
577 pci_set_long(vdev->emulated_config_bits + IGD_BDSM, ~0);
578
579
580
581
582
583
584
585 if (pread(vdev->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),
586 vdev->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {
587 error_report("IGD device %s - failed to read PCI command register",
588 vdev->vbasedev.name);
589 }
590
591 cmd = cmd_orig | PCI_COMMAND_IO;
592
593 if (pwrite(vdev->vbasedev.fd, &cmd, sizeof(cmd),
594 vdev->config_offset + PCI_COMMAND) != sizeof(cmd)) {
595 error_report("IGD device %s - failed to write PCI command register",
596 vdev->vbasedev.name);
597 }
598
599 for (i = 1; i < vfio_igd_gtt_max(vdev); i += 4) {
600 vfio_region_write(&vdev->bars[4].region, 0, i, 4);
601 vfio_region_write(&vdev->bars[4].region, 4, 0, 4);
602 }
603
604 if (pwrite(vdev->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),
605 vdev->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {
606 error_report("IGD device %s - failed to restore PCI command register",
607 vdev->vbasedev.name);
608 }
609
610 trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, ggms_mb + gms_mb);
611
612out:
613 g_free(rom);
614 g_free(opregion);
615 g_free(host);
616 g_free(lpc);
617}
618