Create Windows VM using libvirt
Introduction
This is a simple guide about setting up a Windows guest using KVM. This guide will mainly focuse on using the GUI tool virt-manager with some minor tweak directly in the XML template.
There are many similar guides which you can find online. For example
# the unraid documentation
https://wiki.unraid.net/UnRAID_6/VM_Guest_Support
and
# a useful blog post
http://bkanuka.com/posts/windows-10-libvirt/
basic requirement
- Host machine: Ubuntu 20.04 with KVM installed.
- Windows system images(iso files).
- VirtIO drivers(in a iso file.)
Create the VM
Open the
virt-manager
and selectcreate a new virtual machine
and thenuse local install media(ISO)
. Also, if it can’t detect the guest system from the iso file, you should manually set it towin(10) # or Microsoft Windows 10
Note: you may find this
Microsoft Windows 10(win 10)
system type at theend of life operating systems
category.Keep forward, you can set the memory and number of CPUs for this VM.
You can create a disk image for this VM. This is a simpler choice. Also, you can choose not to create a disk image and passthrough a whole hard drive to your VM(which will not be covered in this guide).
Note: this disk image can not be easily expanded(as far as I know) after creation. A post about [resizing disk image](/post/change-virtual-disk-image/) has been posted. So set its volumn wisely.(But actually you can always set up additional network storage or passthrough addtional disk space to your VM later.)
In the final step, you can setup the name of your VM. Also remember to check
Customize configuration before install
so you can adjust some addtional settings before the VM fires up.In the configuration panel:
In
Overview
, choose firmware toUEFI OVMF
. I choose ‘OVMF_CODE.fd’. For chipset, I preferQ35
, but you can always tryi440fx
, their difference are quite subtle and depending on the very host machine setup.In
CPUs
, you should check theCopy host CPU configuration
and in theTopology
section. There are three options:- Sockets: consider it as the number of physical CPUs, most of the time Windows will support NO MORE THAN 2. I always set this to 1. - Cores: this is the number of physical cores in one CPU. - Threads: this is the number of threads in one physical core.
If the virt-manager don’t get this topology right, you can always set them manually. In my laptop, I set them as 1-3-2, which means 1 CPU, with 3 cores and each core has 2 threads. These will take 6 cores(including hyperthreaded ones) in my host machine.
Add the VirtIO dirver(iso file) into your VM. You can choose
Add Hardware -> Storage -> Select or Create custom storage
remember to set thedevice type
toCDROME device
. If you want to use VirtIO disk for your VM, then you must add this driver image so that Windows can grab it during the installation. Otherwise, you can add this and update the virtIO driver after the windows installation is finished.In
Display Spice
, make sure it’s set to Spice not VNC.In
Video QXL
, make sure the model is QXL and set the RAM up to 64MB if you want high-resolution display(like 4K). For this you’ll have to edit the XML template:- In virt-manager panel, choose
Edit -> Preference -> Enable XML editing
. - In
Video QXL
, go toXML
tab and change vgamem value from 16384 to 65536.
- In virt-manager panel, choose
Add a “Watchdog” device with action
Gracefully shutdown the guest
.(Settings suggested by others) Under “SATA Disk 1” open the Advanced options and change Disk bus to VirtIO, and optionally change Cache mode to “writeback”.
- Writeback means that when the Windows VM makes a write to disk, the host OS will cache this write in memory and tell the VM that the write is complete, before the write is saved to the host HDD. This is dangerous because it can corrupt the Windows VM if there is an incomplete write, but is faster than the default settings. If you never have a long running VM and take backups ofthen, then you can use writeback.
(Settings suggested by others) Under “NIC” change device model to virtio.(Personally, I use the default
e1000e
.)(Settings suggested by others) Add hardware again and add an “Input” device with type EvTouch USB Graphics Tablet.
(Settings suggested by others) Add hardware and add a “Channel” with name
org.qemu.guest_agent.0
. Leave the other settings as a default.
After these configuration, you can choose
Begin Installation
at the top of the setting panel. The focus point may be grabbed by the VM window, you can useCtrl(Left) + Alt(Left)
to get the focus back to the host machine so you can move the mouse, etc. Also it’s possible you end up in a
UEFI Interactive Shell
, normally just typeexit
since you won’t be using any start up script. Then you’ll probably be prompted to a UEFI management page, just hit
Continue
if you don’t need to any modification.If you want to use the VirtIO driver, then during the windows installation, you have to choose to load the
additianl drivers
. Also, you should enablenon-compatible drivers
to see those VirtIO drivers. Besides that, the installation is just like a bare metal one.Normally the installed VM will have display 800*600, which can be changed after you install the VirtIO driver. After the first installation, you can go to
device manager
and find there are some unknown devices. You can chooseupdate driver -> browse my compute -> choose VirtIO driver disk -> include subfolder
to update the drivers. Normally there are four VirtIO devices (Ethernet, SCSI Controller, Balloon, and Serial).You can also iterate through the VirtIO driver disk folder by folder to intall the drivers. Remember to choose the
w10
(windows 10) folder, and choose the architecture according to your guest system. You navagate through the main driver folder, then w10, and then find the file with the type “Setup Information” - it should be a file with a gear icon. Right click on this and then click “Install”. An installer window will pop up and you just click through it. Some recommended ones are:- guest-agent: the QUME guest agent, to resize the guest screen
- virtio-win-guest-tools: VirtIO windows guest tools
- virtio-win-gt: a driver installation wizard
(Optional) Desktop integration.
With the VM open, open the menubar on the host and go to View -> Scale Display -> and check the box “Auto resize VW with window”. You will now be able to resize the VM window to any size and the Windows Desktop will automatically fit the window. This really helps to make Windows 10 feel like an application.
You can also create the file
~/.local/share/applications/windows.desktop
with the following content:[Desktop Entry] Version=1.0 Name=Windows 10 Comment=Starts the Windows 10 VM Exec=bash -c 'virsh start Windows10 && virt-viewer --wait -c qemu:///system Windows10 && virsh shutdown Windows10' Icon=windows Type=Application
In the
Exec
section, replaceWindows10
with the name of your VM in virt-manager.After logging out and back in, you will now have Windows 10 as an “application” that you can run from your launcher (Unity or Gnome Shell or whatever it is). If you shutdown the VM, the window will automatically close, and if you close the window without shutting down the VM, the Windows VM will safely shutdown in the background. This saves you from having to go into virt-manager to start your VM.
(Optional) Performance tuing:
Disable Fast Startup
Disable Hiberfil.sys:
Open a Windows command prompt as an administrator and enter this command:
powercfg -h off
Reboot your VM and the hiberfil.sys file should no longer remain (this step may not be necessary for certain versions of Windows).
Disable Windows Indexing:
- Open a
Run
window(win + R) and typeservices.msc
inside, then press Enter. - Right-click the Windows Search service from the next window and then click Stop.
- Double-click the Windows Search item from the list and in the next window, change the Startup type to Disabled.
- Open a
Disable Automatic Disk Defragmenting:
- Use Windows Explorer to browse to where you can see the C: drive, then right-click on the device and select Properties.
- Click on the Tools tab at the top, then click Optimize.
- Click on the Change settings button.
- UNCHECK Run on a schedule from the next window.
Enable High Performance Power Mode
CPU topology finetune: On the host system, you can use
lscpu
to check the details of your CPU. On myi7-8565U
laptop, it outputslscpu -ae # below are the output #CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ # 0 0 0 0 0:0:0:0 yes 4600.0000 400.0000 # 1 0 0 1 1:1:1:0 yes 4600.0000 400.0000 # 2 0 0 2 2:2:2:0 yes 4600.0000 400.0000 # 3 0 0 3 3:3:3:0 yes 4600.0000 400.0000 # 4 0 0 0 0:0:0:0 yes 4600.0000 400.0000 # 5 0 0 1 1:1:1:0 yes 4600.0000 400.0000 # 6 0 0 2 2:2:2:0 yes 4600.0000 400.0000 # 7 0 0 3 3:3:3:0 yes 4600.0000 400.0000
Pay attention to
CPU
,NODE
,SOCKET
andCORE
columns. One can see theCPU0
andCPU4
in my machine comes from the same physicalCORE
. Naturally, it’s better to assign cpu from the same cores to the guest system. Especially for AMD Ryzen CPUs, it’s better the assign cores from the same CCX to the guest system.
After the<vcpu></vpu>
section in the XML you can manually add a<cputune></cputune>
section which looks like<vcpu placement="static">6</vcpu> <cputune> <vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='2'/> <vcpupin vcpu='2' cpuset='3'/> <vcpupin vcpu='3' cpuset='5'/> <vcpupin vcpu='4' cpuset='6'/> <vcpupin vcpu='5' cpuset='7'/> </cputune>
Here
vcpu
means virtual CPU andcpuset
represents where you want to set it to the host CPU. One can see I’m reserving physicalCORE 0
for the host machine.iothread
: to be added. One can check Arch wiki about OVMF performance tuning and A useful blog postCPU model information: by default,
virt-manager
uses predefinedhost-model
information for the guest system. At the<cpu>
section of the XML, it may look like<cpu mode="host-model" check="none"> <topology sockets="1" cores="3" threads="2"/> </cpu>
For
QEMU
3.1 and above, one can use the modehost-passthrough
instead of thehost-model
.BSOD for Windows 10 later than 1803 – “System Thread exception not handled”:
Add theignore_msrs=1
to eitherkernel paramter
ofmodprobe
. Therefore, it’s eitherkvm.ignore_msrs=1
in
GRUB_CMDLINE_LINUX_DEFAULT
of file/etc/default/grub
. oroptions kvm ignore_msrs=1
in a
kvm.conf
file located under/etc/modprobe.d/
. More details of this type of setting can be found in [this blog post about device passthrough](/post/device-passthrough-in-kvm/).
Enable Hibernation. It’s possible in the windows guest VM there aren’t any hibernation nor fast startup option in the power setting menu. If you run
powercfg /a
in an administrative command line, it will prompt to you that these different power states are not available. If you want to enable them,Edit or add the following settings in to your VM’s XML, at the
<pm> </pm>
section<suspend-to-disk enabled='yes'/> <suspend-to-mem enabled='yes'/>
For hibernate from host, you shoudl install the qemu guest agent in Windows guest like mentioned before.
For hibernate from host, you need to add a qemu-ga “channel” to your VM like mentioned before.
Enable hibernate in your windows guest VM by
powercfg.exe /hibernate on
This should be run in a command line with administrative privillege.
You can send hibernate through host using
virsh
virsh dompmsuspend disk <vm name>
Passthrough
In my personal use case, there are mainly two types of device passthrough
- USB device passthrough/redirection
- PCIE device passthrough
For USB device, you can use the host device redirection
to add the host USB device
to your VM. But if you want something like USB hot-plug in your VM, then you have
to passthrough a USB controller to your VM. We will talk about more details in [a different guide](/post/device-passthrough-in-kvm/).