How to Run (Not Only) Windows Virtual Machine on Linux

I guess you are running Linux on your physical computer. Have you ever needed to run some Windows-only software on your Linux machine? While there are some solutions like Wine, the most reliable way to run Windows programs is by running them on Windows itself. You don't want to install Windows on your computer, you say? You can install it in a virtual machine! Installation media for Windows 10 can be downloaded free of charge from Microsoft website, and it even works without having a license (with some limitations, like an unability to change a wallpaper).

This method mentioned in this howto works for installing other guest (virtualized) operating systems too. In case of Linux guests, it is even easier because Linux distros often already include virtio and QXL drivers and there is no need to install any additional drivers.

Created
October 16, 2019

Virtualization Software on Linux

To be able to create virtual machines, software called hypervisor needs to be installed on the host machine. Host machine is the (usually physical) machine that runs the virtual machines. Virtual machines are then called guests.

Type-1 hypervisors run on bare metal. An example would be Hyper-V on non-home Windows versions. Installing Hyper-V turns the original Windows operating system into a virtual machine. Because of this, Hyper-V virtual machines do not show up in the Task Manager. A Type-1 hypervisor on Linux would be Xen.

Type-2 hypervisors run virtual machines as processes within the host operating system. Some examples would be QEMU/KVM, VirtualBox, VMware Workstation.

These are some of the popular hypervisors (or virtual machine managers) that run on Linux and are free to use:

GNOME Boxes

This app often comes pre-installed with the GNOME desktop. It is installed by default on Fedora Workstation. The user interface is very simple and does not offer many advanced settings. It uses the QEMU/KVM hypervisor in the background. Because of this, advanced settings of virtual machines can be specified using some other software tools, such as virsh.

I use GNOME Boxes for quick testing of various operating systems.

Virtual Machine Manager (virt-manager)

This is a graphical user interface for various Linux virtualization hypervisors, including QEMU/KVM. It is usually included in repositories of the Linux distribution and is easy to install and get running.

Virtual Machine Manager with KVM is my go-to solution for running virtual machines on Linux. With virtio graphical driver, it supports 3D acceleration on Linux guests (but not on Windows guests).

VirtualBox

VirtualBox is a free and open-source hypervisor. It is cross-platform, meaning that it can be installed on various operating systems, including Linux, Windows, macOS, and Solaris. It may not be available in the Linux distro's repositories, but it can be installed from the official 3rd party repositories. However, it may cause problems with UEFI Secure Boot (if it is enabled on the host machine) because of unsigned kernel modules.

VirtualBox can be useful for creating portable virtual machines that can be run on various operating systems. Its performance can be a bit slower compared to other hypervisors.

VMware Workstation Player

This is a free version of VMware Workstation Pro. It is free for personal use only and comes with some limitations to the Pro version. It can be installed on Linux and Windows.

I don't have much experience with VMware Player, however I've read that it (reliably) supports graphical 3D acceleration on Windows guests and that its virtual machines perform very well.

Install Virtual Machine Manager (virt-manager)

I use Virtual Machine Manager with QEMU/KVM hypervisor. On Fedora, it comes as a part of the Virtualization group. This group can be installed using the following command.

sudo dnf install @virtualization

On other Linux distributions, search for some official documentation regarding virtualization or just try searching for virt-manager package in the repositories.

Once the Virtual Machine Manager is installed, it should be accessible from the application menu:

A screenshot of an icon of Virtual Machine Manager in an app overview on GNOME desktop

It will need an administrator's password to be able to manage virtual machines. This should be possible to change by adding the user to some specific group and/or by settings some additional permissions. Writing my password doesn't bother me so I never had a reason to investigate this more.

A screenshot of a GNOME polkit pasword prompt

Next, a window like the following should appear. It contains an overview of existing virtual machines on the system. The list will be empty if there are no virtual machines created.

A screenshot of the main Virtual Machine Manager window

Create a Virtual Machine and Install Guest Operating System

This is only a brief overview of steps I do when creating a virtual machine in Virtual Machine Manager (virt-manager). A step-by-step guide showing how to accomplish these steps will follow.

A step-by-step guide showing how to accomplish these steps along with the description of why I modify some default options can be accessed by clicking the following button.

Step-by-step VM creation with description

Create a Virtual Machine

Before creating a virtual machine, decide whether to use user or global session for QEMU/KVM. User session does not require administrator privileges but may not offer all features like some hardware passthrough or advanced networking.

Things I do when creating a virtual machine (not all are necessary):

  1. Use qcow2 disk format for snapshot ability, raw for better performance.
  2. Set Chipset to Q35 (now it is selected by default).
  3. Change Firmware from BIOS to UEFI x86_64.
  4. Add a controller:
    • Type: SCSI
    • Model: VirtIO SCSI
  5. Attach the hard drive to this controller. In the disk options, choose:
    • Disk bus: SCSI
    • Discard mode: unmap
  6. Maybe change CPU topology to one socket with multiple cores. It is also possible to specify the CPU architecture.

Install

Once the virtual machine is created, a guest os (Windows in this case) can be installed. The steps are the same as if the installation was being done on a physical computer.

Install Guest Drivers

Windows does not always include all drivers by default. Most notably, it does not include a QXL driver for virtual graphics card and a virtio SCSI driver for accessing virtio SCSI hard drives.

Drivers from two sources can be installed:

  1. VirtIO drivers from Fedora repository (recommended on linux-kvm.org),
  2. Spice Windows Guest Tools for better integration and enabling synchronization of clipboard.

Troubleshooting

These are some of the things I came across when using virtual machines in virt-manager.

Virtual Machine Crashes When a Debugging Software is Run on The Guest

Symptom: When I run OllyDbg version 2.01 debugger on a Windows virtual machine, the guest Windows freezes, shows a Blue Screen Of Death and reboots.

Solution: As per this Microsoft Answers thread, this is caused because the debugging software accesses some Model Specific Registers (MSR) that cannot be virtualized. QEMU hypervisor does not try to emulate these registers.

Accessing these registers can be ignored by running the following script (info about this feature).

#!/bin/bash
echo '(Must be run as root)'
# Debuggers in Windows can result in BSOD under KVM, this is the solution
echo 1 > /sys/module/kvm/parameters/ignore_msrs && \
echo Success.

Note that these registers can be accessed by other software than debuggers, including games. It may be possible to mitigate this problem by changing the virtual CPU architecture to Core 2 Duo. In this case, the app should fall back to not using these MSRs.

Host Operating System Uses Swap Space When RAM Is Not Full Yet

Symptom: There is still some free space in the RAM on the host but it starts swapping to hard drive anyway.

Solution: Decrease swappiness value (but do not disable swap altogether):

sudo sysctl -w vm.swappiness=1

Virt-manager does not offer an unmap discard option

Solution: just change it manually using virsh:

sudo virsh edit virtual-debian

Change this line, add discard='unmap':

<driver name='qemu' type='qcow2' discard='unmap'/>