Overview
Ubuntu provides a wide variety of kernels for many different architectures and flavours, such as generic, lowlatency, cloud kernels, kvm, etc.
Maintaining a separate .config
for each of these kernels would be extremely challenging, Kconfig options need to always match the desired value in order to have a kernel functional for the scope that it was designed for.
Starting with Ubuntu 23.04 (Lunar Lobster) the kernel team introduced a new format of annotations: a JSON-like file to store all the kernel config options for the supported architectures and flavours.
Edit: This feature has been backported also to 22.04 (Jammy Jellyfish)
Quick start
- Generate the Ubuntu kernel .config for a specific architecture & flavour (i.e.,
amd64
,generic
):
$ ./debian/scripts/misc/annotations \
--arch amd64 --flavour generic --export > .config
- Import your own kernel .config in the Ubuntu kernel for a specific architecture & flavour (i.e.,
amd64
,generic
):
$ ./debian/scripts/misc/annotations \
--arch amd64 --flavour generic --import .config
- After a new config is imported run
fakeroot debian/rules clean updateconfigs
to update the dependencies, then you can review the actual changes doing a simplegit diff
.
TECHNICAL DETAILS
Ubuntu kernel annotations
There is a main annotations file for each Ubuntu kernel in: debian.<kernel_name>/config/annotations
The main annotations file can include other annotations (recursively).
The annotations has 4 different sections:
-
a header (that defines the format version, the list of supported architectures, the list of supported flavours paired with each architecture and a list of flavour inheritance rules)
-
a list of includes (annotations can include other annotations files to create a hierarchy of configs with overrides)
-
a subset of mandatory config options that have a note associated (typically config options that must be enforced for certain reasons, the note can be simply a reference to a tracking bug, explaining why the specific config needs to be set to a certain value, or just a description, like security implications for that config value, etc.)
-
a subset of config options that are either generated as dependency of the previous subset of configs or configs that have been set using the default Ubuntu policy (enable everything as module when possible, except for debugging, testing or deprecated features), so they donāt need an explicit note.
The annotations format looks like the following:
# Menu: HEADER
# FORMAT: 4
# ARCH: <ARCH_1> <ARCH_2> <ARCH_3> ... <ARCH_N>
# FLAVOUR: <ARCH_1>-<FLAVOUR_1> <ARCH1_FLAVOUR_2> ... <ARCH_N>-<FLAVOUR_M>
# FLAVOUR_DEP: {'<ARCH_1>-<FLAVOUR_1>': '<PARENT_ARCH_1>-<PARENT_FLAVOUR_1>', ..., '<ARCH_N>-<FLAVOUR_M>': '<PARENT_ARCH_N>-<PARENT_FLAVOUR_M>'}
include <FILE_1>
include <FILE_2>
...
include <FILE_N>
CONFIG_<FOO> policy<{'<ARCH_1>[-<FLAVOUR_1>]': '<VALUE_1_1>', ..., '<ARCH_N>[-<FLAVOUR_M>]': '<VALUE_N_M>'}>
CONFIG_<FOO> note<'<DESCRIPTION>'>
...
# ---- Annotations without notes ----
CONFIG_<BAR> policy<{'<ARCH_1>[-<FLAVOUR_1>]': '<VALUE_1_1>', ..., '<ARCH_N>[-<FLAVOUR_M>]': '<VALUE_N_M>'}>
...
-
ARCH: contains the list of comma-separated values that defines all the supported architectures for this kernel
-
FLAVOUR: contains the list of comma-separated values that defines the list of flavours associated to each supported architecture
-
FLAVOUR_DEP: contains a mapping of
ARCH-FLAVOUR
pairs mapped to a parentARCH-FLAVOUR
pair; this can be used to define flavours that derives from other flavours, for exampleamd64-lowlatency
derives fromamd64-generic
(then the local annotations file will only contain an include rule of the generic kernel plus the small subset of config options to override the defaults fromamd64-generic
) -
FILE_1 ā¦ FILE_N: are the other included annotations (e.g., used by derivative kernels that want to include the annotations from the kernel they derive from)
-
FOO, BAR: kernel config options with the associated values across architectures and flavours, represented by the
policy<...>
definition
A simple example of an annotations file is the following (from the lunar/linux-lowlatency
kernel, that derives from the generic kernel lunar/linux
):
# Menu: HEADER
# FORMAT: 4
# ARCH: amd64 arm64
# FLAVOUR: amd64-lowlatency arm64-lowlatency arm64-lowlatency-64k
# FLAVOUR_DEP: {'amd64-lowlatency': 'amd64-generic', 'arm64-lowlatency': 'arm64-generic', 'arm64-lowlatency-64k': 'arm64-generic-64k'}
include "../../debian.master/config/annotations"
CONFIG_HZ_1000 policy<{'amd64': 'y', 'arm64': 'y'}>
CONFIG_HZ_1000 note<'HZ for lowlatency must be set to 1000 to provide better system responsiveness'>
CONFIG_HZ_250 policy<{'amd64': 'n', 'arm64': 'n'}>
CONFIG_HZ_250 note<'Override default HZ used in generic'>
CONFIG_LATENCYTOP policy<{'amd64': 'y', 'arm64': 'y'}>
CONFIG_LATENCYTOP note<'https://lists.ubuntu.com/archives/kernel-team/2014-July/045006.html, LP#1655986'>
CONFIG_PREEMPT policy<{'amd64': 'y', 'arm64': 'y'}>
CONFIG_PREEMPT note<'Enable fully preemptible kernel'>
CONFIG_PREEMPT_VOLUNTARY policy<{'amd64': 'n', 'arm64': 'n'}>
CONFIG_PREEMPT_VOLUNTARY note<'Disable voluntary preemption model'>
# ---- Annotations without notes ----
CONFIG_HZ policy<{'amd64': '1000', 'arm64': '1000'}>
Managing the annotations file
To help the management of annotations each Ubuntu kernel provides a helper script in debian/scripts/misc/annotations
(use --help
for an overview of the supported actions).
In the following examples we are going to define an alias for this script
$ alias annotations='./debian/scripts/misc/annotations'
Here some typical examples of what you can do with the annotations script:
- Show settings for
CONFIG_DEBUG_INFO_BTF
for master kernel across all the supported architectures and flavours:
$ annotations --query --config CONFIG_DEBUG_INFO_BTF
{
"policy": {
"amd64": "y",
"arm64": "y",
"armhf": "n",
"ppc64el": "y",
"riscv64": "y",
"s390x": "y"
},
"note": "'Needs newer pahole for armhf'"
}
- Dump kernel .config for arm64 and flavour generic-64k:
$ annotations --arch arm64 --flavour generic-64k --export
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_COMPAT=y
...
- Update annotations file with a new kernel .config for
amd64
flavourgeneric
:
$ annotations --arch amd64 --flavour generic --import .config
- Enable CONFIG_PROVE_LOCKING on amd64 for flavour generic:
$ annotations -c CONFIG_PROVE_LOCKING --arch amd64 --flavour generic --write y
{
"CONFIG_PROVE_LOCKING": {
"policy": {
"amd64": "y",
"arm64": "n",
"armhf": "n",
"ppc64el": "n",
"riscv64": "n",
"s390x": "n"
}
}
}
$ git diff
diff --git a/debian.master/config/annotations b/debian.master/config/annotations
index bc466d731815..301be4f9aaec 100644
--- a/debian.master/config/annotations
+++ b/debian.master/config/annotations
@@ -9884,7 +9884,7 @@ CONFIG_PROFILE_ALL_BRANCHES policy<{'riscv64': 'n'}>
CONFIG_PROFILE_ANNOTATED_BRANCHES policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n', 'riscv64': 'n', 's390x': 'n'}>
CONFIG_PROFILING policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 'riscv64': 'y', 's390x': 'y'}>
CONFIG_PROTECTED_VIRTUALIZATION_GUEST policy<{'s390x': 'y'}>
-CONFIG_PROVE_LOCKING policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n', 'riscv64': 'n', 's390x': 'n'}>
+CONFIG_PROVE_LOCKING policy<{'amd64': 'y', 'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n', 'riscv64': 'n', 's390x': 'n'}>
CONFIG_PROVIDE_OHCI1394_DMA_INIT policy<{'amd64': 'n'}>
CONFIG_PRU_REMOTEPROC policy<{'arm64': 'm', 'armhf': 'm'}>
CONFIG_PSAMPLE policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm', 'riscv64': 'm', 's390x': 'm'}>
Every time the annotations file is changed we need to make sure that all the dependent config options are refreshed.
To do so we need to run the following command:
$ fakeroot debian/rules clean updateconfigs
...
This command will take care of interfacing with the kernel Kconfig subsystem and itāll interactively ask the value for all the potentially new enabled dependent options.
Conclusion
The annotations format introduced in Lunar provides an easier and more efficient way of managing kernel .configās across the large variety of kernels, architectures and flavours that Ubuntu supports.
If you want to submit a patch to kernel-team@lists.ubuntu.com that needs to change the kernel .config
, or simply if you want to recompile the Ubuntu kernel using a different .config
you just need to modify the annotations file and then you can simply upload your custom modified kernel to a ppa to test it, or you can recompile it locally using the typical Ubuntu way of rebuilding packages.