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