Tutorial on how to use GVT-G to share an Intel iGPU with a Windows VM

I wrote a rather large tutorial on my blog on how to setup GVT-G to share an Intel iGPU with a Windows guest. The performance gets very close to native, it’s a nice solution when all you have is a laptop and you don’t have the hardware for VFIO.

The link is here: https://blog.tmm.cx/2020/05/15/passing-an-intel-gpu-to-a-linux-kvm-virtual-machine/

I figured it’d be useful to share it with the people here as well. I hope it’s useful!

5 Likes

Nice tutorial, I’ll try it out myself in ma moment as I wanted to play some windows-only games recently.

However I’d like to give you some feedback about the font size, please make the “code font” and normal one more close to each other in size… also the site looks better when it’s on 90% its original size (15" 1080p no scaling)

Do you mean the container should be less wide? I’ll fix the font! Thanks.

Thank you for this nicely done tutorial. I tried it once before and it is such an awesome technology! That’s what I’m going to use for work when I get my new notebook. I can finally ditch Windows for good and don’t have to dual boot occasionally and/or rely on RDP-/Citrix-Sessions.

1 Like

I made some changes to the layout, let me know what you think!

1 Like

The code font now seems to match the text one, I’m sure I wouldn’t say anything if it was like this since the beginning, but I’m not a professional designer or anything so keep that in mind :stuck_out_tongue:

Sorry I didn’t respond sooner about the container width.
I meant that if I zoom out the page just “feels better”, there is just more text on the page, however I don’t think you changed the width, did you? I can’t really tell, seems like that zooming out might have been a placebo effect or something,

1 Like

I’m trying to install windows with this config right now… as far as I can tell this line:

<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>

from your config is not needed, however I’ll be back to report if that’s actually the case.

EDIT: The vm is still trying to boot, but I looked at the XML and I have this line, so either virt-manager added it on its own or I copied it and forgot that its actually there.

Right now I’m waiting for the VM to start… which is very very very slow. I think I should have installed and configured windows before editing the xml to add the vgpu…

EDIT: I think the VM just bluescreened without showing me the bluescreen, it just restarted into some recorvery (I’m not familiar with windows) screen…
P.S the recovery screen works in like 0.5 fps


Update:
The VM image works fine when its booted with different xml, the vgpu one just crashes…
If anyone is willing to help me a little bit, here is my xml:

<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0" type="kvm">
  <name>windows_gpu</name>
  <uuid>2944e35d-5e2c-4412-b622-40f1c164e5e9</uuid>
  <metadata>
    <libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
      <libosinfo:os id="http://microsoft.com/win/10"/>
    </libosinfo:libosinfo>
  </metadata>
  <memory unit="KiB">8388608</memory>
  <currentMemory unit="KiB">8388608</currentMemory>
  <vcpu placement="static">4</vcpu>
  <os>
    <type arch="x86_64" machine="pc-q35-5.0">hvm</type>
    <bootmenu enable="yes"/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <hyperv>
      <relaxed state="on"/>
      <vapic state="on"/>
      <spinlocks state="on" retries="8191"/>
    </hyperv>
    <vmport state="off"/>
  </features>
  <cpu mode="host-passthrough" check="partial">
    <topology sockets="1" dies="1" cores="2" threads="2"/>
  </cpu>
  <clock offset="localtime">
    <timer name="rtc" tickpolicy="catchup"/>
    <timer name="pit" tickpolicy="delay"/>
    <timer name="hpet" present="no"/>
    <timer name="hypervclock" present="yes"/>
  </clock>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <pm>
    <suspend-to-mem enabled="no"/>
    <suspend-to-disk enabled="no"/>
  </pm>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/var/lib/libvirt/images/windows_gpu.qcow2"/>
      <target dev="vda" bus="virtio"/>
      <boot order="1"/>
      <address type="pci" domain="0x0000" bus="0x04" slot="0x00" function="0x0"/>
    </disk>
    <disk type="file" device="cdrom">
      <driver name="qemu" type="raw"/>
      <source file="/home/larry/ISO/Win10_1909_English_x64.iso"/>
      <target dev="sdb" bus="sata"/>
      <readonly/>
      <boot order="3"/>
      <address type="drive" controller="0" bus="0" target="0" unit="1"/>
    </disk>
    <disk type="file" device="cdrom">
      <driver name="qemu" type="raw"/>
      <source file="/home/larry/ISO/virtio-win-0.1.171.iso"/>
      <target dev="sdc" bus="sata"/>
      <readonly/>
      <boot order="2"/>
      <address type="drive" controller="0" bus="0" target="0" unit="2"/>
    </disk>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/var/lib/libvirt/images/windows_intel_driver.qcow2"/>
      <target dev="sdd" bus="sata"/>
      <address type="drive" controller="0" bus="0" target="0" unit="3"/>
    </disk>
    <controller type="usb" index="0" model="qemu-xhci" ports="15">
      <address type="pci" domain="0x0000" bus="0x02" slot="0x00" function="0x0"/>
    </controller>
    <controller type="sata" index="0">
      <address type="pci" domain="0x0000" bus="0x00" slot="0x1f" function="0x2"/>
    </controller>
    <controller type="pci" index="0" model="pcie-root"/>
    <controller type="pci" index="1" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="1" port="0x10"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0" multifunction="on"/>
    </controller>
    <controller type="pci" index="2" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="2" port="0x11"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x1"/>
    </controller>
    <controller type="pci" index="3" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="3" port="0x12"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/>
    </controller>
    <controller type="pci" index="4" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="4" port="0x13"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/>
    </controller>
    <controller type="pci" index="5" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="5" port="0x14"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/>
    </controller>
    <controller type="pci" index="6" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="6" port="0x15"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/>
    </controller>
    <controller type="virtio-serial" index="0">
      <address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/>
    </controller>
    <interface type="network">
      <mac address="52:54:00:e3:74:2d"/>
      <source network="default"/>
      <model type="e1000e"/>
      <link state="down"/>
      <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
    </interface>
    <serial type="pty">
      <target type="isa-serial" port="0">
        <model name="isa-serial"/>
      </target>
    </serial>
    <console type="pty">
      <target type="serial" port="0"/>
    </console>
    <channel type="spicevmc">
      <target type="virtio" name="com.redhat.spice.0"/>
      <address type="virtio-serial" controller="0" bus="0" port="1"/>
    </channel>
    <input type="tablet" bus="usb">
      <address type="usb" bus="0" port="1"/>
    </input>
    <input type="mouse" bus="ps2"/>
    <input type="keyboard" bus="ps2"/>
    <graphics type="spice">
      <listen type="none"/>
      <gl enable="yes" rendernode="/dev/dri/by-path/pci-0000:00:02.0-render"/>
    </graphics>
    <sound model="ich9">
      <address type="pci" domain="0x0000" bus="0x00" slot="0x1b" function="0x0"/>
    </sound>
    <video>
      <model type="none"/>
    </video>
    <hostdev mode="subsystem" type="mdev" managed="no" model="vfio-pci" display="on">
      <source>
        <address uuid="bfb85f4a-589e-4a5e-9524-283a2d618b40"/>
      </source>
      <address type="pci" domain="0x0000" bus="0x06" slot="0x00" function="0x0"/>
    </hostdev>
    <redirdev bus="usb" type="spicevmc">
      <address type="usb" bus="0" port="2"/>
    </redirdev>
    <redirdev bus="usb" type="spicevmc">
      <address type="usb" bus="0" port="3"/>
    </redirdev>
    <memballoon model="virtio">
      <address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
    </memballoon>
  </devices>
  <qemu:commandline>
    <qemu:arg value="-set"/>
    <qemu:arg value="device.hostdev0.x-igd-opregion=on"/>
    <qemu:arg value="-set"/>
    <qemu:arg value="device.hostdev0.ramfb=on"/>
    <qemu:arg value="-set"/>
    <qemu:arg value="device.hostdev0.driver=vfio-pci-nohotplug"/>
    <qemu:env name="INTEL_DEBUG" value="norbc"/>
  </qemu:commandline>
</domain>

The only drivers installed on the vm are virt-io drivers and that spice agent linked in the tutorial. I haven’t got to the point when I could install intel drivers.

It seems that you’re not trying to use the virtio devices for storage and networking. So it appears you’re not following the tutorial exactly.

The first time after adding the mdev and removing the regular virtual gpu it is expected that the vm is very slow. I believe I make a note about that in the text.

I’d suggest starting over with the tutorial and making sure you actually follow all the steps and making sure that your VM has internet connectivity. If it doesn’t the Intel drivers from windows update don’t get installed and the vm will never work properly also.

Wait a second, since when windows downloads gpu drivers from a vendor on its own?

Windows 7 I think?

I have followed the tutorial completely on fedora 37, however when I go to add the mdev device and the qemu:arg xml everything goes smoothly until I try to start the VM again at which time I receive and error:
Error starting domain: internal error: process exited while connecting to monitor: qemu-system-x86_64: -set device.hostdev0.x-igd-opregion=on: there is no device “hostdev0” defined

I have tried to define my own alias for the mdev device (ua-hostdev0) and then updating the qemu:args tags, but other the error looks like this then:
Error starting domain: internal error: process exited while connecting to monitor: qemu-system-x86_64: -set device.ua-hostdev0.x-igd-opregion=on: there is no device “ua-hostdev0” defined