B06c: Kernel modules
In this exercise, we will build our own kernel module for the kernel running on the CVD, and integrate that module into the AOSP build process.
We will be working with the cuttlefish emulator device again in this exercise. When working with the kernel and kernel builds, it is important to first understand what kernel we are working with before actually modifying anything.
Inspect the Cuttlefish kernel
Start a new session on the training VM and read the output of the lunch command carefully and note down the TARGET_ARCH value.
Open an adb shell and try to figure out what kernel is running (cf. uname(1)). There are multiple ways to do this.
Take note of the kernel name, then use the Documentation to parse the kernel version string.
Find the kernel in the AOSP source tree. Start with the kernel sub directory in the root directory. Use the information you have collected in the previous steps.
Take a look at the following resources for more information about the running kernel:
Tip
Upstream trims these pages down from time to time, so in case you cannot find the exact kernel version on the respective sub pages for the kernel version in use, just try the next link.
Tip
This page contains information on the build variant you will be using in the next steps.
Build a kernel module
In this step, coding is not required. Simply build the kernel module "as is" from the branch mentioned in the instructions below.
A kernel build environment has been prepared for you on the training VMs in the kernel-gki-android15-6.6 directory.
For reference, the steps to create this environment are as follows:
KERNEL_BUILD_DIR=${HOME}/kernel-gki-android15-6.6 mkdir -p "${KERNEL_BUILD_DIR}" cd "${KERNEL_BUILD_DIR}" repo init -u https://android.googlesource.com/kernel/manifest -c -b common-android15-6.6 repo sync -c -j6 # Check out the kernel sources matching the kernel running in cvd git -c common checkout 02f25b80c91cf5abf216b99ded16570c8cc87dd4
Enter the kernel build directory in a fresh shell session on the training VM. Do not run lunch or build/envsetup.sh in this session.
cd kernel-gki-android15-6.6
The kernel build environment contains the kleaf and bazel wrappers. To use these in the following steps, add them to your $PATH environment variable:
KERNEL_BUILD_DIR=${HOME}/kernel-gki-android15-6.6 export PATH="${KERNEL_BUILD_DIR}/tools:${PATH}"
Info
You will have to do this every time you open a new shell. In a more persistent setup, you would either set the $PATH variable in your shell configuration files or install bazel with your operating system's package manager.
For this training exercise, that kind of overhead is not required.
Before we can build the kernel, we need to identify the bazel build target (similar to a make target). bazel has a query feature that allows listing kernels. The target notation syntax might seem odd at first: it is not 100% accurate to think of the part between "//" and ":" as a directory path relative to the project root "//" but this simplification helps a lot in understanding what is going on. Check out the respective directories in the kernel source tree when running the query commands below. There are a lot of build files used to configure the individual variants:
# Get help regarding the target syntax: bazel help target-syntax # List all common kernel targets bazel query "kind('py_binary', //common:*)" # List all virtual device targets bazel query "kind('py_binary', //common-modules/virtual-device:*)"
Now, let's finally build some kernels!
bazel build //common:kernel_x86_64
Integrate our kernel modules into the source tree
With Android 15, we use in-tree builds:
git clone https://github.com/inovexAcademy/aosp-aaos-training.git vendor/inovex
Read and understand the BUILD.bazel file in ${KERNEL_BUILD_DIR}/vendor/inovex/kernel-module.
Build the kernel module:
bazel build //vendor/inovex/kernel-module:all
After having completed the above steps successfully, you will find your kernel module files in ${KERNEL_BUILD_DIR}/bazel-bin/vendor/inovex/kernel-module/. There are multiple sub-directories, per target and per build type/mode.
In the following steps we will be using the *.ko files found in the main directories. You can inspect them using the following commands:
ls -lh bazel-bin/vendor/inovex/kernel-module/training_mod/*.ko modinfo bazel-bin/vendor/inovex/kernel-module/training_mod/*.ko
Deploy a kernel module
Manually deploy kernel module
In order to quickly test your kernel module, push it onto the running Cuttlefish device and load it. This approach is insufficient for building an actual product, however, it is very useful for quick development iterations.
# We need root privileges to load kernel modules. Do this first: adb root # Push the module: adb push bazel-bin/vendor/inovex/kernel-module/training_mod/aosp_training_sysfs.ko /tmp/ # Load the module adb shell insmod /tmp/aosp_training_sysfs.ko # Let's check if our module has actually been loaded. Pay attention to the usage numbers: adb shell lsmod | grep training # Let's see if our module is actually providing the expected information in sysfs: adb shell cat /sys/kernel/aosp_training/read_me # Unload the kernel module again adb shell rmmod aosp_training_sysfs
Integrate kernel module into AOSP source tree
To include your kernel modules in the AOSP build for the cuttlefish device, we need to tell the build system about them. First, we want to copy the modules to the AOSP tree, to the vendor/inovex folder:
cd ~/android mkdir -p vendor/inovex cp ~/kernel-gki-android15-6.6/bazel-bin/vendor/inovex/kernel-module/training_mod/aosp_training*.ko vendor/inovex
In the next step, the build system needs to be told to include these modules. For the cuttlefish device, this is controlled by the device/google/cuttlefish/shared/BoardConfig.mk file. Here we can add our module to be included for cuttlefish.
Looking at the documentation by Google we see that a variable named BOARD_VENDOR_KERNEL_MODULES is used.
So at the end of device/google/cuttlefish/shared/BoardConfig.mk add:
BOARD_VENDOR_KERNEL_MODULES += \
vendor/inovex/aosp_training_sysfs.ko
and run m. After building the system, restart the CVD. The modules should then be available and loaded automatically:
adb root # Let's see if our modules are actually providing the expected information in sysfs: adb shell cat /sys/kernel/aosp_training/read_me