# Setting up virtualization & virtual machines You will probably be required to use virtual machines during some classes. The procedure to getting them set up is pretty straightforward, but I will summarize them here anyway. As usual, these instructions were written and tested on arch linux. The process should be fairly similar on other distributions, but some might have everything set up already, and some may not support virtualization at all. ## Making sure KVM works KVM is the foundation for virtualization on linux. It allows running performant VMs close to hardware, with support built-in directly in the kernel. ### Check for basic kernel support First of all, your CPU needs to support virtualization. Let's check it with the following command: `LC_ALL=C.UTF-8 lscpu | grep Virtualization` If it outputs the following, your CPU supports virtualization: ```bash Virtualization: VT-x ``` Note that you might need to enable virtualization support in your BIOS/EUFI firmware settings. Now we need to make sure the necessary kernel modules are available. `zgrep CONFIG_KVM= /proc/config.gz` The module is available only if it is set to either `y` or `m`. Now we need to make sure the modules are automatically loaded as well. `lsmod | grep kvm` If the command returns nothing, you need to manually load the modules. There is a great article on this in the [arch wiki](https://wiki.archlinux.org/title/Kernel_module#Manual_module_handling). ## Installing QEMU QEMU is also part of the virtualization chain. It uses KVM as a hypervisor and manages machines behind the scenes. It allow guests to execute code directly on the CPU without extra translation layers to achieve near-native performance. (better than hyper-v on windows). You have a few different options for installing qemu. There is three main packages: `qemu-full`, `qemu-base` and `qemu-desktop`. I won't go through their differenes here, but to save time we will use `qemu-full`: `sudo pacman -S qemu-full` You can also install additional packages for additional hardware support, just to be safe: `sudo pacman -S samba qemu-block-gluster qemu-block-iscsi qemu-user-static` With this, you should be done (with QEMU). If you need to emulate for other architectures, you need to install separate packages for those. See the [QEMU arch wiki article](https://wiki.archlinux.org/title/QEMU) for more information. ## Installing libvirt Now we need to install libvirt, which will provide us with an easy way to manage the virtual machines. Start by installing the `libvirt` package: `sudo pacman -S libvirt` Then we need to install some packages in order for networking to function properly: `sudo pacman -S iptables-nft dnsmasq` If it complains about conflicts, you should be able to replace the old package without any issues, unless you have manually made some special complicated network config. Now edit `/etc/libvirt/network.conf` and change this line: ``` firewall_backend="iptables" ``` Note: If you are using firewalld, as of libvirt 5.1.0 and firewalld 0.7.0 you no longer need to change the firewall backend to iptables. libvirt now installs a zone called 'libvirt' in firewalld and manages its required network rules there. Now we have to install a GUI client to actually do the managing of virtual machines. `sudo pacman -S virt-manager` ### Setting up authorization Your user must have permission to use libvirt. This is to avoid having the enter your password all the time just to use a virtual machine. If for some reason you want to use policy kit or similar for authentication and enter your password all the time, instructions can be found [here](https://wiki.archlinux.org/title/Libvirt#Set_up_authentication). What we will do instead is add your user to the `libvirt` group: `sudo usermod -a -G $USER libvirt` ### Starting the daemon All you need to do to enable the daemon (and thus libvirt) is run the following command: `sudo systemctl enable --now libvirtd.service` And that's it! You should now be able to create and use virtual machines. ### Testing the installation Let's test if the installation works correctly. system-level: `virsh -c qemu:///system` It should open an interactive prompt. If it does, good. You can exit it with CTRL+C. user-level: `virsh -c qemu:///session` Same thing here, it should open a prompt and you can exit it with CTRL+C. If it doesn't work, it could be a due to a load of different issues. You will have to go researching on your own. Here are some articles to help: [Libvirt - archwiki](https://wiki.archlinux.org/title/Libvirt) [QEMU - archwiki](https://wiki.archlinux.org/title/QEMU) [KVM - archwiki](https://wiki.archlinux.org/title/KVM) Good luck! ## Creating a Windows VM Sometimes windows VMs might require some extra tinkering to work properly. Most of the time they will run out of the box, but have frequent crashes/freezes due to things like CPU configuration. Here are some tinkering steps to prevent that. ### 1: Create the VM The first step is to actually create the VM. If you have already created a VM but is having issues with it, it is recommended to delete it and start from scratch while following these instructions. 1. Open virt-manager and create a new VM. Use ISO media and select the windows ISO. 2. Make sure virt-manager detects the correct operating system, such as `Microsoft Windows 10`. If not, set it to the correct type. 3. Continue forward and set the amount of memory and CPU you want for this machine. We will modify these options a bit more later on. 4. Move to the next step and create a disk image for storage. This is pretty straight forward in the virt-manager interface, but if you need help, google it. Please note that this image cannot easily be expanded later, and you should set a size that is "big enough". If you want to run bare windows, 50GB should generally be fine. 5. In the final step you need to set the name of your VM. Remember that you should always avoid spaces in naming, it is inproper to use spaces. ### 2: Configuration We need to change some configuration options in order for our windows machine to run smoothly. This configuration dialog can be found in the virtual machine window (open it by right-clicking the VM in the list and clicking `open`). Just click the lamp icon instead of the monitor icon. ![open config dialog](image-1.png) #### CPUs Navigate to the `CPUs` option in the hardware list. Check "*Copy host CPU configuration*". Make sure that virt-manager got your CPU topology right. It will be in grayed-out boxes under "*Topology*". If not, check "*Manually set CPU topology*" and configure it to be as close to your physical CPU architecture as possible. The most important one is "*Sockets*" and that "*Cores*" doesn't exceed your amount of physical cores. Leaving "*Threads*" at 1 is generally fine. Don't forget to click `Apply`. ![cpu gui config](image.png) #### OPTIONAL: Adding VirtIO drivers. You can optionally add VirtIO drivers as a CD-ROM device into your VM. This will allow you to install the drivers into the VM when it's running, which in turn will enable you to use VirtIO devices. First, get the ISO for the VirtIO drivers. Instructions can be found [here](https://pve.proxmox.com/wiki/Windows_VirtIO_Drivers). Choose `Add Hardware -> Storage -> Select or Create custom storage`, remember to set the `device type` to `CDROME device`. Then add the driver image ISO so that windows can grab it during installation. If you have already installed windows and decided to read through these instructions anyway, you can open the device and run the installer manually just fine. If you choose to install drivers during windows installation, you have to choose "*additional drivers*" during installation, and might have to enable "*non-compatible drivers*" to see them. #### Video / display 1. In `Display Spice`, make sure it's set to Spice and not VNC. 2. In `Video QXL`, make sure the model is QXL. 3. Enable XML editing: In virt-manager panel, choose `Edit -> Preference -> Enable XML editing`. 4. Back in `Video QXL`, go to the "*XML*" tab and change the `vgamem` value under the `model` entry from "*16384*" to "*65536*". Don't forget to click `Apply`. #### Watchdog Look in your hardware list for a `Watchdog` device. If there is none, add it. You can leave "*Model*" as the default value. Change "*Action*" to `Gracefully shutdown the guest`. Click `Apply`. #### Advanced CPU configuration We need to do some further CPU configs. This might be the most important step to avoid random freezes so make sure you follow along closely. 1. Navigate to `CPUs` again and open the "*XML*" tab. 2. Find the `cpu` block and change the opening tag to the following: ```xml ``` 3. Add a feature tag inside the CPU block with the following content: ```xml ``` 4. OPTIONAL: If you later continue to experience issue, considering adding this inside CPU as well: ```xml ``` 5. Make sure the CPU configuration looks correct, the final result should look something like this: ```xml ``` 6. In the same XML file, find the `features` block. 7. Inside the features block, you should add this: ```xml ``` Make sure to add it to the bottom of the block. 8. Make sure this section of the config is correct, the final result might look something like this: ```xml ``` ### 3: OPTIONAL: More configuration If you are still having issues after making these changes, there are some other things you can try. First, make sure you did a full shutdown of the VM after making these changes. If you did that and still have issues, continue reading. #### Disk space Too little disk space is a common issue, especially with windows VMs. Make sure you gave the VM enough storage to operate, and that your machine actually has that storage available. In my experience it's fine to use up some of that storage elsewhere on your machine after creating the VM, as long as the VM doesn't need it. #### VirtIO drivers. If you have any of your hardware devices configured as VirtIO, make sure you installed the drivers. If you are able to, it might be worth installing the drivers anyway. #### Disk config Under `SATA Disk 1`, you can open the "*Advanced options*" and set "*Disk bus*" to `VirtIO`. Note that this requires VirtIO drivers to be installed on the VM. If you have performance issues, you can also try changing the cache mode to "*writeback*". Note that this makes your VM more prone to write errors. #### NIC config If you are having issues that you think might be caused by the virtual network card, you can try changing the "*Device model*". The default is `e1000e`, which is what I'm using without issues. However if you have the VirtIO drivers installed, you can give that a shot. If you know what you're doing you can also try changing the "*Network source*". #### Add a "channel" Add new hardware of type "*Channel*" with name "*org.qemu.guest_agent.0*". Leave the other settings as default #### Fun fact That's all, it should be working just fine now. Also, there is quite a big chance that you will get better performance with this VM on linux than you would on windows! This is thanks to KVM/QEMU/VirtIO allowing VMs to execute code almost directly on the physical hardware (if configured to do so). "When used as a virtualizer, QEMU achieves near native performances by executing the guest code directly on the host CPU. " - archwiki