One of the best ways to find what features are enabled in a given kernel is to look at the kernel configuration. In this blog we describe the format that we use in storing our kernel configuration and methods for extracting the actual configuration.

UEK-next release

UEK-next is the next Unbreakable Enterprise Kernel Developer Release which allows Oracle linux users to experiment with the latest developments from upstream Linux combined with Oracle UEK-specific features. Note that this is not supported for production deployment. RPMs and source for this release can be found here:

Savedefconfig format

savedefconfig format allows us to use minimal config which essentially only stores config options which have values that are different from their defaults. Eg: If the default value of a config option is ‘y’ and the desired value (what we want) is also ‘y’, savedefconfig hides this.

savedefconfig is a make target which creates a ‘defconfig’ file in which it stores the minimal config. These defconfig files are copied back to the source which are used to generate real configurations using ‘make olddefconfig’ during the build process.

Kernel configurations for the UEK-next release are stored in the uek-rpm directory as follows:

  • uek-rpm/ol9/config-<arch> – Where <arch> is one of
    • x86_64 for Intel and AMD platforms
    • aarch64 for ARM platforms

We also have debug configurations used for debug kernels.

How do I check the real config ?

There are multiple ways to read or extract the real configuration

Method 1: Install the rpms using the steps descibed here

After installing the UEK-next kernel, the kernel configuration is present in the /boot directory which looks like: /boot/config-6.8.0-2.el9uek.<arch>

Method 2: Extracting the config from rpm

It is possible that we would just want to check the config without installing the rpms. The config is packaged in the core kernel rpm.

$ rpm2cpio https://yum.oracle.com/repo/OracleLinux/OL9/developer/UEKnext/x86_64/getPackage/kernel-ueknext-core-6.8.0-2.el9uek.x86_64.rpm | cpio -i --to-stdout '*/config' | tee config-uek-next.txt

# The advantage of the above is that we really need not install the rpm on a specific machine.
# Eg: we can see what is there in actual config(/boot/config) of an aarch64 ol9 rpm in a x86_64 machine.

Method 3: Generate the kernel config from the source

Getting the source ready to compile is documented here

$ cp uek-rpm/ol9/config-$(uname -p) .config
$ make olddefconfig
$ vim .config   # This is the real kernel configuration which appears in /boot directory.

# Experiment with config, enable something ?
# In the UEK-next source
$ ./scripts/config --file uek-rpm/ol9/config-$(uname -p) --enable CONFIG_XYZ
$ cp uek-rpm/ol9/config-$(uname -p) .config
$ make olddefconfig
$ vim .config   # this will have necessary changes if dependencies are satisfied

Notice that the real kernel configuration (/boot/config-6.8.0-2.el9uek.<arch> or .config) look quite different from the config file present in the source (eg: uek-rpm/ol9/config-<arch>). This is because the config available in the source is using savedefconfig format.

Some examples

Let us look at a couple of examples to understand this format better.

  1. CONFIG_MEMCG_KMEM

    In the real configuration (/boot/config-6.8.0-2.el9uek.<arch> or .config) this config option is set to ‘y’, but when you look for this option in the source configuration (uek-rpm/ol9/config-<arch>), it would not be present. The reason why this is not present in the source config is that the value desired is same as the default value (‘y’).

    To find what is the default value one should look at Kconfig files. In this case we should look for “config MEMCG_KMEM”

    $ git grep "config MEMCG_KMEM"    # this will point to init/Kconfig
    
    # The Kconfig entry looks something like this
    config MEMCG_KMEM
        bool
        depends on MEMCG
        default y
    
    # Given that we have MEMCG enabled, MEMCG_KMEM default value is 'y'
    # and we want it to be 'y' savedefconfig hides it.
  2. CONFIG_KVM_SW_PROTECTED_VM

    In the real configuration (/boot/config-6.8.0-2.el9uek.<arch> or .config) this config option is set to ‘y’, and the same is present in the source configuration (uek-rpm/ol9/config-<arch>). The default value of this config option is ‘n’ (default value for a bool option is ‘n’). But we want this feature in our kernels so we explicitly set it to ‘y’.

    To find what is the default value one should look at Kconfig files. In this case we should look for “config KVM_SW_PROTECTED_VM”

    $ git grep "config KVM_SW_PROTECTED_VM"    # this will point to arch/x86/kvm/Kconfig
    
    # The Kconfig entry looks something like this
    config KVM_SW_PROTECTED_VM
        bool "Enable support for KVM software-protected VMs"
        depends on EXPERT
        depends on KVM && X86_64
        select KVM_GENERIC_PRIVATE_MEM
        help
          Enable support for KVM software-protected VMs.  Currently, software-
          protected VMs are purely a development and testing vehicle for
          KVM_CREATE_GUEST_MEMFD.  Attempting to run a "real" VM workload as a
          software-protected VM will fail miserably.
    
          If unsure, say "N"
          .
    # Given that we need KVM_SW_PROTECTED_VM in our kernels(desired value: 'y')
    # and default value is 'n', there is an entry in source config which uses
    # savedefconfig format with the desired value

I hope the above examples clarify more on the format. One can check for all rules of Kconfig here.

Why are we using savedefconfig format ?

Savedefconfig formatted config is a minimal config which essentially generates the larger configuration file on doing a “make olddefconfig” which in turn is part of the build process. Storing a smaller config file in the source simplifies the effort while maintaining it during every upstream update.

  • This format also shows us how the config options deviate from their default values
  • This also makes it easier to manage changes when we update from one kernel version to another (next one)
  • Quantitatively, using x86_64 config file as an example. The source config is 2907 lines and the real configuration is 10436 lines.

How do we deal with new upstream options ?

For every new upstream release, after applying Oracle patches, we compare the generated config (result of ‘make olddefconfig’ on 6.x) with the previous one (6.x-1) and make changes as per our need after reviewing each of the new kernel configuration options.

If we want a config option that defaults to ‘y’ but we don’t want to enable it in UEK-next, that would be marked in savedefconfig as the value desired is different from the default.

Conclusion

This blog provides some insights on how to extract the real kernel configuration and how that is different from the one that is present in the source.