Fighting error 43 – Nvidia GPU in a virtual machine

The infamous error 43 is triggered by the Nvidia Windows driver, in case it recognizes the GPU is used inside a virtual machine with GPU passthrough. This means the driver won’t load correctly during the system startup leaving you with cumbersome 800 by 600 display resolution.

Update: With Nvidia driver v465 (or later) Nvidia officially supports the use of consumer GPUs in virtual environments. Thus, edits recommended in this article are no longer required. Thank you!

An examination of the Windows Device Manager will unveil the culprit – Code 43

Windows has stopped this device because it has reported problems. (Code 43)

nvidia error code 43
nvidia error code 43 in Windows 10 device manager

 

Luckily, KVM/QEMU is able to hide the fact that the Nvidia driver is running a virtual environment.

The tested system setup

This method has been tested for the following versions

Host:

  • OS: Ubuntu 18.04, as well as a 16.04
  • Kernel: 4.15 – 5.3.6
  • Hypervisor: QEMU 2.12.0 up to 4.1
  • Libvirt: version 4.6.0 up to 4.7.0

One can use virsh version in order to display the current version status.

Guest:

  • OS: Windows 10 1803 – 1903
  • VM chipset: i440FX, Q35
  • Nvidia driver: 399.07 – 441.12
  • GPU: Geforce GTX 970 and Geforce GTX 1060

Fixing error 43

In order to hide that the system is running on a hypervisor, KVM supports the “hidden” flag.

Depending on whether you call QEMU directly or call it via Libvirt the flag syntax differs.

Set KVM hidden via Libvirt xml

In order edit the virtual machines configuration use:

virsh edit your-windows-vm-name

Once your done editing, you can use CTRL+x CTRL+y to save the changes.

For QEMU 3.0 and later the required flags are “vendor_id” in the hyperv section, and “hidden” in the kvm section, of the features block, of the virtual machines xml definiton. I think it is recommended to use a 12 character value (see excerpt marked green).

Additionally, in case you are using QEMU 4.0 (or higher) in combination with a Q35 chip, the flag ‘ioapic driver='kvm'‘ needs to be added in the features section (see excerpt marked blue).

Excerpt from libvirt xml file

  ...
<features>
<acpi/>
<apic/>
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
<vendor_id state='on' value='1234567890ab'/>
</hyperv>
<kvm>
<hidden state='on'/>
</kvm>
<vmport state='off'/>
<ioapic driver='kvm'/>
</features>
...

Set KVM hidden for direct QEMU usage

In case you call QEMU directly you have to add the flags ‘kvm=off‘ and ‘vendor_id=null‘ on your cpu argument (see excerpt marked green).

Additionally, in case you are using QEMU 4.0 (or higher) in combination with a Q35 chip, use the machine argument ‘kernel_irqchip=on‘.

Example for virtual machine with host-passthrough set as CPU model and Q35 as machine type:

...
-cpu 'host,kvm=off,hv_vendor_id=null' \ -machine 'type=q35,kernel_irqchip=on' \
...

Using QEMU command arguments in the libvirt XML definition

Just for the sake of completeness (and historical compatibility of this article), there is a third way of enabling the hypervisor spoofing. Actually it is a combination of the two described earlier, as it is possible to add QEMU arguments to the libvirt xml defintion file.

These arguments are called after the definition has been parsed, and usually overwrite the settings made via XML structure. Thus it is not recommended to use both ways for one setting in the same definition file.

First of all find the very first line, which should read:

<domain type='kvm'>

and replace it with:

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

Find the line which ends with </devices>
and add the following block afterwards (or alter the block if it already exists):

   ...
</devices>
<qemu:commandline>

<qemu:arg value='-cpu'/>
<qemu:arg value='host,kvm=off,hv_vendor_id=null'/>
<qemu:arg value='-machine'/>
<qemu:arg value='q35,kernel_irqchip=on'/>

</qemu:commandline>
</domain>

Attention: Make sure <devices> and <qemu:commandline> have the same indent.


Thats it – these settings work for me.

Sources

As usual, the glorious arch wiki has further information and help; i.e. it recommends using a 12-character alphanumeric string as vendor ID.

Post updates

21.09.2019 – added further information regarding qemu 4.0 and error 43

07.11.2019 – updated the article structure

25 comments on “Fighting error 43 – Nvidia GPU in a virtual machine”

  1. MICHAEL MAST

    This got me past code 43, but now I get no video during Windows 10 boot. I can get into safe mode no issue, but normal boot produces no video signal and the monitor goes to sleep.

    Reply
  2. Graeme

    How do i fix Code 43 in Xen, as KVM my USB 3 card is grabed by XHCI_HCD!!!!!!!! and i don’t have much success recompiling Kernel to make it a damm module.

    Reply
    1. Mathias Hueber

      Unfortunately, I don’t have much experience with Xen. Which USB-3 card are you using? I found this thread. Also see the redhat post they are referencing.

      Reply
  3. Frank

    Can you please post the actual starting command of the VM? I’m using Proxmox thus “” does not exit there. I am trying to find its equivalent but got no good, the starting command would be really helpful. Thank you!

    Reply
  4. Enyce

    Anyone succeed with the code43 ?

    Reply
    1. Bikram

      Try virshpatcher you’ll know what i am talking about

      Reply
  5. Tosto

    Nothing changed applying these instructions for me.
    Arch/Virt-manager/kvm/geforce 840m

    Reply
  6. ledjoud

    On my config I had an error in dmesg (Bar 3 : ….) which resulted in an error 43 in the Windows host.
    I had to add video=efifb:off to the grub command line and now it works.

    Reply
    1. utilit

      After looking around for a long time this was also the fix for me.
      sudo nano /etc/default/grub
      Add video=efifb:off
      sudo update-grub

      Now it’s working. Mostly. I can launch games on the Win10 host without the Nvidia driver error, and I have display either through spice or through direct attachment, but if I use Spice, mouse isn’t working from the host OS. Does work with a separate mouse redirected to the VM before rebooting.
      If I use Spice as 1 of my 2 monitors, i.e. multi monitor with 1 pane of glass being from Ubuntu, 1 directly to Windows, host mouse isn’t working, and the pointer from Windows is invisible. Interesting.

      Reply
  7. Mr

    Thanks for this great writeup. Helped me fix a botched install and get a GTX 970 running via passthrough.

    Reply
  8. eSavior

    Hi, Mathias. Thanks for documenting this workaround! This article got me past the final Code 43 hurdle on my Linux Mint 20 GPU passthrough voyage for my GeForce 1050ti coupled with a basic Gigabyte B460M DS3H motherboard with a 10th gen Core i7 CPU. The only thing your main passthrough article didn’t describe was a way to make my 1050ti be the primary graphics adapter so Windows 10 would use it instead of the Spice display. To work around that issue, I just removed the Video QXL device and the Graphics Spice devices so that the 1050ti would be the only display adapter Windows 20H2 could access. Maybe now that I have this workaround in place, I can add back the other virtual display. For now, I press ahead into GPU passthrough territory and see what amazing 3d graphics stuff I can revel in 🙂

    Reply
  9. Gary

    May I know anyone can use with hiding KVM for NVIDIA driver for 2 VMs running (1 GPU card passthrough per VM)? Thanks

    Reply
  10. Alligatorbirne

    With the newer nvidia drivers (v465 or later) this modification is not longer necessary.
    The geforce cards now are ready to use for gpu passtrough.

    Reply
    1. Mathias Hueber

      Thank you very much Alligatorbirne! I have added the update.

      Reply
      1. Krishna

        It is not true completely. Some gpus like the 940mx first had its support discontinued and then this modification came up. The drivers never fixes for them. Whats more my physical win11 just has virtualization enabled for Docker Kubernetes testing, and the 940mx driver refuses to install for the physical windows throwing code43.

        Reply
  11. dement

    when i try to install drivers with nvidia geforce experience, they finish installing but then i get asked to install the same drivers again.
    i am stuck on 800×600 resolution and i cant open nvidia control panel, i get an error message or no message at all

    i am on zorin os 16 with a Gigabyte GTX 1080 Ti 11 GB, using virt-manager 2.2.1

    virsh version
    Compiled against library: libvirt 6.0.0
    Using library: libvirt 6.0.0
    Using API: QEMU 6.0.0
    Running hypervisor: QEMU 4.2.1

    here is the features part of my xml:

    Reply
      1. dement

        features>

        </features

        it wont post the xml lol

        Reply
        1. dement

          pastebin.com/rSdWridD
          here is the xml

          Reply
          1. dement

            here is also a link to the whole xml:
            https://pastebin.com/cELzxQ6u

  12. dureal99d

    I have been working at this for 2 weeks now and this worked well for me. Thank you to the author. Card used is a Nvidia gt 710 1gb mem version. Was getting code 43 until I added this to my XML.

    Reply
  13. Patrick

    I am using qemu kvm on ubuntu and try to install win10 and pass a AMD radeon rx 6800 xt with no success. Keep getting error 43. if anyone can help me getting this damn card passed through i‘ll owe you a bottle of single malt! Greetings from Zurich

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *