Linux kernel selftests are small tests used to execute individual code paths in the Linux kernel. KVM selftests are a crucial subset of these used to verify KVM virtualization features. They interact with the KVM API directly and QEMU isn’t required to create a VM.
In addition to the default KVM selftests under the “tools/testing/selftests/kvm” directory, a user may utilize the APIs from KVM selftests to create extra customized tests that can be used to simulate and reproduce KVM bugs, i.e. KVM SMM issue, and kvmclock drift during vCPU hotplug.
By default, KVM selftests are built as dynamic binaries which rely on external libraries to be loaded into memory at runtime. In this blog article, we demonstrate how to build KVM selftests as static binaries on Oracle Linux 8, on a VM in Oracle Cloud Infrastructure (OCI). We demonstrate how this static binary which is built with one version of glibc can still execute in environments containing an older glibc version.
Step 1. Create OCI VMs
For the purposes of this article we are using an Oracle Linux 8 instance in OCI with the VM.Standard2.4 shape.
Step 2. Configure yum and install packages
Once your instance is created, enable the yum repository ol8_codeready_builder to install the prerequisite packages.
$ sudo yum-config-manager --enable ol8_codeready_builder $ cat /etc/yum.repos.d/oracle-linux-ol8.repo ... ... [ol8_codeready_builder] name=Oracle Linux 8 CodeReady Builder ($basearch) - Unsupported baseurl=https://yum$ociregion.$ocidomain/repo/OracleLinux/OL8/codeready/builder/$basearch/ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle gpgcheck=1 enabled=1 ... ...
Next install the required packages.
$ sudo yum install -y patch glibc-static gcc-toolset-11
Step 3. Configure gcc
In order to use gcc-11 we need to enable the gcc-toolset-11 software collection:
$ scl enable gcc-toolset-11 bash
Double check that the gcc version is 11.5.0.
$ gcc -v ... ... gcc version 11.5.0 20240719 (Red Hat 11.5.0-2.0.1) (GCC)
To ensure this software collection is enabled permanently across logins, add the above scl command to /etc/profile.
Step 4. Download source code
We use linux-6.4 in this article. Download and extract.
$ wget https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.4.tar.xz $ tar xvf linux-6.4.tar.xz
Step 5: Add “-static” CFLAGS
Apply the following patch to add CFLAGS “-static” in tools/testing/selftests/kvm/Makefile.
$ cat kvmselftest.patch
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 4761b768b..2474e65fb 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -203,7 +203,7 @@ CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \
-fno-stack-protector -fno-PIE -I$(LINUX_TOOL_INCLUDE) \
-I$(LINUX_TOOL_ARCH_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude \
-I$(<D) -Iinclude/$(ARCH_DIR) -I ../rseq -I.. $(EXTRA_CFLAGS) \
- $(KHDR_INCLUDES)
+ $(KHDR_INCLUDES) -static
ifeq ($(ARCH),s390)
CFLAGS += -march=z10
endif
$ cd linux-6.4
$ patch -p1 < ../kvmselftest.patch
Step 6. Build KVM selftests
$ cd linux-6.4 $ make headers $ cd tools/testing/selftests/kvm $ make
We use kvm_page_table_test as an example in this article.
$ ls -l kvm_page_table_test
-rwxrwxr-x. 1 opc opc 3803272 Mar 18 23:01 kvm_page_table_test
$ ldd kvm_page_table_test
not a dynamic executable
Step 7. Test
Copy kvm_page_table_test to an older Oracle Linux 7 environment, note how it executes successfully.
ol7$ ./kvm_page_table_test Testing guest mode: PA-bits:ANY, VA-bits:48, 4K pages Testing memory backing src type: anonymous Testing memory backing src granularity: 0x1000 Testing memory size(aligned): 0x40000000 Guest physical test memory offset: 0x3fffbffff000 Host virtual test memory offset: 0x7f4d229be000 Number of testing vCPUs: 1 Started all vCPUs successfully KVM_CREATE_MAPPINGS: total execution time: 1409.087522349s KVM_UPDATE_MAPPINGS: total execution time: 1408.532079123s KVM_ADJUST_MAPPINGS: total execution time: 1408.479546540s
If we skip Step 5 and don’t add the -static CFLAG, you will notice kvm_page_table_test fails to execute.
ol7$ ./kvm_page_table_test ./kvm_page_table_test: /lib64/libc.so.6: version `GLIBC_2.27' not found (required by ./kvm_page_table_test)
Summary
In this article we demonstrate how to build KVM selftests as a static binary on Oracle Linux 8 and how it can then be executed on older environments.