26 August, 2018

DKVM - Desktop KVM In Action

DKVM - My only hypervisor

DKVM has been my only hypervisor for the last few weeks. My normal workstation has been moved into a VM (xubuntu), and when I feel like gaming - I can fire up my Windows 10 VM.

The boot-up time isn't that bad from a USB stick. As the DKVM OS is using a run-from-ram method, the performance once booted is excellent.


25 August, 2018

DKVM - Desktop KVM - Part 2

DKVM - Improvements

DKVM Menu

While several improvements has been pushed to my github repository for DKVM, the majority of the work has gone into a new menu-system

I decided to add BASH to my Alpine setup, and build a simple menu-structure using ncurses dialog for BASH.
The menu is far from complete, but currently is a usable state for me.



The add/edit menu options still needs a lot more work, and the internal structure could be a lot better.

The menu simply searches for "dkvm_vmconfig.*" files, and displays a simple menu with the found VMs.


Kernel 4.18.5


As I needed to rebuild the kernel anyway to get HUGETLBFS support, I decided to use the latest stable kernel. The easiest solution for me, was to clone the official AlpineLinux aport repository, and add the modifications to my own fork.
This enables me to easily keep up with the official fixes, while still preserving my own updated kernel with an updated kernel-config optimized for virtualization.
The DKVM buildsystem now has a "stage03" - which is compiling my updated kernel in a chrooted environment.

Build demo


As this is still mainly for my own use, and should be considered to be somewhere in the early alpha/development stages - making sense of the collection of shell-scripts can be troublesome.
So, I decided to record a video of the build-process - in case anyone wants to follow in the same footsteps.


23 July, 2018

ddccontrol - automatic change display input

ddccontrol - change display input


In my DKVM setup, I always use my 2nd graphicscard for my guests. Sadly my monitor does not have automatic input detection, so a little trickery is needed to switch input.

For my DKVM host OS, I use the DVI input.
For my VM guests, I use the DisplayPort input.

ddccontrol - probing

ddccontrol -p is used for probing the I2C bus for displays.
To find the information needed, first find the I2C bus for the display - it should look similar to this
In my case, my monitor is in dev:/dev/i2c-17


Finding the needed i2c address and values.

Still looking at the output from "ddccontrol -p", find a section like "Input settings"

In my case, the i2c address for setting inputsource is 0x60, and the accepted values are
15: DisplayPort
3:  DVI
4:  HDMI
1:  VGA


Writing to the i2c address

To set another display input, use the information gathered, and use "-w" to write
example : ddccontrol -r 0x60 -w 15 dev:/dev/i2c-17
This will set the input source to DisplayPort


Wrapping it up


In my case, I need to set the input to DisplayPort when my Linux guest is starting, and set it back to DVI when I am done.
While there are plenty of ways to run scripts in startup/shutdown, I opted for the easy solution - and just went with an old-fashioned OpenRC init style script, and placed symlinks to the different rc levels.

/etc/init.d/ddccontrol

 #!/bin/sh  
 case "$1" in  
      start)  
      /usr/bin/ddccontrol -r 0x60 -w 15 dev:/dev/i2c-17  
      ;;  
      stop)  
      /usr/bin/ddccontrol -r 0x60 -w 3 dev:/dev/i2c-17  
 esac  

And the required symlinks

 #!/bin/sh  
$ find /etc -iname "*ddccontrol" -exec ls -l {} \; 2>/dev/null
lrwxrwxrwx 1 root root 20 Jul 23 12:49 /etc/rc6.d/K99ddccontrol -> ../init.d/ddccontrol
lrwxrwxrwx 1 root root 20 Jul 23 12:52 /etc/rc0.d/K99ddccontrol -> ../init.d/ddccontrol
lrwxrwxrwx 1 root root 20 Jul 23 12:49 /etc/rc3.d/S01ddccontrol -> ../init.d/ddccontrol
-rwxr-xr-x 1 root root 148 Jul 23 12:48 /etc/init.d/ddccontrol


22 July, 2018

DKVM - Desktop KVM

Desktop KVM Operating System

I have never really liked the idea of having Windows running native on my machines - so for about the last year QEMU/KVM + VFIO has been my solution to running Windows applications.

While many others are currently using QEMU/KVM + VFIO Passthrough to run Windows at near native speed - I was unable to find a dedicated "KVM OS" for my needs.
My "daily-driver" is Linux - and, I wanted an option to allocate more resources to the Windows VM, without scarifying resources to my main Linux OS.
A way to accomplish this, is to have both the "daily driver" and the "gaming os" being virtualized, and not running at the same time.


So, my journey began to find a KVM hypervisor OS focused on running desktop VM's.

My KVM Desktop OS whishes

  • VFIO support
  • Be able to use my one "good" graphics-card for both Linux and Windows
  • Run-From-RAM style OS.
  • Boot from USB stick
  • Minimal memory foot-print
  • Support for software raid (preferable mdadm)
  • Support for bcache

The failed attempts

  • I gave oVirt a go, which honestly is quite nice. But, making this a Run-From-RAM style OS gave me quite some issues. A lot of tweaking was required - and maintaining all my tweaks has too much of a hazzle.
  • VMware ESXi recently has good pass-through support, and qorks really well booting from a USB stick (And it is already a Run-From-RAM style OS). Sadly ESXi has no support for software raid, and the SSD cache functionality is limited compared to bcache.
  • LinuxFromScratch was next in line, and I scriptet most of the build process - and got a fairly good working system. Though, I lacked the "easy maintenance" - and put the code on the shelf for now.

DKVM - My Desktop KVM OS

Lastly, I have AlpineLinux a go - as this has builtin support for Run-From-RAM style booting - including booting from a USB stick.

In short, I use QEMU to build a AlpineLinux bootable image, which can be flashed to a USB stick.
As of 3.8.0 release of AlpineLinux, both UEFI and Legacy booting now works out-of-the-box.

The build process


The setup.sh script is a wrapper for starting the build process - and is also creating a new empty disk-image file.
Here we will also be creating two addition ISO's used for stage01 and stage02.

stage01

Here we setup the base of the operating system.
I have chosen to include an "answer.txt" file for the alpine-setup program. This allowed the setup to run non-interactive.
The result of stage01 is a bootable disk image in a Run-From-RAM style

stage02

Here we setup the more custom part of the OS. Basic configuration like support for saving changes to USB disk is done here - among tweaks to varies aspects of the OS
We also do things like setting up both UEFI and Legacy bootloaders with vfio-pci.ids, and other KVM optimization arguments.

In my case, I have chosen to go for a setup with CPU isolation to minimize latency inside the running guests.
This is done using the isolcpus, nohz_full and rcu_nocbs arguments to the kernel - in combination with taskset to make affinity-rules for the vCPU threads.

vm_start

When the DKVM OS is loaded, i am presented with a simple menu to start my configured VMs.
At the time of writing, I only have two VM's configured - but I would imagine that will change.


This is done fairly simple with a wrapper-script around QEMU. 

vCPU affinity and isolation
Isolation is done using isolcpus - this will ensure no other threads are running on those cores.
The affinity is done using QEMU's builtin QMP system. This allowed the user to query for the threads used by QEMU to serve the vCPUs.


NOTE: In my case, my hyperthreaded cores is interleaved with the physical cores when looking at the processor ID. This can be checked using something similar to: 
# cat /proc/cpuinfo | grep "core id\|processor"
The CORELIST and isolcpu will need to reflect this.



All of the sources are available at my github - though, keep in mind this is written for personal use only!
Any recommendations/patches are welcome though :)

Other useful information / links

Linux and Wendell teamed up to test gaming on Linux. The different options are all quite interesting.



ACPI SLIC in VirtualBox

SLIC table in VirtualBox


Having the need to run a few Windows applications in my Lenovo Carbon X1 - but unwillingly to dual-boot or in other ways run Windows natively, I decided to give VirtualBox a go.

My laptop came with Windows pre-installed, and is using the SLIC table as identification for activation of Windows.

  • Host OS: Ubuntu (Usually following the LTS releases)
  • Guest OS: Windows 10.

Getting SLIC information


In any recent Linux distribution, it is fairly easy to retrieve such information from the DMI tables.
This can be done using the dmidecode utility.

Getting product key from MSDM ACPI table

The SLIC table is used for identification when activation Windows in combination with a a product-key and a SLIC certificate. As with my Lenovo laptop, this product-key was embedded in the MSDM table - and can easily be extracted under Linux.

# Get product key from MSDM table ###########################
productKey=$(sudo hexdump -s 56 -e '/29 "%s\n"' /sys/firmware/acpi/tables/MSDM)
[ -z "$productKey" ] && errorHandle "Error fetching product key from acpi table MSDM"
echo "Your product key is: $productKey"
$zenity --info --height=70 --width=400 --text "Your product key is: $productKey"
############################################################


Setting SLIC information

In VirtualBox, this can be done using "vboxmanage setextradata" to configure "VBoxInternal/Devices/pcbios/0/Config"

Activating Windows

To use the SLIC and productkey table for activation, we need a SLIC certificate. If you already have Windows installed, there is ways to retrieve the same information - including the certificate using a SLIC_ToolKit.

As alternative, dumps of the certificates can be found for most hardware manufactures.

Start cmd.exe as administrator, and issue
  1. slmgr -ilc <path xrn.ms file>
  2. slmgr -ipk <your product key>


Putting it all together

A simple bash script should do the trick - and can easily be shared with people in the same situation as me.
The script setslic.sh can be downloaded from my github repository.
The basic idea of the script is modify the required "pcibios" for a selected VM, with the acquired information from dmidecode.

The steps are:
  1. Configure a VM in VirtualBox, and attach your Windows ISO
  2. Run this script to modify pcibios on the VM (The script will print your productkey - write it down)
  3. Start the VM, and install Windows (Choose "I do not have product key" when installing)
  4. When Windows is loaded, install the certificate and activate using the productkey

Danish PC keyboard layout on MacOS

As I am primarily a GNU/Linux user, and mostly just using MacOS at work - I do not own (or want to own) a MacOS specific keyboard at home. ...