The Pragmatic Neckbeard 4: KVM and libvirt

Intro

In this installation, it’s all QEMU, libvirt and KVM. It’s been a long wait and I really do hope it’s been worth it. This is the part where I’m actually going to guide you through working with libvirt, using virt-manager for most of our work. This can be done by anyone because it’s so simple.

Software requirements

Before we get into the conceptual discussion, I’m going to be outlining a bit of the software that we’re going to need to follow this guide.

  • libvirt and virt-manager (usually found as libvirt and virt-manager in your package manager)
  • QEMU (usually found as qemu in your package manager)
  • fedora-packaged virtio drivers, an ISO which is obtainable at this link. I normally download the latest variant, because I’ve had better results, but you should be okay with either.
  • OVMF, this is your UEFI firmware that the VM is going to run. Some distributions have it as a package, search your package manager for ovmf or edk2 to see if you have it. If not, you’re going to have to extract an RPM for it. The binary files don’t require any libraries, as they’re firmware.

Moving on, you’re going to need to do some configuration so that libvirt can find the OVMF images that we installed. This will be discussed in a later section.

Conceptual Discussion

Alright, this one’s going to be a lot shorter than the previous since there’s not quite as much to cover here. The tricky part is the implementation.

First up is KVM, the Kernel-based Virtual Machine. It’s feature of the Linux kernel that allows you to get near-native performance on same-architecture virtualization. Your hardware must have virtualization extensions (Intel VT or AMD-V) to take full advantage of KVM. That said, you can’t use KVM directly. KVM is more of an ABI (application binary interface) that exposes system calls than a user-executable program.

That’s where QEMU (Quick Emulator) comes in. QEMU is software that emulates CPU’s by translating binary instructions and extends the KVM ABI. QEMU will allow you to emulate a number of different CPU’s, be it of the same or a different architecture. QEMU also allows you to emulate a large number of different devices from disks (HDD, floppy and cdrom drives), NICs, displays and HID (human interface devices, IE: keyboard and mouse) to PCI hubs and TPM devices. QEMU is also capable of redirecting the host machine’s USB devices and PCI devices that have not already been initialized or claimed by a driver.

Now that we’ve got an understanding of the underlying technology, we need something to manage it. That’s where libvirt comes to the rescue. libvirt is software that maintains configuration and manages VM states. Paired with virt-manager as a GUI front-end, you can easily provision and maintain virtual machines on your system. libvirt uses XML to store VM configuration. This makes the config easy to modify outside the front-end, which we may have to do at some point.

Windows 10, UEFI and your GPU in a VM.

It’s time. You’ve quite possibly been waiting upwards of 3 months for this series to get to this point. It’s time to guide you through making a Windows 10 VM with UEFI and stick a GPU in it so we can play windows games on Linux. First thing’s first. I’m going to be assuming you’ve got the Windows 10 ISO and a valid license. (I know, I know)

Before we start our services, we’ve got to make sure that libvirt is configured properly. First thing’s first, we need to make sure that libvirt knows where to find the OVMF files. You’ll need to edit /etc/libvirt/qemu.conf as root and append the following:

nvram = [
    "/usr/share/ovmf/ovmf-x86_64.bin:/usr/share/ovmf/ovmf-x86_64-vars.bin"
]

If your OVMF binaries are in a different location, go ahead and adjust accordingly. Once you’ve got that completed, we’re going to go ahead and make sure that libvirt is enabled by executing systemctl status libvirtd. You’ll get output similar to this:

libvirtd.service - Virtualization daemon
   Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2017-01-16 05:19:13 PST; 7h ago
     Docs: man:libvirtd(8)
           http://libvirt.org
 Main PID: 1635 (libvirtd)
    Tasks: 18 (limit: 512)
   CGroup: /system.slice/libvirtd.service
           ├─1635 /usr/sbin/libvirtd --listen
           ├─1899 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/defa...
           └─1900 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/defa...

It’s showing me that it’s running and has been enabled to start on boot (under the Loaded: … section, it says enabled;)

If your output says disabled;, you’ll need to enable it with:

systemctl enable libvirtd

This will allow libvirt to start on boot. We still need to manually start it this time though, so you’ll need to run, as root:

systemctl start libvirtd

Now that we’ve started libvirt, we can load up virt-manager and start configuring our VM.

Before we do that, however, I’d like to stop and take a quick look at a few different storage options. I’m currently using pure SSD storage for my VM’s, but you may want to choose a mix of SSD and HDD for yours. Also, be sure that you’re not using BTrFS to host your VM image, or if you must, disable copy-on-write with chattr +C on the directory you’re storing the image in. I’m going to use the default directory (/var/lib/libvirt/images) for my VM’s C:/ Drive, with a raw storage format. raw disks will give us the best performance. I’m going to be assuming you’ve got a windows 10 ISO downloaded and have access to it.

Now that we’ve got our storage more or less figured out, we can go through the VM creation process. Go ahead and set up your VM as you’d like but be sure that before you click “finish” you check the box for “Customize configuration before install”. This will allow us to get the VM set up exactly as we need it. You should now have a window with a large number of options listed down the left side.

Configuring the VM’s hardware

The first thing we need to do is change the firmware and chipset. We want to select UEFI for the firmware and Q35 for the chipset. You can safely ignore the warning that Q35 is less tested. I’ve never seen a hardware configuration where Q35 needs to be disabled, however, if you find this to be the case, please let me know so I can update this guide accordingly.

Once that’s done, let’s move on to the CPU configuration. We want to check the box about halfway down the window where it says “copy host CPU configuration” and set the topology to something logical for your CPU. I’ve got a quad-core with hyper threading, so I’m going to use 1 socket, 4 cores and 1 thread.

Moving on to memory, go ahead and set it to 8192MB (8GB). You can do what you want here, but I’ve found that my system runs best with 8GB of ram allocated to it.

Now let’s configure our disks. Under advanced options for each disk, we need to change HDD 1 to virtio and change the CDROM to sata. From there, we also want to add a secondary CDROM device and mount the virtio driver CD (obtainable here) there. Again, set this device to use the sata bus. We also want to use unsafe caching and threads for the IO mode.

Leaving the virtual network device set to NAT will be the best configuration for most cases. What we want to do, though, is change the device model to virtio, as with the disks above.

Now we’ve got a bunch of superfluous devices that can be removed. Remove the following devices:

  • Mouse
  • Display Spice
  • Console
  • Channel Spice
  • Video QXL

Next step is to configure the Controller USB to work in USB 3 mode. From there, make sure you’ve got a RNG device at the bottom and continue to the next step. If you don’t, you’ll need to add a RNG attached to /dev/random via the Add Hardware button.

Adding the GPU

Before we take another step forward, it’s important to mention that if you have an AMD GPU, you’ll potentially run into PCIe Bus reset errors, which means you’ll have to cold boot the Linux host every time you want to reboot the VM. This issue won’t cause any damage to your system, but it’s a hardware flaw, so there is no software workaround. To the best of my knowledge, the RX 4xx series is not affected by it and from personal experience, the R9 380 and Fury line of cards suffer this issue.

Now, AMD is easiest to work with on the software side of things because AMD doesn’t purposely kill the drivers if it detects it’s in a VM. This means you don’t have to do any trickery to get the GPU to work properly, and in fact, you’ll probably have better performance with an AMD GPU than an Nvidia.

Time to add the GPU. Go into Add Hardware and choose PCI Host Device from the left side menu, find the PCI address of your device, usually something like 0000:01:00.0 or the like and add it. You’ll need to add both the GPU and the HDMI audio device or you won’t be able to get the drivers to work. The HDMI audio will almost always be attached at .1 on the same lane. So if you’ve got your GPU at 0000:01:00.0, your HDMI audio will be at 0000:01:00.1. Always add the GPU first, then the HDMI audio second. That way, the devices get addressed properly.

Starting the VM

This is it, the moment we’ve all been waiting for. The fifth symphony, The force awakens. Make sure you’ve got a monitor connected to the GPU you’re passing through and click Begin Installation. If you’ve got an Nvidia GPU, stop the VM after you’ve verified that there’s output on the screen. AMD users can continue with the installation below at the “Installing Windows 10” section.

Hiding KVM from Nvidia

Nvidia took the high-ground in trying to sell quadro cards to consumers by not allowing their GTX series GPUs to work if the driver has detected KVM or Hyper-V extensions. How can we solve this heinous act of terror, you ask? We’re just going to disable and hide the KVM and Hyper-V extensions. Unfortunately, this means that the VM will have slightly lower performance, but the difference in performance is about 1%. If you’re that concerned about 1%, consider Vega.

Now, on to solving the problem.

We need to open up the config file for the VM, so exit out of all the virt-manager windows, open up your terminal and execute sudo virsh edit win10, replacing win10 with your VM name. Next, go down to the very bottom of the file, you’ll see </domain>. Just above that line, insert the following:

<qemu:commandline>
<qemu:arg value='-cpu'/>
<qemu:arg value='host,hv_time,kvm=off,hv_vendor_id=null'/>
</qemu:commandline>

This directly appends CPU configuration to the QEMU command that virt-manager executes. On the third line, the host argument is telling QEMU to emulate the host cpu, so if you’ve got a skylake processor, the VM will see the CPU as skylake. The hv_time argument is a paravirtualized real time clock that can be used to help sync the VM’s time with the host. The kvm=off argument is telling QEMU to disable KVM extensions for this VM. This is where you see a bit of performance dip, but it’s not huge and will allow your GPU to work. The hv_vendor_id=null argument is hiding hyperv extensions from the VM since this is one of the features that the Nvidia drivers look for.

Save and quit the editor, then go ahead and load up virt-manager again and move on to the Windows installation process below.

A note on input devices

libvirt allows you to hot-plug USB devices to the VM. By default, you are allotted two, but you can add additional slots by adding another USB Redirector and restarting the VM. If you want to plug in a USB device, click the Add Hardware button and select USB Host Device, which is just above the PCI Host Device option that was used to install the GPU. My recommendation is to have a secondary keyboard and mouse for your VM while we go through the installation process. This will make it easier to work with your host system during the install process. Of course, this can be done with only one keyboard and mouse, but you’ll need to shut down the VM in order to restore control over the host system.

Installing Windows 10

Now, how about we get windows installed? The windows install process is going to be pretty normal, except for the part where we configure the storage. Windows doesn’t carry drivers for the virtio storage devices by default, so you’re going to have to install them from the ISO that we mounted earlier. When you get to the unsettlingly empty disk selection screen, choose Load Driver from the bottom of the window, where you can find viostor and choose the proper directory for your Operating System. Click through the rest of the process and you’ll find yourself back at the disk selection menu with a shiny new virtio disk showing up empty. Continue on with the install process and we’ll rejoin when the VM is at the desktop.

Installing additional drivers

Now that you’ve got windows installed, you’ll notice that you’ve got no network devices. This is, again, due to the fact that we chose virtio for the network device type and Windows doesn’t carry drivers for this device. We can right click the start menu button, choose Device Manager and find the devices that windows couldn’t assign a driver to in the menu. From there, right click it, install a driver, tell the system to look locally, browse to your CD drive with the drivers, choose the root of the CDROM, click OK, check the box to search recursively within the CD and you’re off to the races. Repeat this process for all the other devices that are unknown except your GPU.

Once you’ve installed drivers for all the KVM machines, you’ll need to install your GPU drivers, so navigate to your respective vendor, download their driver package and install it. AMD users please note that I’ve heard reports of the ReLive drivers having issues in VMs, so if you encounter problems, try the Crimson drivers for the time being. I don’t imagine this problem lasting too long. Once your drivers are installed, go ahead and reboot your VM and we’re done with the install.

QEMU Audio

Passing audio from the VM to Linux is a pain in the ass. I can’t guarantee it will work for you, but I’m happy to give you the methods that have worked for me.

Before we go into the instructions, OpenSUSE just works. If you’re not married to a distro, give it a try, it’s quite nice.

Only follow the steps below if you’re having issues with passing audio through.

Libvirt, by default, only allows you to pass audio if you’ve got a virtual display on the VM. Remember how we removed Display Spice? That also removed our ability (in the default state) to have audio. So, to fix that, we need to go into /etc/libvirt/qemu.conf and append the following:

nographics_allow_host_audio = 1

This will give us the ability to have audio in many instances.

The next problem is only for Pulse users. Pulseaudio doesn’t normally allow audio streams from any services. Normally it only allows connections from the current user, which is a problem, since libvirt and QEMU need to run as root. We solve this by editing two files. The first is /etc/pulse/default.pa. Append the following to it:

load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1

The second file is /etc/pulse/client.conf and we’re appending this:

default-server = 127.0.0.1

Now, reboot your host machine and give it a go. If you’re still encountering issues with audio after following this guide, feel free to leave a comment or shoot me some hatemail.

Synergy

I’ve got a love-hate relationship with Synergy for multiple reasons I won’t get into right now, but it’s definitely the easiest method to share your keyboard and mouse. I recommend setting it up if you want to easily share keyboard, mouse and clipboards, but I’m not going to be able to give a tutorial and still get this out today, so I’m just going to leave it at that. If enough people want a tutorial, I’ll make one. If not, so be it.

Future articles

I’m coming towards the end of the planned articles in the Pragmatic Neckbeard series. I do intend to do an article on the pi-based C&C module, but I want to wait until I’ve got it a bit more stable. I’ve got some stuff in the pipelines, but with the FIRST build season going on right now, I’ve got about 12 high school kids to help with C++ programming and 5 to oversee at the mill. Don’t expect much from me in the next two months.

20 Likes

Awesome series - quick question, could you explain what the process of cold booting is like with AMD hardware?

Great to see you are still working on it! I haven't tested it yet but you might have solved my audio issues. I spent hours of research without a satisfying solution. Thanks in advance!

The 1% performance loss only seems to be affecting older versions of qemu/KVM. In the Arch Linux Wiki they describe a way to simply spoof a vendor ID and hide the KVM extensions while the HyperV features remain activated. I've edited the XML file according to the wiki page and it seems to work well.

1 Like

Thanks for the update! I've tried the archwiki instructions and they worked for my 660ti but not my 970. I chose the more broad attack so no one has problems.

@fdcardano the idea of a cold boot, in general is to completely turn off the computer, then turn it on. "cold boot" generally refers to the first boot of a machine from a previously powered-off state, rather than just restarting. So for the AMD device, whenever you restart the VM, you'll need to shut down the whole computer and turn it back on. This is only for certain AMD GPUs though.

1 Like

maybe for older gpus? polaris 10 works great w/o problems paired with trinity apu(onboard 7560D for host that uses radeon drivers with mesa+gallium and works like a charm even playing games on host is doable) also passthrou is amazing, a bit bottleneck cuz low cpu, would like to get some cheap 3770k/2600k with moboo for cheap too :&

1 Like

Thanks for the tutorials. Was running Freenas 9.10 and moved to Freenas 10 and just could not get past the web ui hanging up so I moved to fedora 25 workstation. I am in process of getting virt-manager and a bridged connection to work but keep getting a spice cant get to localhost when i go to install a new vm. Probably gonna get some screenshots and make a thread on it and get some help if I don't figure it out over the weekend.

1 Like

You're setting up passthrough right? If so, when using virt-manager, you're not going to want a spice display on there. In fact, this is what you want it to look like before you launch.

No passthrough yet. This Dell t20 is mainly gonna be a NAS/ VM rig for stuff like Gitlab,Zoneminder,Unifi controller, dev work, etc, etc. I am waiting for ryzen to hit the market and plan on building a passthrough rig around Christmas of this year.

Ah okay.

Can you attach some screenshots (or paste console output) of the errors you're getting?

Is there a way to get back to that gui editor after configuring, or a simple way to add parameters? Or is virsh edit or whatever the only way?

And would anyone be willing to upload an example config xml with gpu passthrough?

I meant to cover that.

Once you edit the XML with virsh edit, you can still make changes via the GUI. Just reopen it and start making your changes.

Here's my XML. Keep in mind that I'm on Solus, so file paths may not be exactly the same.

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  <name>win10</name>
  <uuid>6cc07e20-90ce-4fe4-ad42-068c58390960</uuid>
  <memory unit='KiB'>8388608</memory>
  <currentMemory unit='KiB'>8388608</currentMemory>
  <vcpu placement='static'>4</vcpu>
  <os>
    <type arch='x86_64' machine='pc-q35-2.7'>hvm</type>
    <loader readonly='yes' type='pflash'>/usr/share/ovmf/ovmf.fd</loader>
    <nvram>/var/lib/libvirt/qemu/nvram/win10_VARS.fd</nvram>
  </os>
  <features>
    <acpi/>
    <apic/>
    <hyperv>
      <relaxed state='on'/>
      <vapic state='on'/>
      <spinlocks state='on' retries='8191'/>
    </hyperv>
    <vmport state='off'/>
  </features>
  <cpu mode='host-model'>
    <model fallback='allow'/>
    <topology sockets='1' cores='4' threads='1'/>
  </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>restart</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/win8.1.qcow2'/>
      <target dev='vda' bus='virtio'/>
      <boot order='1'/>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x04' function='0x0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/data/libvirt/win8.1.qcow2'/>
      <target dev='vdb' bus='virtio'/>
      <boot order='2'/>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x05' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <source file='/data/libvirt/Windows_10.iso'/>
      <target dev='sda' bus='sata'/>
      <readonly/>
      <boot order='3'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <source file='/data/libvirt/virtio-win-0.1.126.iso'/>
      <target dev='sdb' bus='sata'/>
      <readonly/>
      <boot order='4'/>
      <address type='drive' controller='0' bus='0' target='0' unit='1'/>
    </disk>
    <controller type='usb' index='0' model='nec-xhci'>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x03' 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='dmi-to-pci-bridge'>
      <model name='i82801b11-bridge'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/>
    </controller>
    <controller type='pci' index='2' model='pci-bridge'>
      <model name='pci-bridge'/>
      <target chassisNr='2'/>
      <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/>
    </controller>
    <interface type='network'>
      <mac address='52:54:00:3c:44:f3'/>
      <source network='default'/>
      <model type='rtl8139'/>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/>
    </interface>
    <input type='mouse' bus='ps2'/>
    <input type='keyboard' bus='ps2'/>
    <sound model='ich6'>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x02' function='0x0'/>
    </sound>
    <hostdev mode='subsystem' type='pci' managed='yes'>
      <source>
        <address domain='0x0000' bus='0x02' slot='0x00' function='0x0'/>
      </source>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x06' function='0x0'/>
    </hostdev>
    <hostdev mode='subsystem' type='pci' managed='yes'>
      <source>
        <address domain='0x0000' bus='0x02' slot='0x00' function='0x1'/>
      </source>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x07' function='0x0'/>
    </hostdev>
    <hostdev mode='subsystem' type='pci' managed='yes'>
      <source>
        <address domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
      </source>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x09' function='0x0'/>
    </hostdev>
    <redirdev bus='usb' type='spicevmc'>
    </redirdev>
    <redirdev bus='usb' type='spicevmc'>
    </redirdev>
    <memballoon model='virtio'>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x08' function='0x0'/>
    </memballoon>
  </devices>
  <qemu:commandline>
    <qemu:arg value='-cpu'/>
    <qemu:arg value='host,hv_time,kvm=off,hv_vendor_id=null'/>
  </qemu:commandline>
</domain>
1 Like

Yes will do once I get back to it this weekend.

1 Like

Thank you, @SgtAwesomesauce.

I have been at this for a while now, and the problem I keep having is that I can't get any output to my (Asus strix) 980ti.

It only worked one time, and that was on Proxmox and passing the card to Ubuntu 16.10, which complained about drivers and was hardly usable.
It's worth mentioning that I have tried Proxmox, ESXi, and Ubuntu w qemu/kvm. None have really worked so far and Windows absolutely will not boot on the card. I have to force it off with the gpu attached; shutdown won't work.

Now, following this method, the display freezes at boot (because of vfio, right? that's good I guess), since it was blacklisted from the host. I can ssh or VNC to a virtual desktop, start any VM, and it just turns the display off (no signal). I added a spice sever in virt-manager, and got Kali to boot with seabios. lspci in the guest shows that both the gpu and gpu audio are passed through, but there is no display. Booting without a spice console does nothing. Booting anything ovmf with spice on just gives me a uefi shell that also shows the card+audio are passed through (physical display still shows nothing). Seabios without spice also yields nothing on the display. I tried Windows 10, Kali, and TrueOS (BSD), none of which worked.

Any thoughts? Could it have to do with the PLX chips in my board? I am stumped.
Thanks again yall.

So I cranked up the old fedora 25 server cranked up creating a new VM and voila it works now. I believe my problem was I was remote desktop into server from main pc and that was causing my issues. I assume I will need to get a 2nd NIC if I want to remote desktop and also have VMs bridged.

1 Like

Sounds like you aren't binding the GPU correctly. check with lspci -vnn that you've got vfio-pci bound to your GPU AND your gpu's HDMI audio. (you also have to pass both to the VM)

You need to use your iGPU for Linux. Go into your bios and set the primary video output to your iGPU. Then you need to connect one input on the monitor to your iGPU (for Linux) and one to your dGPU (for Windows). This could possibly be part of the "vm not taking the GPU" issue.

Check the boot order in virt-manager. Should be the 5th option. Make sure the cdrom is set to your first or second option and checked.

@sanfordvdev Glad you were able to sort it out. Not sure exactly what the problem was though. :/

Only thing that changed was I worked directly with server instead of using a remote desktop connection. Unless I was doing something during my haze of anger and don't remember now.
Server runs great and now I just need a quick answer on linux permission over my zfs mount folders. I started a thread in linux category if anyone is interested. Don't want to derail this anymore than I have.

getting usbaudiocard ain't so perfect but it's much better than ac97 it has almost no stutters, unless you enable ultralowfreq. in cpu so when it clocks down to lowest multiplier it gives a bit of stutter :P

I can verify that both the gpu and its audio list only vfio-pci under "Kernel driver in use".

I suppose i should have previously mentioned that it's my only gpu in the system, and it's a X99 rig, so no iGPU. I'm guessing now that's the source of my problems, eh?

I did make sure to try the boot order thing before. CD-ROM was first and had a disk image loaded in it. That was part of what led me to the result I described above.

I have a spare hd7750 I could drop in the system and see if that helps pass through the 980ti. It's just that I'd like to avoid having both cards installed if I can. If there's no way around having two gpu's I can live with it, but it'd be nice to just disable video output for the host and pass it through to a VM at boot, making the host transparent, but allowing additional guests to be spawned for other purposes. You know, typical virtualization. :p

I followed a portion of a Reddit post and ran this script:

cp /usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd /tmp/my_vars.fd

qemu-system-x86_64 \
-enable-kvm \
-m 2048 \
-cpu host,kvm=off \
-vga none \
-device vfio-pci,host=05:00.0,multifunction=on \
-device vfio-pci,host=05:00.1 \
-drive if=pflash,format=raw,readonly,file=/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd \
-drive if=pflash,format=raw

And received this error:

(Sorry for the weird layout, I had to screenshot the terminal on my phone).

I searched for the error and found a thread suggesting that "pci-assign" might work in lieu of vfio. Anything notable about that? I tried running it in the script above, but it complained about vfio, so I'll have to go back and disable it before proceeding.

https://bbs.archlinux.org/viewtopic.php?id=162768&p=2

One more question- I looked around, and found a few things but can anyone recommend a Proxmox or ESXi-like web interface to install so I can access my regular installation through https? I love the idea of spinning up a VM in seconds in chromium.

At any rate, I'm learning a lot. Thanks again.

Your image, that issue indicates that it's trying to create a X window. To solve this, try appending:

--nographic

That should get it working. The rest of that command line should be good.

Ok, that took care of the error, but still no video output. I put the hd7750 in slot 3, but no success passing the 980ti in slot 1. If I nuke it and start over, is there a chance I'll be able to pass the gpu in slot 1 or is there no way around the host OS grabbing the first card? I can switch them if I have to.

I am hoping if I start over with them switched and use Proxmox it'll give me everything I want, with the exception of omitting the crappy card. But that's fine.