Installing / Setup Steps
This is a quick guide on how to install Windows 10 on your QEMU-KVM setup. Make sure you followed the previous guide QEMU-KVM on Arch Linux Guide.
First I will provide you with a generic script. You can use this and most likely it will cover your needs.
#!/bin/bash # QEMU name and PID OPTS="-name windows-10-pro" OPTS="$OPTS -pidfile /tmp/windows-10-pro.pid" # Processor (4 cores with 2 threads) OPTS="$OPTS -cpu host,topoext,host-cache-info=on,kvm=off,check,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,hv_stimer,hv_synic,hv_vpindex,hv_vendor_id=whatever,-hypervisor" OPTS="$OPTS -smp 8,sockets=1,cores=4,threads=2" # Machine OPTS="$OPTS -machine type=pc-q35-3.1,accel=kvm,kernel_irqchip=on" # The following setting enables S3 (suspend to RAM). OVMF supports S3 # suspend/resume. Disable when using Q35 OPTS="$OPTS -global PIIX4_PM.disable_s3=0" # Memory (assumes you use hugepages!) OPTS="$OPTS -m 8G" OPTS="$OPTS -mem-path /dev/hugepages" OPTS="$OPTS -mem-prealloc" OPTS="$OPTS -balloon none" # Hardware clock OPTS="$OPTS -rtc base=localtime" # Sound hardware # If you use Qemu 3.x.x #QEMU_ALSA_DAC_BUFFER_SIZE=512 #QEMU_ALSA_DAC_PERIOD_SIZE=170 #QEMU_AUDIO_DRV=alsa #OPTS="$OPTS -device ich9-intel-hda,bus=pcie.0,addr=1b.0,id=sound0 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0" # If you use Qemu 4.x.x, 5.x.x OPTS="$OPTS -device ich9-intel-hda,bus=pcie.0,addr=0x1b" OPTS="$OPTS -device hda-micro,audiodev=hda" OPTS="$OPTS -audiodev pa,id=hda,server=unix:/tmp/pulse-socket" # Graphic card passthrough (Gigabyte GeForce GTX 980 G1 Gaming) OPTS="$OPTS -device vfio-pci,host=02:00.0,multifunction=on" OPTS="$OPTS -device vfio-pci,host=02:00.1" # USB 3.0 passthrough (NEC/Renesas) #OPTS="$OPTS -device vfio-pci,host=03:00.0" # Keyboard layout OPTS="$OPTS -k en-us" # Boot priority OPTS="$OPTS -boot order=c" # OVMF cp /usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd /home/tanasaki/qemu/VMs/windows10/my_vars.fd OPTS="$OPTS -drive if=pflash,format=raw,readonly,file=/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd" OPTS="$OPTS -drive if=pflash,format=raw,file=/home/tanasaki/qemu/VMs/windows10/my_vars.fd" # System drive OPTS="$OPTS -drive id=disk0,if=none,cache=unsafe,format=raw,file=/home/tanasaki/qemu/VMs/windows10/windows10.img" OPTS="$OPTS -device driver=virtio-scsi-pci,id=scsi0" OPTS="$OPTS -device scsi-hd,drive=disk0" # Other drive #OPTS="$OPTS -drive id=disk1,if=none,cache=none,aio=native,format=raw,file=/dev/disk/by-id/ata-Hitachi_HDS721050CLA660_JP1570FR1ZWP7K" #OPTS="$OPTS -device driver=virtio-scsi-pci,id=scsi1" #OPTS="$OPTS -device scsi-hd,drive=disk1" # Other drive 2 #OPTS="$OPTS -drive id=disk2,if=none,cache=none,aio=native,format=raw,file=/dev/disk/by-id/ata-Hitachi_HDS5C3020ALA632_ML0220F30NX2DD" #OPTS="$OPTS -device driver=virtio-scsi-pci,id=scsi2" #OPTS="$OPTS -device scsi-hd,drive=disk2" # Windows 10 Pro installer OPTS="$OPTS -drive id=cd0,if=none,format=raw,readonly,file=/home/tanasaki/qemu/OS_ISOs/Windows10/Windows10.iso" OPTS="$OPTS -device driver=ide-cd,bus=ide.0,drive=cd0" # Virtio driver OPTS="$OPTS -drive id=virtiocd,if=none,format=raw,file=/home/tanasaki/qemu/OS_ISOs/virtio-win.iso" OPTS="$OPTS -device driver=ide-cd,bus=ide.1,drive=virtiocd" # OVMF emits a number of info / debug messages to the QEMU debug console, at # ioport 0x402. We configure qemu so that the debug console is indeed # available at that ioport. We redirect the host side of the debug console to # a file. #OPTS="$OPTS -global isa-debugcon.iobase=0x402 -debugcon file:/tmp/windows_10_pro.ovmf.log" # QEMU accepts various commands and queries from the user on the monitor # interface. Connect the monitor with the qemu process's standard input and # output. #OPTS="$OPTS -monitor stdio" # A USB tablet device in the guest allows for accurate pointer tracking # between the host and the guest. #OPTS="$OPTS -device piix3-usb-uhci -device usb-tablet" # Network #OPTS="$OPTS -netdev tap,vhost=on,ifname=$VM,script=/usr/local/bin/vm_ifup_brlan,id=brlan" #OPTS="$OPTS -device virtio-net-pci,mac=52:54:00:xx:xx:xx,netdev=brlan" # Disable display. Use '-vga none' if you use GPU-passthrough OPTS="$OPTS -vga none" #OPTS="$OPTS -vga qxl" #OPTS="$OPTS -serial null" #OPTS="$OPTS -parallel null" #OPTS="$OPTS -monitor none" #OPTS="$OPTS -display none" #OPTS="$OPTS -daemonize" # QEMU Guest Agent #OPTS="$OPTS -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0" #OPTS="$OPTS -device virtio-serial" #OPTS="$OPTS -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0" sudo taskset -c 0-7 qemu-system-x86_64 $OPTS
If you have downloaded this already, you can skip this step.
Download VirtIO drivers from Red Hat
Since we will be using the vfio-pci and in order for Windows to discover our (virtual) hard drive, we need to download the VirtIO drivers from Red Hat.
Choose the folder you want to download the files to and then, download stable
and also the latest:
wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/virtio-win.iso -O virtio-win-latest.iso
The “Latest virtio-win iso” has drivers for Windows 10. We are also downloading the stable version, because it might happen that the “latest” version will give you errors during installation. You have to experiment with that.
Create a new container (disk)
qemu-img create -f qcow2 -o preallocation=metadata,compat=1.1,lazy_refcounts=on windows10.img 200G
Modify the script
Now modify the first script to match
- location of the Windows 10 install ISO
- location of your container
- location of the VirtIO drivers ISO
- Do you want to create a bridged network? Follow this guide!
USE ABSOLUTE PATHS! NOT RELATIVE ONES! 🙂
Important Remark: Since we are using vfio-pci the virtual system drive will not be visible during installation, which is normal. To make the drive visible, you need to install the VirtIO drivers from the
virtio-win.iso you downloaded earlier.
Well, basically you can save this script wherever you want as long as all paths from the above section are correct. You need make it executable with chmod +x and later run it as root.
Setting up huge pages
Hugepages is a mechanism that allows the Linux kernel to utilize the multiple page size capabilities of modern hardware architectures. Linux uses pages as the basic unit of memory, where physical memory is partitioned and accessed using the basic page unit. The default page size is 4096 Bytes in the x86 architecture.
First you need to know how much memory you will assign to all guests in total. Lets suppose that you have 16GB of ram in you system and you are allocating up to 12GB to your guests, leaving 4GB for the host. The standard huge page size is 2048kB – 2MB, so for 12GB hugepages we calculate: 12 * 1024 / 2 = 6144
First we need to check if we have the directory /dev/hugepages . If not, create it. Now, we need the right permissions to use this directory.
Add to your /etc/fstab:
hugetlbfs /dev/hugepages hugetlbfs mode=1770,gid=78 0 0
Of course the gid must match that of the kvm group. The mode of 1770 allows anyone in the group to create files but not unlink or rename each other’s files. Make sure /dev/hugepages is mounted properly:
sudo umount /dev/hugepages && sudo mount /dev/hugepages
and check result:
> mount | grep huge hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,mode=1770,gid=78)
Now we allocate the amount of needed huge pages:
sudo sysctl vm.nr_hugepages=6144
and to make it permanent:
echo 'vm.nr_hugepages=6144' | sudo tee -a /etc/sysctl.d/10-kvm.conf
Verify that the correct amount of huge pages has been allocated:
cat /proc/meminfo | grep HugePages_Total
If it shows less than the amount we have tried to allocate, the memory is allocated by other processes already and you need to reboot your system.
- Your windows installation does hand at 2% and does not move on?
– Try using a different version of the VirtIO drivers. In my case I used the stable version and installed drivers for Windows 8.1
- Your windows installation gives an error at 36%?
– It related to this. Just format the primary drive partition before installing the OS OR simply close the installation and re-run it!
- Combinations of -cpu and -machine that worked for me:
-cpu qemu64 && -machine type=pc-i440fx-2.1
-cpu host && -machine type=q35
- Qemu 4.0.0 issues
- Pulseaudio issue:
pulseaudio: pa_context_connect() failed pulseaudio: Reason: Connection refused pulseaudio: Failed to initialize PA contextaudio: Could not init 'pa' audio driver
/etc/pulse/default.paand add the following two lines:
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 load-module module-native-protocol-unix auth-anonymous=1 socket=/tmp/pulse-socket