Google is committed to advancing racial equity for Black communities. See how.

Generic Kernel Image

The Android Common Kernels (ACKs) are the basis for all Android product kernels. Vendor and device kernels are downstream of ACKs. Vendors add support for SoCs and peripheral devices by modifying the kernel source code and adding device drivers. These modifications can be extensive, to the point that as much as 50% of the code running on a device is out-of-tree code (not from upstream Linux or from AOSP common kernels).

Thus, a device kernel is comprised of:

  • Upstream: The Linux kernel from kernel.org
  • AOSP: Additional Android-specific patches from AOSP common kernels
  • Vendor: SoC and peripheral enablement and optimization patches from vendors
  • OEM/device: Additional device drivers and customizations

Nearly every device has a custom kernel. This is kernel fragmentation.

Android kernel hierarchy leads to fragmentation

Figure 1. Android kernel hierarchy leads to fragmentation

The costs of fragmentation

Kernel fragmentation has several negative effects on the Android community.

Security updates are labor intensive

Security patches cited in the Android Security Bulletin (ASB) must be backported into each of the device kernels. However, due to kernel fragmentation, it's prohibitively expensive to propagate security fixes to Android devices in the field.

Difficult to merge Long-Term Supported updates

The Long-Term Supported (LTS) releases include security fixes and other critical bug fixes. Staying up to date with LTS releases has proven to be the most effective way to provide security fixes. On Pixel devices, it was discovered that 90% of the kernel security issues reported in the ASB had already been fixed for devices that stay up to date.

However, with all of the custom modifications in the device kernels, it's difficult to just merge the LTS fixes into device kernels.

Inhibits Android platform release upgrades

Fragmentation makes it difficult for new Android features requiring kernel changes to be added to devices in the field. Android Framework code must assume that as many as five kernel versions are supported and that no kernel changes were made for the new platform release (Android 10 supports 3.18, 4.4, 4.9, 4.14, and 4.19 kernels, which in some cases haven't been enhanced with new features since Android 8 in 2017).

Difficult to contribute kernel changes back to upstream Linux

With all of the changes being made to the kernel, most flagship devices ship with a kernel version that's already at least 18 months old. For example, the 4.14 kernel was released by kernel.org in November of 2017 and the first Android phones using 4.14 kernels shipped in the Spring of 2019.

This long delay between upstream kernel release and products makes it difficult for the Android community to feed needed features and drivers into the upstream kernels, so it's challenging to fix the fragmentation issue.

Fixing the fragmentation: Generic Kernel Image

The Generic Kernel Image (GKI) project addresses kernel fragmentation by unifying the core kernel and moving SoC and board support out of the core kernel into loadable modules. The GKI kernel presents a stable Kernel Module Interface (KMI) for kernel modules, so modules and kernel can be updated independently.

The GKI:

  • Is built from the ACK sources.
  • Is a single-kernel binary plus associated loadable modules per architecture, per LTS release (currently only arm64 for android11-5.4 and android12-5.4).
  • Is tested with all Android Platform releases that are supported for the associated ACK. There’s no feature deprecation for the lifetime of a GKI kernel version
  • Exposes a stable KMI to drivers within a given LTS.
  • Does not contain SoC- or board-specific code.

Here’s how an Android device looks with GKI implemented.

GKI architecture

Figure 2. GKI architecture

GKI is a complex change that will be rolled out in several stages starting with the v5.4 kernels in the Android 11 platform release.

GKI 1.0 — GKI compatibility requirements

For the Android 11 platform release, Treble compatibility will require GKI testing for devices running v5.4 kernels.

Partitions for GKI compatibility testing

Figure 3. Partitions for GKI compatibility testing

GKI compatibility means that the device passes the VTS and CTS-on-GSI+GKI tests with the Generic System Image (GSI) and the GKI kernel installed by flashing the GKI boot image into the boot partition and GSI system image in the system partition. Devices can ship with a different product kernel and can use loadable modules that GKI doesn't provide. However, both the product and GKI kernels must load modules from the same vendor_boot and vendor partitions. Therefore, all product kernels are required to have the same binary kernel module interface (KMI). Vendors can extend the KMI for product kernels as long as it remains compatible with the GKI KMI. There's no requirement that vendor modules be unloadable in GKI 1.0.

GKI 1.0 goals

  • Don't introduce regressions in VTS or CTS when the product kernel is replaced by the GKI kernel.
  • Reduce the kernel maintenance burden for OEMs and vendors to stay up to date with AOSP common kernels.
  • Include core Android changes in kernels whether a device is upgraded to a new Android platform release or newly launched.
  • Never break Android userspace.
  • Separate hardware-specific components from the core kernel as loadable modules.

GKI 2.0 - GKI products

Devices that launch with the Android S (2021) platform release using kernel versions v5.x (where 5.x is the kernel selected as LTS at the end of 2020) or higher will be required to ship with the GKI kernel. Signed boot images will be made available and updated regularly with LTS and critical bug fixes. Because binary stability will be maintained for the KMI, these boot images can be installed with no changes to vendor images.

GKI 2.0 goals

  • Don't introduce significant performance or power regressions with GKI.
  • Enable OEMs to deliver kernel security fixes and bug fixes (LTS) without vendor involvement.
  • Reduce cost of updating major kernel version for devices (for example, v5.x to v5.y).
  • Maintain only one GKI kernel binary per architecture by updating kernel versions with a clear process for upgrading.

GKI design

KMI kernel branches

GKI kernels are built from the ACK KMI kernel branches, which are described in detail in Android Common Kernels. The KMI is uniquely identified by the kernel version and the Android platform release, so the branches are named <androidRelease>-<kernel version>. For example, the 5.4 KMI kernel branch for Android 11 is named android11-5.4. It's expected that for Android S (not committed and shown only to demonstrate how the new branching model will progress in the future) there will be two additional KMI kernels, android12-5.4 and a second kernel based on the new LTS kernel, which should be declared at the end of 2020.

KMI kernel hierarchy

Figure 4 shows the branch hierarchy for the 5.x KMI kernels (where 5.x is the kernel selected as LTS at the end of 2020). android12-5.x is the KMI kernel corresponding to Android S and android13-5.x corresponds to Android 13 (not committed and shown only to demonstrate how the new branching model will progress in the future).

KMI kernel hierarchy for 5.x

Figure 4. KMI kernel hierarchy for 5.x

As shown in Figure 4, the KMI branches cycle through three phases: development (dev), stabilization (stab), and frozen. These phases are described in detail in Android Common Kernels.

After the KMI kernel is frozen, no KMI-breaking changes are accepted unless a serious security issue is identified that can't be mitigated without affecting the stable KMI. The branch remains frozen throughout its entire lifetime.

Bug fixes and partner features can be accepted into a frozen branch as long as the existing KMI isn't broken. The KMI can be extended with new exported symbols as long as the interfaces comprising the current KMI aren’t affected. When new interfaces are added to the KMI, they immediately become stable and can’t be broken by future changes.

For example, a change that adds a field to a structure used by a KMI interface is not allowed because it changes the interface definition:

struct foo {
  int original_field1;
  int original_field2;
  int new_field; // Not allowed
};

int do_foo(struct foo &myarg)
{
  do_something(myarg);
}
EXPORT_SYMBOL_GPL(do_foo);

However, adding a new function is fine:

struct foo_ext {
  struct foo orig_foo;
  int new_field;
};

int do_foo2(struct foo_ext &myarg)
{
  do_something_else(myarg);
}
EXPORT_SYMBOL_GPL(do_foo2);

KMI stability

To realize the GKI goals, it’s critical to maintain a stable KMI for drivers. The GKI kernel is built and shipped in binary form, but vendor-loadable modules are built in a separate tree. The resulting GKI kernel and modules must work as if they were built together. For GKI compatibility testing, the boot image containing the kernel is replaced with a boot image containing the GKI kernel, and the loadable modules in the vendor image must function correctly with either kernel.

The KMI doesn't include all symbols in the kernel or even all of the 30,000+ exported symbols. Instead, the symbols that can be used by modules are explicitly listed in a set of symbol list files maintained publicly in the root of the kernel tree. The union of all the symbols in all of the symbol list files defines the set of KMI symbols maintained as stable. An example symbol list file is abi_gki_aarch64_db845c, which declares the symbols required for the DragonBoard 845c.

Only the symbols listed in a symbol list and their related structures and definitions are considered part of the KMI. You can post changes to your symbol lists if the symbols you need aren't present. After new interfaces are in a symbol list, and therefore are part of the KMI description, they're maintained as stable and must not be removed from the symbol list or modified after the branch is frozen.

Each KMI kernel tree has its own set of symbol lists. No attempt is made to provide ABI stability between different KMI kernel branches. For example, the KMI for android11-5.4 is completely independent of the KMI for android12-5.4.

Generally, the Linux community has frowned on the notion of in-kernel ABI stability for the mainline kernel. In the face of different toolchains, configurations, and an ever-evolving Linux mainline kernel, it isn't feasible to maintain a stable KMI in mainline. However, it's possible in the highly constrained GKI environment. The constraints are:

  • The KMI is only stable within the same LTS kernel (for example, android11-5.4).
    • No KMI stability is maintained for android-mainline.
  • Only the specific Clang toolchain supplied in AOSP and defined for the corresponding branch is used for building kernel and modules.
  • Only symbols known to be used by modules as specified in a symbol list are monitored for stability and considered KMI symbols.
    • The corollary is that modules must use only KMI symbols. This is enforced by failing module loads if non-KMI-symbols are required.
  • After the KMI branch is frozen, no changes can break the KMI, including:
    • Config changes
    • Kernel code changes
    • Toolchain changes (including updates)

KMI monitoring

ABI monitoring tools monitor KMI stability during presubmit testing. Changes that break the KMI fail presubmit testing and must be reworked to be compatible. These tools are available to partners and the public for integration into their build processes. The Android kernel team uses these tools to find KMI breakages during development and when merging LTS releases. If a KMI breakage is detected during an LTS merge, the KMI is preserved by either removing the offending patches or by refactoring the patches to be compatible.

The KMI is considered broken if an existing KMI symbol is modified in an incompatible way. Examples:

  • New argument added to a KMI function
  • New field added to a structure used by a KMI function
  • New enum value added that changes the values of enums used by a KMI function
  • Configuration change that changes the presence of data members affecting the KMI

Adding new symbols doesn't necessarily break KMI, but new symbols that are used must be added to a symbol list and to the ABI representation. Otherwise future changes to this part of the KMI won’t be recognized.

Partners are expected to use the ABI monitoring tools to compare the KMI between their product kernel and the GKI kernel and ensure that they're compatible.

The latest android11-5.4 binary GKI kernel can be downloaded from ci.android.com (kernel_aarch64 builds).

Single compiler

A compiler change can alter the internal kernel data structure layout that affects the ABI. Because it's critical to keep the KMI stable, the toolchain used to build the GKI kernel must be completely compatible with the toolchain used to build vendor modules. The GKI kernel is built with the LLVM toolchain included in AOSP.

As of Android 10, all Android kernels must be built with an LLVM toolchain. With GKI, the LLVM toolchain used to build product kernels and vendor modules must generate the same ABI as the LLVM toolchain from AOSP and partners must ensure that the KMI is compatible with the GKI kernel.

The Android kernel build documentation describes how the reference GKI kernel is built. In particular, the documented procedure ensures that the correct toolchain and configuration are used to build the kernel. Downstream partners are encouraged to use the same tooling for producing the final kernel to avoid incompatibilities caused by toolchain or other build-time dependencies.

Kernel configs

The GKI kernel is built using arch/arm64/configs/gki_defconfig. Because these configs affect the KMI, the GKI configs are managed very carefully. For the frozen KMI kernels, configs can only be added or removed if there's no impact to the KMI.

The GKI kernel must be configured to run on a diverse set of devices. Therefore it must have built-in support for all the subsystems and options required for all these devices, not including the loadable modules that are used to enable the hardware. Partners should request the needed config changes to dev kernels.

Boot changes

To facilitate a clean separation between the GKI and vendor components, the boot partition contains only generic components, including the kernel and a ramdisk with GKI modules. A new version of the boot header (v3) is defined to indicate compliance with the GKI architecture. The GKI version of the boot images is delivered by Google and replaces the vendor's version of the boot image when testing for GKI compatibility.

The ramdisk for first-stage init, recovery, and fastbootd is an initramfs image comprised of two CPIO archives that are concatenated by the bootloader. The first CPIO archive comes from the new vendor_boot partition. The second comes from the boot partition.

A summary of the changes is provided here. See Vendor boot partition for details.

Boot partition

The boot partition includes a header, kernel, and a CPIO archive of the generic portion of the boot ramdisk.

With a boot header v3 boot partition, these sections of the prior boot partition are no longer present:

  • Second stage bootloader: If a device has a second stage bootloader it must be stored in its own partition.
  • DTB: The DTB is stored in the Vendor boot partition.

The boot partition contains a CPIO archive with the GKI components:

  • GKI kernel modules located in /lib/modules/
  • first_stage_init and libraries it depends on
  • fastbootd and recovery (used in A/B and Virtual A/B devices)

The GKI boot image is provided by Google and must be used for GKI compatibility testing.

The latest arm64 android11-5.4 boot.img is downloadable from ci.android.com in the aosp_arm64 build artifacts of the aosp-master branch.

The latest arm64 android11-5.4 kernel image (Image.gz) can be downloaded from ci.android.com in the aosp_aarch64 build artifacts of the aosp_kernel-common-android11-5.4 branch.

Vendor boot partition

The vendor_boot partition is introduced with GKI. It's A/B'd with Virtual A/B and consists of a header, the vendor ramdisk, and the device tree blob. The vendor ramdisk is a CPIO archive that contains the vendor modules required for device boot. This includes modules to enable critical SoC functionality as well as storage and display drivers needed to boot the device and display splash screens.

The CPIO archive contains:

  • First-stage init vendor kernel modules located in /lib/modules/
  • modprobe config files located in /lib/modules
  • modules.load file indicating the modules to load during first-stage init

Bootloader requirement

The bootloader must load the generic ramdisk CPIO image (from the boot partition) into memory immediately following the vendor ramdisk CPIO image (from the vendor_boot partition). After decompression, the result is the generic ramdisk overlaid on top of the file structure of the vendor ramdisk.

GKI compatibility testing

For the Android 11 platform release, devices launched with a v5.4 kernel must run the VTS and CTS-on-GSI tests using the GKI boot image supplied by Google.

Contributing to the GKI kernel

The GKI kernel is built from the AOSP Common Kernels starting with android11-5.4. All submitted patches must conform to these contribution guidelines, which document two strategies:

  1. Best: Make all of your changes to upstream Linux. If appropriate, backport to the stable releases. These patches are merged automatically in the corresponding AOSP common kernels. If the patch is already in upstream Linux, post a backport of the patch that conforms to the patch requirements below.
  2. Less good: Develop your patches out of tree (from an upstream Linux point of view). Unless the patches are fixing an Android-specific bug, they're very unlikely to be accepted unless they've been coordinated with kernel-team@android.com.

For partners implementing GKI, there might be valid reasons why out-of-tree patches are required (especially if there are silicon schedules that must be met). For these cases, file a Buganizer issue.

Submit GKI changes through Gerrit to the android-mainline branch first and then backported to other release branches as needed.

The source code associated with loadable modules doesn't need to be contributed to the GKI kernel source tree, however it's strongly recommended to submit all drivers to upstream Linux.

Requesting backports from mainline

Generally, mainline patches needed by GKI partners can be backported to the GKI kernels. Upload the patch to Gerrit following the contribution guidelines.

If the patch has been posted upstream, but hasn't yet been accepted, it's recommended to wait until it is accepted. If the schedule doesn't permit waiting for the patch to be accepted upstream, file a Buganizer issue.

Adding and removing GKI configs

To request the addition or removal of configs in arch/arm64/configs/gki_defconfig, file a Buganizer issue clearly stating the request and the justification. If there's no accessible Buganizer project, then post the patch with the config change to Gerrit and make sure the commit message clearly states the reason the config is needed.

Config changes in frozen KMI kernels must not affect KMI.

Modifying core kernel code

Modifications to core kernel code in AOSP common kernels are discouraged. First send patches to upstream Linux and then backport them. If there's a good reason for a core kernel change, file a Buganizer issue clearly stating the request and the justification. No Android-specific features are accepted without a Buganizer issue. Send an email to kernel-team@android.com if you can't create a Buganizer issue.

Exporting symbols using via EXPORT_SYMBOL_GPL()

Don't send patches upstream that contain only symbol exports. To be considered for upstream Linux, additions of EXPORT_SYMBOL_GPL() require an in-tree modular driver that uses the symbol, so include the new driver or changes to an existing driver in the same patchset as the export.

When sending patches upstream, the commit message must contain a clear justification for why the patch is needed and beneficial to the community. Enabling exports to benefit out-of-tree drivers or functionality isn't a persuasive argument to upstream maintainers.

If for some reason, the patch can't be sent upstream, file a Buganizer issue and explain why the patch can't be sent upstream. Generally, symbols that are the supported interface to a kernel subsystem are likely to be accepted as exports. However, random internal helper functions are unlikely to be accepted and you'll be asked to refactor your code to avoid using them.

Adding a symbol to a KMI symbol list

The KMI symbol lists must be updated with GKI kernel symbols used by vendor modules. Because only KMI symbols are maintained as stable, GKI doesn't allow modules to load if they rely on a non-KMI symbol.

The extract_symbols script extracts the relevant symbols from a kernel build tree and can be used to update a KMI symbol list. Refer to the symbol listing documentation for further details.