Setting Windows VM on Linux

Table of Contents
- Introduction
- Examples
- System requirements
- Firmware settings to enable virtualization
- Kernel settings to enable virtualization
- Installing required packages
- Downloading required ISOs
- Creating VM
- GPU passthrough
- Known issues with GPU passthrough
- Setting up EVDEV for input device management
- Further performance optimizations
- Bluetooth
- Windows configuration
- Windows activation
- Windows software installation
- Useful links
Introduction
This article initially started up as a guide to configure KVM for Windows 10/11. Now, obviously, it is still a guide on configuring KVM for Windows 10/11, but there is more stuff on Windows such as debloating, software installation, configuration and etc (see below).
Examples
You can download some examples of configuration files here (zipped folder).
System requirements
You would need a processor with virtual machine acceleration support. Minimal system requirements for running windows VM:
- 2.4+ Ghz CPU with virtualization support and 4+ cores (technically you can even use CPU with 2 cores, but windows guest and host performance issues would blame you).
- 8+ GiB RAM (windows 10 requires at least 4 GiB RAM. Even debloated windows 10 with anti-malware services stopped still eats 3 GiB RAM on standby).
- SSD or NVME (anything except for HDDs - they are slow, so you would literally spend DAYS installing windows or, presumably, any other OS) with 100+ GiB of free space.
- VT-d (or iommu) support for your processor. This feature is required only if you are planning to do PCI/USB devices passthrough to your VM (for example, GPU passthrough). These settings are different for all firmware settings out there so just google how one looks like on your settings.
Firmware settings to enable virtualization
- Enable virtualization:
- Intel: enable
vmx
orIntel Virtualization Technology
option. - AMD: enable
AMD Virtualization Technology
option.
- Intel: enable
- If you are planning to passthrough PCI/USB devices, make sure to enable IOMMU passthrough:
- Intel: enable
VT-d
option. - AMD: enable
iommu
option.
- Intel: enable
Warning! Make sure to reboot your system after this step.
Kernel settings to enable virtualization
-
Open
/etc/default/grub
file in your preferred text editor. -
Add following options to
GRUB_CMDLINE_LINUX_DEFAULT
variable:- Intel:
intel_iommu=on iommu=pt
- AMD:
amd_iommu=on iommu=pt
- Intel:
-
If variables
GRUB_CMDLINE_LINUX_DEFAULT
orGRUB_CMDLINE_LINUX
containquiet
argument, make sure to remove it (at least during the VM configuration, since it would help to indicate kernel issue during boot time if one appears). -
Regenerate grub configuration files and reboot the machine:
grub-mkconfig -o /boot/grub/grub.cfg
-
If you are planning to passthrough PCI devices (not USB), we need to add them to kernel commandline as well: Run the following script in your terminal (no elevated privileges required):
#!/bin/bash shopt -s nullglob for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do echo "IOMMU Group ${g##*/}:" for d in $g/devices/*; do echo -e "\t$(lspci -nns ${d##*/})" done done
Sample output of this script:
IOMMU Group 0: 00:02.0 VGA compatible controller [0300]: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630] [8086:3e98] (rev 02) IOMMU Group 1: 00:00.0 Host bridge [0600]: Intel Corporation 8th/9th Gen Core 8-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] [8086:3e30] (rev 0d) IOMMU Group 2: 00:01.0 PCI bridge [0604]: Intel Corporation 6th-10th Gen Core Processor PCIe Controller (x16) [8086:1901] (rev 0d) 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU106 [GeForce RTX 2060 SUPER] [10de:1f06] (rev a1) 01:00.1 Audio device [0403]: NVIDIA Corporation TU106 High Definition Audio Controller [10de:10f9] (rev a1) 01:00.2 USB controller [0c03]: NVIDIA Corporation TU106 USB 3.1 Host Controller [10de:1ada] (rev a1) 01:00.3 Serial bus controller [0c80]: NVIDIA Corporation TU106 USB Type-C UCSI Controller [10de:1adb] (rev a1)
Warning! If you want to pass a PCI device to VM, you need to pass all devices, which are in the same group with your device, otherwise nothing would work. For example, if I were to pass my GeForce RTX 2060 SUPER to VM, I would also need to pass other devices from IOMMU group 2 to VM (as long as they are available).
Device ids can be found in
[]
brackets at the same line as the device name and description. For example, my GeForce RTX 2060 SUPER has device id10de:1f06
. Copy all these device ids and open back grub configuration.Append following option to
GRUB_CMDLINE_LINUX_DEFAULT
:vfio-pci.ids=<device1>,<device2>,<device3>,...
, wheredevice1
,device2
,device3
are ids of devices you have selected (comma separated). Example:vfio-pci.ids=8086:1901,10de:1f06,10de:10f9,10de:1adb
. -
Open
/etc/modprobe.d/vfio.conf
in your preferred text editor (file might not exist). -
Append the following text:
options vfio-pci ids=<device1>,<device2>,<device3>,...
Where where
device1
,device2
,device3
are ids of devices you have selected (comma separated, should look the same as in kernel commandline).If you are using NVIDIA GPU, append this as well:
softdep nvidia pre: vfio-pci
Warning!
softdep nvidia pre: vfio-pci
works only when you have proprietary nvidia driver installed (pacman -S nvidia
). With open source nvidia driver (nouveau
) this line should be changed to something like:softdep nouveau pre: vfio-pci
(NOT TESTED!).Example:
options vfio-pci ids=8086:1901,10de:1f06,10de:10f9,10de:1adb softdep nvidia pre: vfio-pci
-
Regenerate grub configuration one more time and reboot your machine.
Installing required packages
-
On Arch linux (or any Arch-derived distributive) run:
pacman -S qemu-full virt-manager virt-viewer dnsmasq vde2 bridge-utils openbsd-netcat libguestfs
If you are using any other other distributive, you can figure out yourself how these packages are called for your package manager, it is not that complicated.
Warning! On Artix linux, you should also install libvirt package for your specific init system, for example:
libvirt-openrc
-
After installation, make sure to enable and start
libvirtd
daemon:systemctl enable libvirtd.service systemctl start libvirtd.service
Or
rc-update add libvirtd rc-service libvirtd start
-
Configure libvirtd by modifying
/etc/libvirt/libvirtd.conf
file: Make sure that settings, presented in following lines exist (if not, insert them) and are NOT commented (if so, uncomment them) and set to the correct values:unix_sock_group = "libvirt" unix_socket_ro_perms = "0777" unix_socket_rw_perms = "0770"
-
Add yourself to the
libvirt
group:useradd -aG libvirt <username>
Where
<username>
stands for your username (you can use$USER
environment variable instead). -
Restart libvirtd service by running:
systemctl restart libvirtd.serice
Or
rc-service libvirtd restart
-
Open application, called
Virtual Machine Manager
(included invirt-manager
package) and do the following:- Open
Edit
=>Preferences
and tickEnable XML editing
feature. - Open
Edit
=>Connection Details
=>Virtual Networks
. Make sure to setAutostart (on boot)
property.
- Open
-
If you are installing Windows 11 (which requires TPM device), make sure to install following package to emulate TPM:
pacman -S swtpm
Warning! Make sure to logout and login back or reboot your system to make sure you have got added to the libvirt group.
Downloading required ISOs
- Download Windows 10 ISO from Microsoft website or use 3rd party ISO downloader.
- Download Qemu VirtIO drivers for Windows from github repository. I recommend choosing
Stable
version instead of latest. Also make sure that you are downloading ISO, not RPM or any other package.
Creating VM
- Open application, called
Virtual Machine Manager
(included invirt-manager
package). HitFile
=>New Virtual Machine
and configure your virtual machine. I recommend giving it at least 2 CPU cores and 4 GiB of RAM. On the last page, clickConfigure Before Installation
and hitFinish
. - Set firmware type to
UEFI
. - Open
CPUs
section and hitManually set CPU topology
. Make sure that socket count is 1 (do not know why virt manager does this by default). Adjust the CPU topology for optimal performance. If your host machine has more than 1 logical core per physical core, specify this in topology. - Add TPM device if you are installing Windows 11. Click
Add Hardware
=>TPM
. Make sure to set type toEmulated
. - Remove
USB Redirector #...
devices from your VM (if they exist). They are useless. - If you are installing
Windows 11
, remove network adapter from VM (you would add it later, after installation). - Now launch your VM and install Windows. After installation is complete, shut the VM down and remove the installation (windows) ISO.
- Add ISO for qemu virtio drivers and boot Windows.
- Add temporary virtio disk.
Add Hardware
=>Storage
. Nobody actually cares about this disk, so you can just leave its size to1GiB
. If you can change the disk type tovirtio
, do that, otherwise open XML properties for this disk and modify following:- In
target
field changebus
option tovirtio
. - In
address
field changetype
option topci
.
- In
- Boot the VM. Open ISO folder and launch
virtio-win-guest-tools
application. - After installation is complete, power off the VM. Remove the qemu virtio drivers installation media as well as temporary virtio drive.
- Open XML properties for windows virtual disk (the one, which contains windows installation):
- In
target
field changebus
option fromsata
tovirtio
. - In
address
field changetype
option fromdrive
topci
. - In
driver
field adddiscard="unmap"
option (if does not exist already).
- In
- Open NIC (Network Interface Card)properties and change
Device model
tovirtio
(If you are installing Windows 11 and you have deleted the NIC, just create new one).
GPU passthrough
-
Open virtual machine settings and click
Add Hardware
=>PCI Host Device
. For each device id that you have configured kernel to isolate and use virtio driver in kernel settings to enable virtualization step, add it to virtual machine. -
Boot your virtual machine. You should not use your GPU output port for now, since it is not configured properly. Download nvidia drivers (I suggest downloading game ready driver, since it appears to be NVIDIA's general purpose solution for its GPUs) using this link.
If your mouse stops working after driver installation, it is totally ok, fixing this in further steps.
Now your GPU is fully configured. Make sure to connect your monitor with it.
-
Open
Overview
section in your VM settings. OpenXML
editor. Find and delete all properties which havespice
orvnc
orvga
(case-insensitive). Delete allSPICE
andVGA
related stuff from your virtual machine settings (both XML and UI). Remove USB redirectors from your settings (can be done with UI). -
Now you can boot your virtual machine (not recommended yet!). Video would now be displayed through GPU.
Known issues with GPU passthrough
- XFCE4: When switching between VM and host
Display
(Display settings) window pops up:- Navigate to
Settings
=>Display
=>Advanced
. - Set property
When new displays are connected
(in theConnecting Displays
section) toDo nothing
.
- Navigate to
- XFCE4: When switching between VM and host resolution resets to monitor default:
- Instead of changing monitor resolution, use scaling. Example: monitor has default resolution
3840x2160
; instead of chaning it to1920x1080
, set scale to0.5x0.5
.
- Instead of changing monitor resolution, use scaling. Example: monitor has default resolution
Setting up EVDEV for input device management
-
Open
Overview
section in your VM settings. OpenXML
editor. Replace first line in XML content with the following text:<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0" type="kvm">
-
Clone evdev repository (it is not recommended to delete it after installation for further configuration, so place it somewhere safe):
git clone --depth 1 https://github.com/pavolelsig/evdev_helper.git cd evdev_helper
Run the
run_ev_helper.sh
script:chmod a+x run_ev_helper.sh ./run_ev_helper.sh
This script would create file named
evdev.txt
. Evdev would configure qemu so that:- To redirect input from keyboard/mouse to VM, you should press left and right CTRL keys simultaneously.
- To switch input from keyboard/mouse back to host, you should press left and right CTRL simultaneously.
This script also creates qemu backup configuration - stored in
.backup.qemu.conf
file.Copy all contents of
evdev.txt
file except for first line (you have already inserted that at step 1) and insert it in your VM XML configuration (openOverview
=>XML
) at the very end of the configuration - below</devices>
and above</domain>
. -
Copy following XML and insert it in your VM XML configuration (open
Overview
=>XML
) at the very end of the configuration - below</devices>
and above</domain>
:<qemu:capabilities> <qemu:del capability="usb-host.hostdevice"/> </qemu:capabilities>
-
Now you can start virtual machine (make sure to switch monitor signal input to the GPU you have passed through).
Further performance optimizations
-
Enable IO threads (disk might work faster).
- Insert following XML under
domain
property in virtual machine XML configuration (openOverview
=>XML
):
You can have more io threads, but it is not recommended to have more than one.<iothreads>1</iothreads>
- Open XML properties for windows virtual disk (the one, which contains windows installation) And append following parameters to
driver
property (remove duplicates):cache="none"
io="threads"
queues="6"
(set to whatever vCPUs you have provided VM with).
- Insert following XML under
-
Enable static CPU placement (not recommended for standart installation, unless you want to maximum performance):
-
Add
placement="static"
option invcpu
property in virtual machine XML configuration (openOverview
=>XML
): -
Under
vcpu
property addcputune
section. This section would specify, which virtual processor would be bound to which physical (or logical) core. Specify binding with the following XML:<vcpupin vcpu="<virtual cpu index>" cpuset="<physical cpu index>"/>
Where
virtual cpu index
andphysical cpu index
are just integers. You must mention all virtual CPUs in binding settings.Example:
<cputune> <vcpupin vcpu="0" cpuset="1"/> <vcpupin vcpu="1" cpuset="5"/> <vcpupin vcpu="4" cpuset="3"/> <vcpupin vcpu="5" cpuset="7"/> </cputune>
You can also add
emulatorpin
property to set affinity for qemu emulator (multiple cores can be specified):<emulatorpin cpuset="0,4"/>
If you are using iothreads, you can setup binding for iothread as well by adding
iothreadpin
property (multiple cores can be specified):<iothreadpin iothread="1" cpuset="0,4"/>
Example with
iothreadpin
andemulatorpin
:<cputune> <vcpupin vcpu="0" cpuset="1"/> <vcpupin vcpu="1" cpuset="5"/> <vcpupin vcpu="4" cpuset="3"/> <vcpupin vcpu="5" cpuset="7"/> <emulatorpin cpuset="0,4"/> <iothreadpin iothread="1" cpuset="0,4"/> </cputune>
Make sure to separate VM-related cores and stuff-related cores (qemu emulator or io threads) to maximize performance.
-
Replace the entire
<hyperv>
tree configuration settings with the following:<hyperv mode="custom"> <relaxed state="on"/> <vapic state="on"/> <spinlocks state="on" retries="8191"/> <vpindex state="on"/> <synic state="on"/> <stimer state="on"> <direct state="on"/> </stimer> <reset state="on"/> <frequencies state="on"/> <reenlightenment state="on"/> <tlbflush state="on"/> <ipi state="on"/> </hyperv>
-
Bluetooth
Since bluetooth is USB-bus device (even motherboard-integrated bluetooth uses USB bus), you do not need to configure it same as PCI devices. Open VM settings, click Add Hardware
, click USB Host Device
, select and add your bluetooth device to VM.
Windows configuration
- Both windows 10 and 11 contain a lot of bloatware out of the box. Since we are configuring virtual machine, most of this bloatware would never be used, such as
camera
,cortana
,diagnostic centre
etc. For Windows 11 installation (would also work on windows 10, but not recommended) you can use this debloat script collection. For Windows 10 installation you can use this script (project is abandoned, but is still useful). - You can also use free tool
O&O ShutUp10++: Free antispy tool for Windows 10 and 11
. It allows to tweak some windows telemetry/spy/data collection settings. Download link. When configuring windows using this app, make sure to apply settings both for current user and entire system. - You can also use Chris Titus Windows Tool, which combines A LOT OF functionality, including debloating stuff, software removal, all kinds of tweaks, automated software install and many more. Configuration system is also supported.
- Completely remove Microsoft Edge:
- Open
Command Prompt
with Administrator privileges. - Navigate to
C:\Program Files (x86)\Microsoft\Edge\Application\<edge-version-here>\Installer
.<edge-version-here>
stands for current edge version, which typically looks like this:92.0.902.67
. If you have many different edge versions installed, you should repeat uninstall process for each version. - Execute following (make sure to do this as an administrator):
setup.exe -uninstall -system-level -verbose-logging -force-uninstall
- Open task manager and kill all tasks, which are related to edge. Since we had already uninstalled it, you should mostly look for processes like
EdgeUpdater...
etc. Make sure to destroy all of them. - Open services management page (both on windows 10 and windows 11 you can do this via task manager). Find services related to edge (typically those are auto-update services). Open their properties and make sure to set
Autostart Type
toDisabled
. - Remove all related to edge folders in
C:\Program Files (x86)\Microsoft
. Those being:Edge
,EdgeWebView
,EdgeCore
and some others (might depend on your windows installation). This process would require administrator privileges.
- Open
- Adjust Windows Performance settings:
- Open
Settings => System => About
. - Open
System Protection
men. For Windows 10 it is located on the right. For Windows 11 it is located on the bottom. - Select
Advanced
tab in newly opened menu. - Open
Performance
settings. - Here you can remove basically all checked marks (since they not really usable much), except maybe for
Smooth Edges of Screen Fonts
(which basically enables font Anti-Aliasing for you). The best thing you can do is to adjust it depending on what exactly are you planning to do.
- Open
Warning! All this optimizations might not have good affect at your installation. Apply them at your own risk!
Windows activation
-
Select your product key (same keys apply for both windows 10 and windows 11):
Edition Product Key Home TX9XD-98N7V-6WMQ6-BX7FG-H8Q99
Home N 3KHY7-WNT83-DGQKR-F7HPR-844BM
Home Single Language 7HNRX-D7KGG-3K4RQ-4WPJ4-YTDFH
Home Country Specific PVMJN-6DFY6–9CCP6–7BKTT-D3WVR
Professional W269N-WFGWX-YVC9B-4J6C9-T83GX
Professional N MH37W-N47XK-V7XM9-C7227-GCQG9
Education NW6C2-QMPVW-D7KKK-3GKT6-VCFB2
Education N 2WH4N-8QGBV-H22JP-CT43Q-MDWWJ
Enterprise NPPR9-FWDCX-D2C8J-H872K-2YT43
Enterprise N DPH2V-TTNVB-4X9Q3-TJR4H-KHJW4
By the way, the "N" in Windows stands for "Not with Media Player." As the name implies, the only difference between Windows N and other Windows editions is that it does not come with built-in multimedia features.
-
Install KMS client key:
slmgr /ipk <license-key>
-
Connect to KMS server:
slmgr /skms kms8.msguides.com
-
Activate Windows
slmgr /ato
If your Windows didn't get activated, you can try another license key. Also check your internet connection.
Windows software installation
The majority of the software most people need can be installed via again, Chris Titus Windows Tool, as it was already mentioned in Windows configuration section. However, there are still programs that are either not covered by this tool, or those you want to install manually. We will not go though all of them, here are the common ones:
- VMware Workstation. Product copies can be acquired from Broadcom website. You will to create an account. However, broadcom will not allow you to download anything, if it detects that you are trying to register or log in from country, sanctioned by the US. Unfortunately, VPNs (both private and public) do not solve this issue, so the best way to access and do anything on Broadcom website, unfortunately, is to use
Tor
. Don't forget to disableNoScript
extension for all Broadcom website subdomains. - Microsoft Office. There is a guide on how to install Microsoft Office here. In short: Legit office configuration with volume licenses can be generated at config.office.com (click
Create
button in the bottom left corner). Detailed video can be found here. The video describes how to download and install Office 2021, but with config.office.com you can try to install whatever version you want. If you end up with error, try a different version. My recommendation is to select LTSC (long time support) releases.
Useful links
- Bluetooth passthrough
- Mental Outlaw: Setting up Windows 10 VM
- Mental Outlaw: NVIDIA GPU passthrough
- NVIDIA GPU passthough
- GPU passthrough performance
- CPU topology
- Mental Outlaw: Windows 10 Debloating
- Mental Outlaw: Windows 11 Debloating
- Chris Titus Windows Tool
- Windows 10/11 Activation
- Microsoft Edge Uninstall
- Microsoft Office Install Guide
- Microsoft Office configuration website
- Broadcom website