Installing a Linux Mint 19 (Ubuntu 18.04) VM with VGA Passthrough

Introduction

Installing a Linux Mint 19 VM (or Ubuntu 18.04) with VGA passthrough is surprisingly straightforward. This tutorial follows the Running Windows 10 on Linux using KVM with VGA Passthrough almost step-by-step. I will therefore focus on what’s different from the above tutorial.

While booting the Linux Mint 19 life installation media (ISO) as a VM was easy, the installation of Linux Mint invariably ended with the following error:

The ‘grub-efi-amd64-signed’ package failed to install target/

The following tutorial will describe the steps to overcome this problem (bug?).

Preliminary steps

As always: Backup your system! I mean everything – the host, the VMs, etc. One small error and your valuable data is lost.

If you already installed a Windows 10 VM with VGA passthrough, you can skip to the next step, “Edit the Linux VM start script”.

  1. If you have not yet prepared your PC for VGA passthrough, follow the Running Windows 10 on Linux using KVM with VGA Passthrough tutorial chapters 4.1 to 4.6.
  2. Download the life Linux ISO of the distribution you wish to install, for example from https://linuxmint.com/download.php or https://www.ubuntu.com/download/desktop.

Edit the Linux VM start script

Copy the start script from chapter 4.10¬† and save it as “linuxvm.sh”. If you already have a working Windows 10 VM start script, copy that script!

Make the file executable:
sudo chmod +x linuxvm.sh

Now edit the script in your favorite editor. Change the name of the VM at the top of the script, for example:

vmname="lm19vm"

Just underneath the VM name definition is a “if...else...fi” statement. Make sure it reads as follows:

if ps -ef | grep qemu-system-x86_64 | grep -q multifunction=on; then
echo "A passthrough VM is already running." &
exit 1

else

(Explanation: The above statement checks if we are accidentally trying to run a second VGA passthrough VM. The ps -ef command shows the running processes and their command line. grep qemu-system-x86_64 filters out the qemu command, but also the ps -ef | grep qemu… command we just issued. To filter out the latter, grep -q multifunction=on searches through the qemu command to detect if it contains “multifunction=on“, which is a good indicator for VGA passthrough.

If your script does NOT contain the “multifunction=on” option, replace it by the PCI bus ID of the graphics card, e.g. “02:00.0“.)

Underneath the qemu-system-x86_64 command, look for the following lines:

-drive id=disk0,if=virtio,cache=none,format=raw,file=/media/user/win.img \
-drive file=/home/user/ISOs/win10.iso,index=1,media=cdrom \
-drive file=/home/user/Downloads/virtio-win-0.1.140.iso,index=2,media=cdrom \

and change them to:

-drive id=disk0,if=virtio,cache=none,format=raw,file=/media/user/linux.img \
-drive file=/home/user/ISOs/linux.iso,index=1,media=cdrom \

Important: Replace the paths and filenames with yours.

Note that we don’t need the virtio-win-0.1.140.iso driver disk for Linux.

As an example, here is my complete qemu… command:

qemu-system-x86_64 \
-name $vmname,process=$vmname \
-machine type=q35,accel=kvm \
-cpu host,kvm=off \
-smp 4,sockets=1,cores=2,threads=2 \
-m 8G \
-balloon none \
-rtc clock=host,base=localtime \
-vga none \
-nographic \
-serial none \
-parallel none \
-soundhw hda \
-usb -usb-host,vendorid=045e,productid=076c \
-usb-host,vendorid=045e,productid=0750 \
-device vfio-pci,host=02:00.0,multifunction=on \
-device vfio-pci,host=02:00.1 \
-drive if=pflash,format=raw,readonly,file=/usr/share/OVMF/OVMF_CODE.fd \
-drive if=pflash,format=raw,file=/tmp/my_vars.fd \
-boot order=dc \
-drive id=disk0,if=virtio,cache=none,format=raw,file=/media/user/linux.img \
-drive file=/home/user/ISOs/linux.iso,index=1,media=cdrom \
-netdev type=tap,id=net0,ifname=vmtap0,vhost=on \
-device virtio-net-pci,netdev=net0,mac=00:16:3e:00:01:01

Important: Replace the PCI IDs/slots of the devices (mouse, keyboard, GPU) you pass to the guest with the PCI IDs you discovered in chapter 4.3:

-usb -usb-host,vendorid=045e,productid=076c \
-usb-host,vendorid=045e,productid=0750 \
-device vfio-pci,host=02:00.0,multifunction=on \
-device vfio-pci,host=02:00.1 \

Check the script file to see that the file names and paths are correct, as well as the PCI devices.

Install the Linux VM

After you have verified the VM start script, run the script as follows from a terminal:

sudo ./linux.sh

If all goes well, you will see a brief Tianocore screen and the life Linux media will boot.

Once you see the desktop, open Firefox and see if networking works.

If you got a network connection, proceed to run the installer.

Inside the installer (ubiquity in the case of Linux Mint and Ubuntu) skip the installation of 3rd party drivers.

At the “Installation type” screen, select the default option (“Erase disk and install Linux Mint” in the case of Linux Mint 19). This will install Linux onto the virtual file system linux.img we created with fallocate.

The installation will then proceed and end with the following error message:

The ‘grub-efi-amd64-signed’ package failed to install into target/

When you click OK, it will tell you that grub didn’t install and that the system cannot be booted.

This problem has been reported here, together with a solution that only required some minor modifications. These are the steps to work around this bug/error:

  1. Open a terminal and enter:
    sudo -i
  2. Mount the installed file system into /mnt:
    mount /dev/vda2 /mnt
    mount /dev/vda1 /mnt/boot/efi

    for i in /dev /dev/pts /proc /sys; do sudo mount -B $i /mnt$i; done
    where /dev/vda2 is the root partition and /dev/vda1 the EFI partition.
  3. Load the efivars module:
    modprobe efivars
  4. Reinstall grub-install:
    apt-get install --reinstall grub-efi-amd64-signed
    grub-install --no-nvram --root-directory=/mnt
  5. Change root to /mnt and run update-grub:
    chroot /mnt
    update-grub
  6. Once update-grub ran successfully (check the terminal output), you can exit the chroot:
    exit
  7. Quit the Linux VM.
  8. Edit the start script and change the following line to read:
    -boot order=c \
    Save the file.
  9. Boot the Linux VM:
    sudo ./linux.sh

If all goes well, your newly installed Linux VM will boot. You can then update the packages and install drivers, for instance the proprietary Nvidia graphics driver (if your passed-through GPU is Nvidia).

Please let me know if this tutorial has worked for you (or not) by leaving a comment below.

 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.