Recover a Lost or Missing Commit in Git

Recover a Lost or Missing Commit in Git

If you have ever lost a commit in Git, don’t worry there might be still a chance to recover it. For example I encountered a problem with Git, when I was pushing my commit to the remote server. For some reason my Git client had some error when sending the commit to the remote server. So the commit didn’t go through and the Git client deleted all my local modifications from my local machine. So I couldn’t try to send the commit again (as Git said there’s no modifications / commit to send). Basically it reset all my files to the state that they were when I last time made a successful commit to the server. Fortunately I found a way to dig up the lost commit and modifications that I have made with git reflog. Go inside your project folder, and then run the following:

git reflog

Now you should see a log of what has happened in your local repository. Every action that you have taken in your local repository (in your your local computer) should have an ID and what kind of action is it. So for example I found my lost commit few rows below in the log. The lost commit is in a form of “db123456 HEAD commit: your commit message”. Write down the ID string (in my example it’s the 8 characters long string “db123456”). Before we try to recover the lost commit, you should backup your project folder just in case, if something goes wrong or you need to try recovering again.


We will next reset the local git repository. Remember it will delete any modifications that you have made after the lost commit. So if you have multiple missing commits, then you should maybe try to recover them one by one. That’s why I recommend backup your project folder before recovering. To get back your missing commit, run the following command (remember to replace the ID with your ID that you have written down):

git reset --hard db123456

Now hopefully you should have recovered your lost commit.


Game development in Linux

How to install Unity game engine and Rider IDE in Pop OS / Ubuntu

How to install Unity game engine and Rider IDE in Pop OS / Ubuntu

This is a quick guide how to install Unity game engine and Jetbrain’s Rider IDE and necessary dependencies. First we will start from installing Mono (the open source implementation of .NET framework), as otherwise the Rider can’t work correctly. The installation process differs a bit from which Linux distro you are using and which version. You can see the install instructions here:


For example for distros that are based on Ubuntu 20.04 (like Pop OS 20.04), you can install Mono with the following commands:

sudo apt install gnupg ca-certificates
sudo apt-key adv –keyserver hkp:// –recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo “deb stable-focal main” | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
sudo apt update
sudo apt install mono-devel


Next we will install Rider. There’s two different ways to install Rider. One way is to download from their web-site ( or download through Snap package manager. I will be using the Snap package manager way. For Pop OS, we need to install Snap package manager, as it doesn’t come with it by default. Ubuntu users can skip this step.

sudo apt install snapd


Then we will install Rider

sudo snap install rider --classic


This step is optional. The Unity Hub is distributed as an AppImage, but due to the nature of AppImage (as it more like an isolated image that you run), the Unity Hub might not integrate that well to your system. For example I noticed as I use Planck dock to start my apps, I had troubles to add the Unity Hub to the dock permanently. But I found a solution: to use AppImageLauncher ( Depending of your needs this step isn’t mandatory, but for example if you experience any problems with Unity Hub and Planck dock, I can recommend this one. You can install AppImageLauncher with the following commands:

sudo add-apt-repository ppa:appimagelauncher-team/stable
sudo apt update
sudo apt install appimagelauncher

Next we will install Unity. Head to and download the Unity Hub to a folder that you want to run it from. Then with shell to that folder and run the following command (to allow the UnityHub.AppImage to run):

chmod +x UnityHub.AppImage


If you installed the optional AppImageLauncher, right click the UnityHub.AppImage as choose run with AppImageLauncher. The AppImageLaucher should no pop up and ask, if you want to integrate the UnityHub to the system.

After you have started Unity Hub, recover your license, and download the Unity version that you want. 

NOTE: Before you can add an older Unity project to Unity Hub, you have to create a new project first. For some reason there’s currently a bug that the add project button doesn’t work until you have created at least one new Unity project. After that you can add your previous Unity projects in Unity Hub.

NOTE: If you want to install a specific version of Unity (not the latest one), unfortunately the Unity Hub links in Unity download archive don’t work currently in Linux. But there’s fortunately a workaround for this problem: Go to Unity download archive ( and go to the Unity version that you want, and right click on the Unity Hub download link, and choose copy link. The link should be in form of “unityhub://2021.1.16f1/5fa502fca597”.


Now with your shell, go to the folder where your UnityHub.AppImage is and run the following command (replace the link with the link that you copied before):

./UnityHub.AppImage unityhub://2021.1.16f1/5fa502fca597


The Unity Hub should now open and it should ask if you want to install that version.



Set double-click a ZIP archive file to automatically extract/unzip it in Windows 10

Set double-click a ZIP archive file to automatically extract/unzip it in Windows 10

If you are for example a long time user of a Mac, then you have probably got used extracting/unzipping ZIP-files (or RAR-files or other archive packages files) by just double-clicking the file. But in Windows, if you double-click an ZIP file, you will open an extract dialog window, where you have to confirm where you want to extract the ZIP archive. Or you can right click the ZIP file and choose the option “Extract Here” to extract it. But after using a Mac for many years, the double-clicking habbit has become basically a muscle memory for me unfortunately. In this article I will show quickly how to change this default behaviour of Windows with 7-Zip and some register changes.


First we will install 7-Zip ( and we will open the 7-Zip File Manager as an administrator. Then go to “Tools” -> “Options” and choose the file types that you want to 7-Zip to extract. For example I associated ZIP and RAR, as I mostly work with them. For both these file types, I associated both my user account and all accounts


Next we will run RegEdit run as an administrator. Locate the following key:



Then there should be a “shell” subfolder under the When you click the subfolder, you should see on the right side panel the key “(default)”. Double-click the “(default)”. And in the new dialog window write:



Next right click the “shell”-folder on the left side panel and create a new key. Give this name “extract”. And then select the new “extract” folder. And then double-click “(default)”. In the dialog window write “Extract to Folder”.

Extract to Folder


Finally select the “extract” folder on the left side panel. Then right click it and create a folder named “command”.Select the “command” folder. Then right click the “(default)”. And in that dialog window write:

C:\Program Files\7-Zip\7zG.exe x “%1” -o*


If your 7-Zip installation isn’t in the default path, then replace the path with your own.

If you assiociated other file formats than ZIPs at the beginning in 7-Zip File Manager, then you need to repeat the the register change for them also. You will find them in HKEY_CLASSES_ROOT/7-Zip.archivetype. So for example in my case I also chose RAR-files, so I will need to make changes also to HKEY_CLASSES_ROOT/7-Zip.rar



How to use package manager Winget, Apt or Homebrew

How to use package manager Winget, Apt or Homebrew

In this article I will quickly tell what a package manager is and list common package manager commands that you can use with Winget on Windows, Apt (Apt-Get) on Linux and Homebrew on Mac (an unofficial package manager for Mac). I won’t go through in-depth the differences of the different package manager and how they work in this article. If you need to go back and forth between different package managers or you aren’t familiar with one of the package manager listed here, you might find this article useful.

Those of you that don’t know what a package manager is (especially users from Windows): A package manager allows you to install new apps quickly through command line. So you don’t need to go to every app companies’ web-site to download their apps. Especially if you need to quickly install a lot of apps at once (for example you are reinstalling your computer). It’s also a centered approach to update all your apps. Recently Microsoft has released their own package manager called Winget. It isn’t still yet completely finished, but there’s already more apps available there than in Microsoft Store. You can install the new package manager for example from directly downloading from Microsoft’s github:

Search for apps:

How to search for an app if it is available in your package manager’s repositories:

# Winget
winget search appname
# Apt
apt search appname
# Homebrew
brew search appname


Installing apps:

Install an app:

# Winget
winget install appname
# Apt
apt install appname
# Homebrew
brew install appname


List all installed apps

List all installed apps. For Homebrew, this command will list all apps that you have listed through Homebrew (not the apps that you have installed through other ways). But for example Winget will list all the apps that are installed in your Windows (not just apps through Winget, so you will see for example Windows Updates there also). Because of this it might not be so useful to see quickly, if you have installed some app before. But you can use in “winget list appname”, to see if you have already installed the app or not.

# Winget
winget list
# Homebrew
brew list


List only a spesific app

If you don’t want the whole list of all the installed, you can also only list a specific app. For example if you just want to know, if some certain app is installed or not.

# Winget
winget list appname

# Homebrew (formulae)
brew list appname

# Homebrew (cask)
brew list --cask appname

Updating and upgrading apps (in Apt and Homebrew)

In Apt and in Homebrew you can easily update all your apps at the same time. But first you need to update your package manager’s database (so the package manager knows, if there’s an updates or not). After that you can run the upgrade command to install the updates. The package manager will during upgrade process show which packages will be updated, and you can cancel the update installation at that time, if you for example notice that you need some app to be on certain version.

# Apt update package database
apt update

# (Optional step) Apt list which packages can be upgraded
apt list --upgradeable

# Apt upgrade and install the new updates
apt upgrade

# Homebrew update package database
brew update

# (Optional step) Homebrew: list which packages can be upgraded
brew outdated

# Homebrew upgrade and install the new updates
brew upgrade


You can also upgrade and install an update to a certain app (if for some reason you want to update only one application).

# In Apt upgrade certain package and install the new update
apt --only-upgrade install appname 

# In Homebrew upgrade certain package and install the new update
brew upgrade appname

Updating and upgrading apps (in Winget)

As Winget is still in Beta, it has been reported that it might not be so good idea to upgrade all apps at once through Winget. The problem might be related that Winget itself list all apps that have been installed in your Windows (not just the applications that have been installed through Winget). For this reason, you should use Winget to update only apps that you have installed through Winget and one by one. With the following command you can update a specific app:

winget upgrade appname



To updates all apps in Winget at once, you can run the following command, but as stated before, Winget is currently in Beta and using the following command isn’t recommended:

winget upgrade -all




Virtual Machine

Resizing your virtual machine's IMG virtual disk image

Resizing your virtual machine's IMG virtual disk image

I recently wrote a guide about how to create your own VM under PopOS. In that guide, we created a virtual disk image (IMG) for the VM to install the Windows 10 on it. But if you later felt that maybe the virtual disk was too small, you can easily resize the virtual disk with one command. But first make a backup just in case something goes wrong. Then go to the folder where your VM IMG is and run the following command. Replace “win10” with your VM IMG name, and change “+256G” to how much new space you want to give tp your virtual disk, so in my example I will add 256GB new empty space to the current size of the virtual disk. When you run the command it might give you a warning, that’s why it’s good to have an backup.

qemu-img resize win10.img +256G


And after you have run the command, just boot up your VM, and for example in case of Windows 10, just go to Windows’ Disk Utility and expand your partition to cover the new empty space.

Virtual Machine

Windows 10 virtual machine on PopOS 20.04 with GPU passthrough

Windows 10 virtual machine on PopOS 20.04 with GPU passthrough

In this guide I will go through how I got Windows 10 to run on a virtual machine under PopOS 20.04 with GPU passthrough. I will passthrough a Nvidia RTX 2080 GPU on the first PCI-e slot of the motherboard to Windows 10. Here’s the whole specs of my system:

AMD Ryzen 3950X (later updated to 5950X)
Asrock X570 Creator motherboard (BIOS version: 3.30, AGESA version: AMD AGESA Combo-AM4 V2 patch D)
MSI RTX 2080 Sea Hawk EK X GPU (on the first PCI-e x16 slot, for Windows 10)
AMD Radeon VII GPU (on the second PCI-e x16 slot, for PopOS)

Inateck 2 port USB 3.0 PCI-E card (on the third PCI-e x4 slot for Windows 10)
PopOS 20.04 as host OS
Windows 10 as guest OS

USB on Windows 10

As you can see from the specs I will also passthrough an USB PCI-e card, as it can be quite difficult to passthrough any USB ports that are directly on your motherboard. For example I tried to passthrough some USB ports in my motherboard to Windows, but unfortunately it didn’t work or it resulted in hanging up the whole system. That’s why I would recommend getting a seperate USB PCI-e card. Other solution is to passthrough each USB device by device (instead of passthrough the whole USB port), but in that case when you want to passthrough a new USB device, you would need to then add that device to the list of devices that you want to be passed through. Second problem that you might encounter with this solution, is that if your USB device gets disconneted and reconnected again, the virtual machine might not find the USB device again until you restart the virtual machine. For example I have a hardware KVM which I use to switch my mouse and keyboard to different computers, in this case the seperate USB PCI-e card is much better solution.

Installing SSH server

My second recommendation would be to install SSH server on your PopOS. Especially if you are going to passthrough your GPU in the first PCI-e slot of your motherboard, as you might stumble to a problem that after you have backlisted the GPU and restarted your computer, PopOS can’t start X Server (basically meaning a blank screen with no graphical interface). We will talk about more how to solve this problem later, if you happen to encounter it. With an SSH server running, you can remote connect to your computer from another computer. To install SSH server run the following command:

sudo apt install openssh-server
Then I would just in case test that you can connect to the computer from another computer. By using the following command from the other computer (if you are using Linux or Mac on the other computer):
ssh your_username@your_ip_address

BIOS settings

You should first enable IOMMU in BIOS (IOMMU allows us to passthrough PCI-e devices). For example in my Asrock motherboard the setting can be found under: Advanced -> AMD CBS -> NBIO Common Settings -> IOMMU


You might also need to enable SR-IOV Support under Advanced -> PCI Configuration -> SR-IOV support. And you might need to enable CSM under Boot -> CSM (Compatibility Support Module) -> CSM

Installing Qemu and enabling IOMMU

First we will start by installing Qemu (handles the virtualization), Virt-manager (graphical interface for QEMU so we can set up the VM a bit more easier) and all the other needed software:

sudo apt install qemu-kvm qemu-utils virt-manager libvirt-daemon-system libvirt-clients bridge-utils ovmf

Enabling IOMMU for AMD CPUs:

sudo kernelstub -o "amd_iommu=on amd_iommu=pt"
Restart your computer.

Identifying PCI bus / device ids

Next we want to find out the PCI bus ids and device ids for the GPU and USB card that we want to passthrough:

lspci -nnv

This should print out a really long list of all the different devices in your computer. You need to look through this list and find your GPU and USB card. For example here’s my Nvidia card:

35:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104 [GeForce RTX 2080 Rev. A] [10de:1e87] 
(rev a1) (prog-if 00 [VGA controller])
Subsystem: Micro-Star International Co., Ltd. \[MSI\] TU104 \[GeForce RTX 2080 Rev. A\] \[1462:3728\]
Flags: fast devsel, IRQ 255
Memory at dc000000 (32-bit, non-prefetchable) \[size=16M\]
Memory at 90000000 (64-bit, prefetchable) \[size=256M\]
Memory at a0000000 (64-bit, prefetchable) \[size=32M\]
I/O ports at e000 \[size=128\]
Expansion ROM at dd000000 \[disabled\] \[size=512K\]
Kernel driver in use: vfio-pci
Kernel modules: nvidiafb, nouveau, nvidia\_drm, nvidia

35:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10f8] (rev a1)
Subsystem: Micro-Star International Co., Ltd. \[MSI\] Device \[1462:3728\]
Flags: fast devsel, IRQ 255
Memory at dd080000 (32-bit, non-prefetchable) \[disabled\] \[size=16K\]
Kernel driver in use: vfio-pci
Kernel modules: snd\_hda\_intel

35:00.2 USB controller [0c03]: NVIDIA Corporation Device [10de:1ad8] (rev a1) (prog-if 30 [XHCI])
Subsystem: Micro-Star International Co., Ltd. \[MSI\] Device \[1462:3728\]
Flags: fast devsel, IRQ 80
Memory at a2000000 (64-bit, prefetchable) \[size=256K\]
Memory at a2040000 (64-bit, prefetchable) \[size=64K\]
Kernel driver in use: xhci\_hcd

35:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device [10de:1ad9] (rev a1)
Subsystem: Micro-Star International Co., Ltd. \[MSI\] Device \[1462:3728\]
Flags: fast devsel, IRQ 255
Memory at dd084000 (32-bit, non-prefetchable) \[disabled\] \[size=4K\]
Kernel driver in use: vfio-pci
Kernel modules: i2c\_nvidia\_gpu

And here’s my USB card:

2b:00.0 USB controller [0c03]: Fresco Logic FL1100 USB 3.0 Host Controller [1b73:1100] (rev 10) (prog-if 30 [XHCI])
Subsystem: Fresco Logic FL1100 USB 3.0 Host Controller [1b73:1100]
Flags: fast devsel, IRQ 27
Memory at eaa00000 (64-bit, non-prefetchable) [size=64K]
Memory at eaa11000 (64-bit, non-prefetchable) [size=4K]
Memory at eaa10000 (64-bit, non-prefetchable) [size=4K]
Kernel driver in use: vfio-pci
Kernel modules: xhci_pci
All the different devices that are related to the GPU are listed consecutively, and they will belong to the same group (in my example: 35:00). You can see from the list that my GPU card has been listed four times: VGA compatible controller (video), Audio device (as most cards can output audio through HDMI/DisplayPort, so you will probably also have this one), USB controller (this might be a bit more rare as my Nvidia card has also an USB-C connector, so you might not have this entry), Serial bus controller. You should then write down the GPU’s PCI bus ids (35:00.0, 35:00.1, 35:00.2, 35:00.3), device ids (10de:1e87, 10de:10f8, 10de:1ad8, 10de:1ad9) and also what kind of device it is (VGA, Audio, USB and Serial Bus). For the device ids it is enough to write down only the ids that are listed on the title of each entry. For example I would write down on my VGA combatible controller only 10de:1e87 (don’t need the 1462:3728).

For my USB card , I would write down PCI bus id 2b:00.0 and device id 1b73:1100.

Blacklisting your GPU and USB card

Next we will blacklist our GPU that we want to passthrough to Windows. Before we blacklist the GPU, there’s few things you should know: The BIOS menu will still show up in the first GPU, but when Pop OS starts to load up, you will see video output only on the second GPU. Second thing is that you might not get any video output at all in PopOS, if the X Server fails to start, but don’t panic, we will fix that problem later. To blacklist our GPU and USB card, run the following command, but remember to replace with your own device ids:

sudo kernelstub --add-options "vfio-pci.ids=10de:1e87, 10de:10f8, 10de:1ad8, 10de:1ad9, 1b73:1100"
And if you happen to make a mistake, for example if you put wrong device ids, you can delete the changes with the following command (for example if I would want to delete the above changes from my kernelstub, I would use the following command):
sudo kernelstub --delete-options "vfio-pci.ids=10de:1e87, 10de:10f8, 10de:1ad8, 10de:1ad9, 1b73:1100"

Next we will run the following command (some certain Windows version require it):

sudo kernelstub --add-options "kvm.ignore_msrs=1"

Next we will disable the EFI/VESA framebuffer when the PopOS is booting (as otherwise the Pop OS will reserve the first GPU card, and then the GPU passthrough might not work):

sudo kernelstub --add-options "video=efifb:off"

Last the step before rebooting, is to blacklist the Nvidia/Nouveau drivers in PopOS, so the Nvidia drivers don’t try to initiliaze the GPU (and then the GPU passthrough would fail). Go to edit the following file (in my example I’m using Emacs to edit it):

sudo emacs /etc/modprobe.d/blacklist.conf

Add the following lines to the end of the file:

blacklist nvidia
blacklist nouveau

Finally reboot your computer. After rebooting your computer you can run the “ls -nnv” command again, and now you should see on your GPU and USB card devices that have “Kernel driver in use” as “vfio-pci” (except for the USB-C port that’s on the Nvidia GPU, if you  happen to have an USB-C port in your Nvidia GPU). For example for my VGA controller it would show the following:

35:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104 [GeForce RTX 2080 Rev. A] [10de:1e87] 
(rev a1) (prog-if 00 [VGA controller])
Subsystem: Micro-Star International Co., Ltd. \[MSI\] TU104 \[GeForce RTX 2080 Rev. A\] \[1462:3728\]
Flags: fast devsel, IRQ 255
Memory at dc000000 (32-bit, non-prefetchable) \[size=16M\]
Memory at 90000000 (64-bit, prefetchable) \[size=256M\]
Memory at a0000000 (64-bit, prefetchable) \[size=32M\]
I/O ports at e000 \[size=128\]
Expansion ROM at dd000000 \[disabled\] \[size=512K\]
Kernel driver in use: vfio-pci
Kernel modules: nvidiafb, nouveau, nvidia\_drm, nvidia

Problems after rebooting

If you didn’t have any problems after rebooting then you can skip this section. But if you have any problems after rebooting, like no video signal on your second GPU after PopOS has started to boot (no PopOS boot information and no login screen). Then you might need to have to edit your xorg.conf. If you encrypted your PopOS hard drive then after booting, wait a bit, and then input your encryption password blindly (even though you can’t see the input encryption screen). And then wait a bit again. And then try to SSH from another computer to your computer. Create xorg.conf.d folder under /etc/X11/

sudo mkdir /etc/X11/xorg.conf.d

Then create the 10-gpus.conf file to under that folder:

sudo emacs /etc/X11/xorg.conf.d/10-gpus.conf

And then add the following to the file (this applies to only AMD GPU):

# For AMD
Section "Device"
Identifier "AMD"
Driver "amdgpu"

Then disconnect SSH and reboot your computer. Hopefully now you can see PopOS booting and the encryption/login screen.


But if you can’t still see anything, then I would recommend to turn off the computer and then switch the GPUs’ places (so put the AMD GPU to the first slot and then Nvidia GPU to the second slot). You should then able to boot normally and you can then try to backtrack, if you missed anything.

Creating a virtual disk for the Windows VM

Now we will create a virtual disk for the Windows VM that will host our Windows VM install. There are different approaches for this (for example you could passthrough a whole NVMe SSD drive), but I have usually created just img-file. Maybe one advantage for this is that if you want to make a backup of the Windows install, then you just copy the img-file. Of course one disadvantage will be that the file size will be as big as the size of the virtual disk (even though you haven’t filled up your virtual disk). We can create a virtual disk with the following command. The 512G option means that the virtual disk will 512GB big. You can make the disk bigger or smaller as you want. The virtual disk can be made bigger later, if you find that you need more space (I will cover this one in a later post).

fallocate -l 512G win10.img

Download necessary files

Download Windows 10 installation ISO from Microsoft ( Then download Virtio drivers for the virtual disk, as otherwise Windows installer won’t recognize the virtual disk. The Virtio drivers can be found at (Download the stable-virtio version that has a version number on it and that ends with .iso). You can optionally download your GPU drivers and put them on a USB stick, if you prefer to install the GPU drivers without Windows automatic driver installation.


(Optional) Download vBIOS

This is an optional step as in new Nvidia drivers for Windows there shouldn’t be any problems running consumer Nvidia GPUs under VM. But in older Nvidia drivers, Nvidia blocked running consumer GPUs under VMs. Basically after you installed Nvidia drivers in Windows, the drivers wouldn’t load after reboot and Windows’ Device Manager would show Error 43 under the Nvidia GPU. You wouldn’t able to change resolution or use 3D accelaration. To counter the Error 43, we will provide a fresh copy of the GPU’s vBIOS. For example in my case as I will passthrough the GPU in the first PCI-e slot, when I start up my computer the BIOS will show up on Nvidia GPU (before the video output would move to my second GPU when the PopOS will start to load). At this point when the BIOS is loaded, the Nvidia GPU will be marked as initialized. But when I go to my VM side, and I start up my Windows VM, the Nvidia CPU would know that it has been initiliazed in another OS first (so it is running under a VM). And at this point the Nvidia drivers would block using the Nvidia GPU and not load the drivers.

This step doesn’t affect, if you use already new enough drivers (it will work with those too). But you can of course try first without doing this step and then come back if you encounter to the Error 43.

To fix Error 43, we will first download a copy of the GPU’s vBIOS from Find the exact GPU model that you are using and download its vBIOS (you can’t use another manufacturer’s or another version of vBIOS, it needs to be the same manufacturer and exactly the same model otherwise it can be harmful to your GPU). 

Then we create vgabios folder under usr/share folder (because usr/share folder is accessible for Qemu, for example if we put the vBIOS under our own home directory PopOS’ AppArmor security might block access to it):

sudo mkdir /usr/share/vgabios

Then we just go to the folder that has our donwloaded vBIOS and move it to the vgabios folder (for example my ROM-file is named MSI):

sudo cp MSI.rom /usr/share/vgabios/MSI.rom

We will add this vBIOS file later to the VM settings, when we get to that point.

Creating the VM in Virtio

After all the pre-configurations we are ready to create the VM in Virtio. Launch Virt-manager. And select File -> New Virtual Machine

From the new window select “Local install media (ISO image or CDROM”).

In the next window click “Browse”, then “Browse Local”, and then select the Windows installer ISO that you downloaded previously.

Next you can choose how much memory and CPUs (threads), you want to assign to your VM. Leave some threads and memory to Pop OS (don’t assign everything to Windows). For example I used 24 threads (so 12 cores) and 49152MiB.

Next we will assign the virtual disk where Windows will be installed that we created before hand. Select “Select or create custom storage” option, and then click “Manage”, then “Browse Local”, and then find your virtual disk. 

In the next window enable the “Customize configuration before install” option and hit Finish.

Now we will add the Virtio ISO that we downloaded previously. Click “Add Hardware”.

Choose “Storage”, and then as “Device Type” “CDROM device” and “Bus Type” as”SATA”. Click the “Manage”, and then “Browse Local”, and find the location where the Virtio ISO is.

Next we will add the GPU devices and the USB card that we want to passthrough. At the beginning of this guide we wrote down the PCI bus ids of the GPU and USB card. Click the “Add Hardware” again, then select “PCI Host Device”, and select the PCI bus id that you had written down before. And repeat this until you have added all the devices that you want to passthrough.

(Optional step) Depending on the Nvidia drivers, you might encounter Error 43 inside Windows. To avoid this we will give a fresh copy of CPU’s vBios that we downloaed earlierly to the VM. Select your VGA controller (in my case it’s the 0000:32:00:0). And go to the XML-tab and add the line “<rom bar=”on” file=”/usr/share/vgabios/MSI.rom”/>”. And click Apply. You don’t need to add the vBios to other deviced related to your GPU.

Installing Windows

Finally we are ready to start the VM. Optionally if you prefer to Windows not automatically install your GPU drivers, but install the drivers yourself, then you should now disable your network connection. Now we click the Run button to start the VM. And then the Monitor button to open the monitor tab. Because we don’t yet have any drivers, you might not get any video output through your GPU at this point. But don’t panic, we can see video output inside the monitor tab (of course this won’t be GPU accelerated, but this shouldn’t matter for the intallation process).

During the Windows installation you might notice that Windows can’t find a disk to install the OS. This is because we need to load the Virtio drivers that we donwloaded earlierly. Click “Load driver” and point to the Virtio disc. The drivers should be inside the “amd64/w10” folder. Now you should able to continue with the installation.

After Windows has finished installing, we can install the Nvidia drivers. Depending if you disabled your network connection, then you need to insert the USB stick with the GPU drivers and install from there. Or if you didn’t disable your network connection, then Windows should automatically recognize your GPU and install the correct drivers. After the drivers have finished installing, you should able to extend the desktop to the monitor that is connected to your GPU. You can disable the “virtual monitor” from Windows’ monitor settings. Or you can even delete the Spice Server/Screen in your VM settings to completely disable the “virtual monitor”.

Now you should have a Windows VM up and running! I hope that this guide has been helpful. If you notice that there’s some errors in the guide, or if you have encountered any problems, please leave a comment. I posted some problems that I have encountered myself below.


Slow upload speed with Dropbox

I noticed that some times I had really slow upload speeds in Dropbox some times for some reason. I haven’t yet found a reason why this happens when I use the shared ethernet connection. Currently I have passthrough the second Ethernet connection to the VM (as my motherboard has two Ethernet ports). And I haven’t noticed any slow down anymore.

VM not starting up

If for some reason, your VM doesn’t start, for example you get an error, but the error message isn’t that clear what’s the problem, then you can try to see Qemu’s log file (replace the “win10” with the name that you gave to your VM in Virt-manager):

sudo emacs /var/log/libvirt/qemu/win10.log

How to check what you have added to your kernelstub

If you want to check what you have added to your kernelstub, for example you have some problems with the VM and you want to double check, if everything is correct in the kernelstub. Or if you bought a new GPU, and you want to remove the old one, but you don’t remeber exactly what you have added to the kernelstub. You can quickly check with the following command:

cat /proc/cmdline

For example I get the following output (remember not to remove the initrd or root, as they relate which hard drive to use to boot your Pop OS):

initrd=\EFI\Pop_OS-********-****-****-****-************\initrd.img root=UUID=********-****-****-****-************ ro kvm.ignore_msrs=1 amd_iommu=on amd_iommu=pt video=efifb:off vfio-pci.ids=10de:1e87,10de:10f8,10de:1ad8,10de:1ad9,1b73:1100

Ignored rdmsr problem when booting PopOS

If you are booting your PopOS, but the bootup fails, and you get a black screen, and the following error message (the number values might be different for you):

[27.508658] kvm [2055]: ignored rdmsr: 0x48b data 0x0

This might be that the IOMMU and SR-IOV settings in your motherboard’s BIOS have been disabled (because of a BIOS reset). This might happen if you have updated your motherboard’s BIOS. Or for example if there has been some electric blackout during at the same time as you were using your computer and the computer then has shutdown incorrectly and caused a BIOS reset. So you should then check your BIOS settings that the IOMMU and SR-IOV are enabled (and that other settings are also correct).


-21. November 2021 added ignored rdmsr problem

Useful links and sources:


Prevent SSH session to a server from disconnecting

Prevent SSH session to a server from disconnecting

If you need to connect for example to a web server by using SSH, you might have encountered that sometimes the SSH session becomes unresponsive, because the connection has timed out and disconnected. This migth happen, if you haven’t typed anything in the terminal in a while (for example you reading some documentation at the same time). There’s an easy fix for that. We need to add the following to /etc/ssh/ssh_config file:

# Keep connection alive by sending a packet every 10 seconds
ServerAliveInterval 10



I found the following thread on StackExchange useful for fixing this problem.


Customizing your bash shell for better reading experience in terminal

Customizing your bash shell for better reading experience in terminal


If you are using a lot of  terminal / command line and bash shell, you might have experiences that some times it is bit difficult to read the terminal. For example in cases that you have long lists of texts and you print those lists several times, you might lose track, when one list ends and when another list starts as the text is all the same color.  As a solution we will add some color coding to the bash shell / terminal. Some bash shells / terminals will have this color coding enabled by default for example in some Linux distros. But for example in my bash shell under Mac OS we don’t have any color coding:

Before color coding

So let’s change that boring look to this one:

After color coding

To get this style of color coding, we create a .bash_profile file in our home directory for example with Emacs text editor. In the file we will add the following lines:

# You can comment in the file after hashtag and one empty space


# Enable color coding

export CLICOLOR=1


# With the next line we can customize which colors to use and how to for example show username, computer/host name
# and current folder. You can reorder the username, host name and current folder in any order you want. Or you can even
# leave some out, if you don’t need. But in my example I will order them as follow:
username @ host name : folder$


# \[\e[32m\] = Use green color

# \u = Username

# \h = Host name

# \W = Current folder

# \[\e[0m\] = Reset text color (so go back to using white color)

export PS1=”\[\e[32m\]\u@\h:\W$ \[\e[0m\]”


And if you aren’t happy with the green color, you can replace it with some other color:

\[\e[30m\]  = Black
\[\e[31m\]  = Red
\[\e[32m\]  = Green
\[\e[33m\]  = Yellow
\[\e[34m\]  = Blue
\[\e[35m\]  = Purple
\[\e[36m\]  = Cyan
\[\e[37m\]  = White

More Customizing:

If you want to customize even more, you can change the color of the folder, symbolic link, etc. So for example when you run the ls command to list what’s under the current directory, for example the folders would be in red colored text. If you want to do that you can add this following in the .bash_profile after the “export CLICOLOR=1”:

export LSCOLORS=ExFxBxDxCxegedabagacad

These values are read as a pair (for example “Ex”, “Fx”, “Bx”, etc). For example the first value in “Ex” (the value “E”) means that item’s text color should be bold blue. The second value “x” means default background color (so don’t change the background color). Here’s the order what each pair means, first will be the color of folder, second pair will be the color of symbolic link etc:

1 = folder
2 = symbolic link
3 = socket
4 = pipe
5 = executable
6 = block special
7 = character special
8 = executable with setuid bit set
9 = executable with setgid bit set
10 = directory writable to others, with sticky bit
11 = directory writable to others, without sticky bit

And here’s the color values:

a = black
b = red
c = green
d = brown
e = blue
f = magenta
g = cyan
h = light grey
A = bold black (might show as dark grey also)
B = bold red
C = bold green
D = bold brown (might show as yellow also)
E = bold blue
F = bold magenta
G = bold cyan
H = bold light grey
x = default text color / background


Articles that I have found useful myself when I was searching information how to customize bash shell. Thanks for these authors for writing these articles. I have quoted the color value and pair value lists from them.