Notes and information on installing KVM (Kernel-based Virtual Machine) and QEMU (Quick EMUlator) on a new Gentoo host.

Adding KVM Support to Kernel

Does Machine Support Virtualization

Check if machine support virtualization by running the command below which checks whether Intel Vt-x or AMD AMD-V virtualization technologies for supporting concurrent operating system use of CPUs are enabled/available. A result of > 0 would suggest the machine is capable of virtualization.

$ grep -E "^vmx|^svm" /proc/cpuinfo |wc -l
24
$ 

Kernel Settings

The machine I am installing this on is Intel based, so while there is no harm building the AMD processor support as a module, I opted not to waste time building something that won’t be used on this machine. There is also no need for Virtual Box Guest integration so I disabled that as well when I noticed it was on. I suspect there are other settings hidden about I might need to turn on, but I think the below should be sufficient to get things going. After rebuilding kernel, add to boot loader and reboot machine to load kernel before moving on to the next section.

[*] Virtualization  --->

--- Virtualization
<M>   Kernel-based Virtual Machine (KVM) support
<M>     KVM for Intel (and compatible) processors support
< >     KVM for AMD processors support
[*]     Audit KVM MMU   

Device Drivers  --->

[*] Virtualization drivers  --->
--- Virtualization drivers 
< >   Virtual Box Guest integration support
< >   Nitro Enclaves Support

[*] VHOST drivers  --->
 --- VHOST drivers
<M>   Host kernel accelerator for virtio net
<M>   VHOST_SCSI TCM fabric driver
<M>   vhost virtio-vsock driver
[ ]   Cross-endian support for vhost

[*] Network device support  --->
--- Network device support
[*]   Network core driver support
...
<M>     Universal TUN/TAP device driver support
...

-*- Networking support  --->
--- Networking support
      Networking options  ---> 
      ...
      -*-   The IPv6 protocol  --->
      ...
      <M> 802.1d Ethernet Bridging
      ...

Test Kernel has KVM Support

I’ve rebooted the machine to load the new kernel and I make sure KVM support has been added by looking for the existence of /dev/kvm. If it wasn’t there, I would need to go back and check my work and troubleshoot until I got it to appear.

$ ls /dev/kvm
/dev/kvm

Install QEMU

Create Package Use Flags File and Install QEMU

QEMU has a lot of USE flags to control what features are built. As I am not entirely sure which features I will eventually use, I created a /etc/portage/package.use/app-emulation/qemu with some initial settings as below. As my needs change over time, I will be able to edit the file and rebuild QEMU to add or remove features as required.

$ sudo mkdir /etc/portage/package.use/app-emulation
$ sudo vim /etc/portage/package.use/app-emulation/qemu
app-emulation/qemu nfs plugins python ssh spice usb usbredir QEMU_SOFTMMU_TARGETS: arm aarch64 i386 x86_64 risc64 QEMU_USER_TARGETS: x86_64 aarch64 arm armeb i386 risc64

$ sudo emerge -avt qemu

These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[ebuild  N     ] app-emulation/qemu-5.2.0-r2::gentoo  USE="aio bzip2 caps curl fdt filecaps jpeg ncurses nfs nls oss pin-upstream-blobs plugins png python seccomp slirp spice ssh udev usb usbredir vhost-net vnc xattr -accessibility -alsa -capstone -debug -doc -glusterfs -gnutls -gtk -infiniband -io-uring -iscsi -jack -jemalloc -lzo -multipath -numa -opengl -pulseaudio -rbd -sasl -sdl -sdl-image (-selinux) -smartcard -snappy -static -static-user -systemtap -test -vde -vhost-user-fs -virgl -virtfs -vte -xen -xfs -zstd" PYTHON_TARGETS="python3_8 -python3_7 -python3_9" QEMU_SOFTMMU_TARGETS="aarch64 arm i386 x86_64 -alpha -avr -cris -hppa -lm32 -m68k -microblaze -microblazeel -mips -mips64 -mips64el -mipsel -moxie -nios2 -or1k -ppc -ppc64 -riscv32 -riscv64 -rx -s390x -sh4 -sh4eb -sparc -sparc64 -tricore -unicore32 -xtensa -xtensaeb" QEMU_USER_TARGETS="aarch64 arm armeb i386 x86_64 -aarch64_be -alpha -cris -hppa -m68k -microblaze -microblazeel -mips -mips64 -mips64el -mipsel -mipsn32 -mipsn32el -nios2 -or1k -ppc -ppc64 -ppc64abi32 -ppc64le -riscv32 -riscv64 -s390x -sh4 -sh4eb -sparc -sparc32plus -sparc64 -tilegx -xtensa -xtensaeb" 0 KiB
[ebuild  N     ]  app-emulation/spice-0.14.3::gentoo  USE="-gstreamer (-libressl) -lz4 -sasl -smartcard -static-libs" 0 KiB
[ebuild  N     ]  net-libs/libslirp-4.4.0::gentoo  USE="-static-libs" 0 KiB
[nomerge       ] app-emulation/qemu-5.2.0-r2::gentoo  USE="aio bzip2 caps curl fdt filecaps jpeg ncurses nfs nls oss pin-upstream-blobs plugins png python seccomp slirp spice ssh udev usb usbredir vhost-net vnc xattr -accessibility -alsa -capstone -debug -doc -glusterfs -gnutls -gtk -infiniband -io-uring -iscsi -jack -jemalloc -lzo -multipath -numa -opengl -pulseaudio -rbd -sasl -sdl -sdl-image (-selinux) -smartcard -snappy -static -static-user -systemtap -test -vde -vhost-user-fs -virgl -virtfs -vte -xen -xfs -zstd" PYTHON_TARGETS="python3_8 -python3_7 -python3_9" QEMU_SOFTMMU_TARGETS="aarch64 arm i386 x86_64 -alpha -avr -cris -hppa -lm32 -m68k -microblaze -microblazeel -mips -mips64 -mips64el -mipsel -moxie -nios2 -or1k -ppc -ppc64 -riscv32 -riscv64 -rx -s390x -sh4 -sh4eb -sparc -sparc64 -tricore -unicore32 -xtensa -xtensaeb" QEMU_USER_TARGETS="aarch64 arm armeb i386 x86_64 -aarch64_be -alpha -cris -hppa -m68k -microblaze -microblazeel -mips -mips64 -mips64el -mipsel -mipsn32 -mipsn32el -nios2 -or1k -ppc -ppc64 -ppc64abi32 -ppc64le -riscv32 -riscv64 -s390x -sh4 -sh4eb -sparc -sparc32plus -sparc64 -tilegx -xtensa -xtensaeb" 
[nomerge       ]  dev-libs/glib-2.66.4:2::gentoo  USE="mime xattr -dbus -debug -fam -gtk-doc (-selinux) -static-libs -sysprof -systemtap -test -utils" ABI_X86="(64) -32 (-x32)" 
[ebuild  N     ]   x11-misc/shared-mime-info-2.1::gentoo  0 KiB
[ebuild  N     ]    dev-libs/glib-2.66.4:2::gentoo  USE="mime xattr -dbus -debug -fam -gtk-doc (-selinux) -static-libs -sysprof -systemtap -test -utils" ABI_X86="(64) -32 (-x32)" 0 KiB

Total: 5 packages (5 new), Size of downloads: 0 KiB

Would you like to merge these packages? [Yes/No] yes
...
>>> Auto-cleaning packages...

>>> No outdated packages were found on your system.

 * GNU info directory index is up-to-date.
$

Add User Account to KVM Group

$ sudo gpasswd -a chuck kvm
Adding user larry to group kvm
$

Reset Permissions on /dev/kvm

On new installs it is recommended to ask udev to rest the permissions on /dev/kvm, and so that is what the command below does.

$ sudo udevadm trigger -c add /dev/kvm
$

QEMU Networking Host & Guest VMs

Network Plan

Bridging Tools

As there is a bridge in my desired setup, best to start by installing bridge-utils to manage via brctl.

$sudo  emerge -a bridge-utils

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] net-misc/bridge-utils-1.6  USE="(-selinux)" 

Would you like to merge these packages? [Yes/No] yes
...
>>> Installing (1 of 1) net-misc/bridge-utils-1.6::gentoo

>>> Recording net-misc/bridge-utils in "world" favorites file...
>>> Auto-cleaning packages...

>>> No outdated packages were found on your system.

 * GNU info directory index is up-to-date.
$

Install Libvirt

emerge -vat libvirt

These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[ebuild  N     ] app-emulation/libvirt-7.0.0-r1:0/7.0.0::gentoo  USE="caps libvirtd nls qemu udev virt-network -apparmor -audit -dtrace -firewalld -fuse -glusterfs -iscsi -iscsi-direct -libssh -lvm -lxc -nfs -numa (-openvz) -parted -pcap -policykit -rbd -sasl (-selinux) -virtualbox -wireshark-plugins -xen -zfs" 0 KiB
[ebuild  N     ]  dev-perl/XML-XPath-1.420.0::gentoo  USE="-examples -test" 0 KiB
[ebuild  N     ]  x11-libs/libpciaccess-0.16::gentoo  USE="zlib" ABI_X86="(64) -32 (-x32)" 359 KiB
[ebuild  N     ]   media-fonts/font-util-1.3.2-r1::gentoo  155 KiB
[ebuild  N     ]  net-misc/radvd-2.19::gentoo  USE="(-selinux) -test" 218 KiB
[ebuild  N     ]  net-dns/dnsmasq-2.84-r101::gentoo  USE="dhcp dumpfile inotify ipv6 nls script -auth-dns -conntrack -dbus -dhcp-tools -dnssec -id -idn -libidn2 -lua -nettlehash (-selinux) -static -tftp" LUA_SINGLE_TARGET="lua5-1 -lua5-2 -lua5-3 -lua5-4 -luajit" 503 KiB
[ebuild  N     ]  net-analyzer/openbsd-netcat-1.195::gentoo  58 KiB
[ebuild  N     ]  acct-user/qemu-0-r1::gentoo  0 KiB
[ebuild  N     ]   acct-group/qemu-0-r1::gentoo  0 KiB
[ebuild  N     ]  net-libs/libssh2-1.9.0_p20200614::gentoo  USE="zlib -gcrypt (-libressl) -mbedtls" ABI_X86="(64) -32 (-x32)" 472 KiB
[nomerge       ] net-dns/dnsmasq-2.84-r101::gentoo  USE="dhcp dumpfile inotify ipv6 nls script -auth-dns -conntrack -dbus -dhcp-tools -dnssec -id -idn -libidn2 -lua -nettlehash (-selinux) -static -tftp" LUA_SINGLE_TARGET="lua5-1 -lua5-2 -lua5-3 -lua5-4 -luajit" 
[ebuild  N     ]  acct-user/dnsmasq-0-r1::gentoo  0 KiB
[nomerge       ] app-emulation/libvirt-7.0.0-r1:0/7.0.0::gentoo  USE="caps libvirtd nls qemu udev virt-network -apparmor -audit -dtrace -firewalld -fuse -glusterfs -iscsi -iscsi-direct -libssh -lvm -lxc -nfs -numa (-openvz) -parted -pcap -policykit -rbd -sasl (-selinux) -virtualbox -wireshark-plugins -xen -zfs" 
[ebuild  N     ]  net-firewall/ebtables-2.0.11-r3::gentoo  USE="perl -static" 419 KiB
[ebuild  N     ]   net-misc/ethertypes-0::gentoo  1 KiB
[nomerge       ] net-misc/radvd-2.19::gentoo  USE="(-selinux) -test" 
[ebuild  N     ]  dev-libs/libdaemon-0.14-r3:0/5::gentoo  USE="-doc -examples -static-libs" ABI_X86="(64) -32 (-x32)" 333 KiB
[nomerge       ] x11-libs/libpciaccess-0.16::gentoo  USE="zlib" ABI_X86="(64) -32 (-x32)" 
[ebuild  N     ]  x11-misc/util-macros-1.19.3::gentoo  83 KiB
[nomerge       ] app-emulation/libvirt-7.0.0-r1:0/7.0.0::gentoo  USE="caps libvirtd nls qemu udev virt-network -apparmor -audit -dtrace -firewalld -fuse -glusterfs -iscsi -iscsi-direct -libssh -lvm -lxc -nfs -numa (-openvz) -parted -pcap -policykit -rbd -sasl (-selinux) -virtualbox -wireshark-plugins -xen -zfs" 
[ebuild  N     ]  app-text/xhtml1-20020801-r6::gentoo  227 KiB
[ebuild  N     ]  dev-python/docutils-0.16-r1::gentoo  PYTHON_TARGETS="python3_8 -pypy3 -python3_7 -python3_9" 1,917 KiB
[ebuild  N     ]   dev-python/pygments-2.7.4::gentoo  USE="-doc -test" PYTHON_TARGETS="python3_8 -pypy3 -python3_7 -python3_9" 2,271 KiB
[ebuild  N     ]  dev-libs/yajl-2.1.0-r2:0/2::gentoo  USE="-static-libs" ABI_X86="(64) -32 (-x32)" 83 KiB
[ebuild  N     ]  sys-apps/dmidecode-3.3::gentoo  USE="(-selinux)" 56 KiB
[ebuild  N     ]  dev-libs/libnl-3.5.0:3::gentoo  USE="debug threads -python -static-libs -utils" ABI_X86="(64) -32 (-x32)" PYTHON_TARGETS="python3_8 -python3_7 -python3_9" 946 KiB
[ebuild  N     ]  app-misc/scrub-2.6.1::gentoo  355 KiB
[nomerge       ] net-dns/dnsmasq-2.84-r101::gentoo  USE="dhcp dumpfile inotify ipv6 nls script -auth-dns -conntrack -dbus -dhcp-tools -dnssec -id -idn -libidn2 -lua -nettlehash (-selinux) -static -tftp" LUA_SINGLE_TARGET="lua5-1 -lua5-2 -lua5-3 -lua5-4 -luajit" 
[ebuild  N     ]  acct-group/dnsmasq-0-r1::gentoo  0 KiB

Total: 23 packages (23 new), Size of downloads: 8,446 KiB

Would you like to merge these packages? [Yes/No] yes

...
>>> Auto-cleaning packages...

>>> No outdated packages were found on your system.

 * GNU info directory index is up-to-date.

Add User to libvirt

Add user account to libvirt group, then log oout and back in to pick up changes. This and the next step below should make virt-admin usable for users other than root.

$ sudo gpasswd -a larry libvirt
Adding user larry to group libvirt
$

Uncomment the following lines in /etc/libvirt/libvirtd.conf and save.

$ sudo vim etc/libvirt/libvirtd.conf

auth_unix_ro = "none"
auth_unix_rw = "none"
unix_sock_group = "libvirt"
unix_sock_ro_perms = "0777"
unix_sock_rw_perms = "0770"

Start libvirt Service

Enable, start and check the running status of __libvirtd__ using _systemd_.

$ sudo systemctl enable libvirtd
Created symlink /etc/systemd/system/multi-user.target.wants/libvirtd.service → /usr/lib/systemd/system/libvirtd.service.
Created symlink /etc/systemd/system/sockets.target.wants/virtlockd.socket → /usr/lib/systemd/system/virtlockd.socket.
Created symlink /etc/systemd/system/sockets.target.wants/virtlogd.socket → /usr/lib/systemd/system/virtlogd.socket.
Created symlink /etc/systemd/system/sockets.target.wants/libvirtd.socket → /usr/lib/systemd/system/libvirtd.socket.
Created symlink /etc/systemd/system/sockets.target.wants/libvirtd-ro.socket → /usr/lib/systemd/system/libvirtd-ro.socket.

$ sudo systemctl restart libvirtd

$ systemctl status libvirtd
● libvirtd.service - Virtualization daemon
     Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: disable>
     Active: active (running) since Mon 2021-02-15 04:45:55 CST; 45s ago
TriggeredBy: ● libvirtd-admin.socket
             ● libvirtd.socket
             ● libvirtd-ro.socket
       Docs: man:libvirtd(8)
             https://libvirt.org
   Main PID: 300698 (libvirtd)
      Tasks: 21 (limit: 32768)
     Memory: 10.2M
        CPU: 450ms
     CGroup: /system.slice/libvirtd.service
             ├─293488 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
             ├─293489 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
             └─300698 /usr/sbin/libvirtd

Feb 15 04:45:55 sparky systemd[1]: Starting Virtualization daemon...
Feb 15 04:45:55 sparky systemd[1]: Started Virtualization daemon.
Feb 15 04:45:57 sparky dnsmasq[293488]: read /etc/hosts - 2 addresses
Feb 15 04:45:57 sparky dnsmasq[293488]: read /var/lib/libvirt/dnsmasq/default.addnhosts - 0 addresses
Feb 15 04:45:57 sparky dnsmasq-dhcp[293488]: read /var/lib/libvirt/dnsmasq/default.hostsfile
$

I think that is enough for now. The above was sufficient to get emulation KVM/QEMU set up on my new machine. If you have made it this far then good for you.

References