Building the Linux Kernel for Raspberry Pi 5
Building the Linux Kernel for Raspberry Pi 5
The Raspberry Pi 5, powered by the Broadcom BCM2712 (quad-core Cortex-A76 at 2.4GHz), represents a significant leap in ARM SBC performance. Building a custom kernel unlocks hardware-specific optimizations, debugging capabilities, and the ability to patch or extend kernel functionality.
This guide covers cross-compilation from an x86_64 host, kernel configuration for debugging, and deployment to a running Pi 5.
Hardware Context
The BCM2712 SoC features:
- CPU: Quad Cortex-A76 (ARMv8.2-A) @ 2.4GHz
- GPU: VideoCore VII
- PCIe: Gen 2.0 x1 (exposed via RP1 southbridge)
- Memory: LPDDR4X (4GB/8GB variants)
The RP1 southbridge is a new addition that handles GPIO, USB, Ethernet, and other I/O—requiring specific kernel support via rp1 drivers.
Development Environment Setup
Cross-Compilation Toolchain
Cross-compiling on an x86_64 host is significantly faster than native compilation on the Pi.
# Debian/Ubuntu - Install ARM64 cross-compiler
sudo apt update
sudo apt install -y \
crossbuild-essential-arm64 \
gcc-aarch64-linux-gnu \
binutils-aarch64-linux-gnu \
libncurses-dev \
bison \
flex \
libssl-dev \
libelf-dev \
bc \
git \
make
# Verify toolchain
aarch64-linux-gnu-gcc --version
Kernel Source
The Raspberry Pi Foundation maintains a fork with BCM2712 and RP1 support:
# Clone the Pi kernel (use depth=1 for faster clone)
git clone --depth=1 --branch rpi-6.6.y \
https://github.com/raspberrypi/linux.git rpi-linux
cd rpi-linux
# Check available Pi 5 branches
git branch -r | grep rpi-6
The rpi-6.6.y branch is the current LTS with full Pi 5 support. For bleeding-edge features, use rpi-6.8.y or later.
Kernel Configuration
Base Configuration for Pi 5
Start with the official Pi 5 defconfig:
# Set cross-compile environment
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
# Generate Pi 5 default config
make bcm2712_defconfig
# View the generated config
head -50 .config
The bcm2712_defconfig enables:
- BCM2712 SoC support
- RP1 southbridge drivers
- VideoCore VII GPU
- PCIe controller
- LPDDR4X memory controller
Interactive Configuration
make menuconfig
Navigate using arrow keys, Enter to select, Space to toggle. Key sections:
General Setup
General setup --->
[*] Kernel .config support
[*] Enable access to .config through /proc/config.gz
(-rpi5-custom) Local version - append to kernel release
Processor Features
Kernel Features --->
Preemption Model (Voluntary Kernel Preemption) --->
(X) Preemptible Kernel (Low-Latency Desktop)
Timer frequency (1000 HZ) --->
For real-time workloads, enable PREEMPT_RT if available in your branch.
Debug Configuration
Kernel debugging is essential for driver development and crash analysis.
Enable Core Debug Options
# Apply debug config fragment
cat >> .config << 'EOF'
# Debug Information
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF5=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_GDB_SCRIPTS=y
# Kernel Address Sanitizer (KASAN)
CONFIG_KASAN=y
CONFIG_KASAN_GENERIC=y
CONFIG_KASAN_INLINE=y
# Lock Debugging
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
CONFIG_LOCKDEP=y
# Memory Debugging
CONFIG_DEBUG_SLAB=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_MEMORY_INIT=y
# Stack Protection
CONFIG_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_STRONG=y
# Function Tracing
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_DYNAMIC_FTRACE=y
CONFIG_STACK_TRACER=y
# Kernel Crash Dumps
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
# Magic SysRq (emergency debugging)
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
EOF
# Merge and validate config
make olddefconfig
KGDB: Kernel Debugger
Enable remote debugging via serial:
cat >> .config << 'EOF'
# KGDB Configuration
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_KGDB_KDB=y
CONFIG_KDB_KEYBOARD=y
CONFIG_FRAME_POINTER=y
EOF
make olddefconfig
Boot parameters for KGDB:
kgdboc=ttyAMA0,115200 kgdbwait
Kernel Symbols and Kallsyms
# Ensure symbol table is included
scripts/config --enable CONFIG_KALLSYMS
scripts/config --enable CONFIG_KALLSYMS_ALL
This enables /proc/kallsyms for symbol resolution in crash dumps and tracing.
Cross-Compilation
Build the Kernel
# Set environment (if not already set)
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
# Clean build (optional, use for fresh builds)
make mrproper
make bcm2712_defconfig
# Build with parallel jobs
make -j$(nproc) Image.gz modules dtbs
# Build time: ~15-30 min on modern 8-core x86_64
Build artifacts:
arch/arm64/boot/Image.gz- Compressed kernel imagearch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb- Device Tree Blob
Inspect Build Output
# Check kernel version
file arch/arm64/boot/Image.gz
# List built modules
find . -name "*.ko" | wc -l
# Verify DTB
fdtdump arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb | head -30
Deployment to Raspberry Pi 5
Prepare the Target
On the Pi 5, ensure SSH is enabled and note the boot partition:
# On the Pi - check current kernel
uname -r
# Identify boot partition (usually /boot/firmware on Bookworm)
mount | grep boot
ls /boot/firmware/
Install Modules
# On build host - create module staging directory
export INSTALL_MOD_PATH=./modules_install
make modules_install
# Package for transfer
tar czf modules.tar.gz -C modules_install lib
# Transfer to Pi
scp modules.tar.gz pi@raspberrypi.local:/tmp/
On the Pi:
# Backup existing modules
sudo cp -r /lib/modules/$(uname -r) /lib/modules/$(uname -r).bak
# Extract new modules
sudo tar xzf /tmp/modules.tar.gz -C /
Install Kernel and DTBs
From build host:
# Copy kernel
scp arch/arm64/boot/Image.gz pi@raspberrypi.local:/tmp/kernel8.img
# Copy DTBs
scp arch/arm64/boot/dts/broadcom/bcm2712*.dtb pi@raspberrypi.local:/tmp/
On the Pi:
# Backup current kernel
sudo cp /boot/firmware/kernel8.img /boot/firmware/kernel8.img.bak
# Install new kernel
sudo cp /tmp/kernel8.img /boot/firmware/kernel8.img
# Install DTBs
sudo cp /tmp/bcm2712*.dtb /boot/firmware/
# Update config.txt if needed
sudo nano /boot/firmware/config.txt
Ensure config.txt contains:
[pi5]
kernel=kernel8.img
arm_64bit=1
Reboot and Verify
sudo reboot
# After reboot
uname -r
# Should show: 6.6.x-rpi5-custom (or your local version string)
# Verify debug features
cat /proc/config.gz | gunzip | grep CONFIG_DEBUG_INFO
Using Debug Features
Function Tracer (ftrace)
# Mount debugfs if not mounted
sudo mount -t debugfs none /sys/kernel/debug
# Enable function tracing
cd /sys/kernel/debug/tracing
echo function > current_tracer
echo 1 > tracing_on
# Trace specific functions
echo 'bcm2712*' > set_ftrace_filter
cat trace
# Disable
echo 0 > tracing_on
KASAN Reports
When KASAN detects a memory error, it logs detailed reports to dmesg:
dmesg | grep -A20 "KASAN"
Example output:
BUG: KASAN: slab-out-of-bounds in some_function+0x42/0x100
Read of size 4 at addr ffff000012345678 by task test/1234
Kernel Crash Analysis
If the kernel panics, use crash tool with vmlinux:
# On build host - keep vmlinux for debugging
cp vmlinux /safe/location/vmlinux-$(make kernelrelease)
# Analyze crash dump
crash vmlinux /var/crash/vmcore
Performance Tuning Options
For production kernels, disable debug options and enable:
# Performance-oriented config
scripts/config --disable CONFIG_DEBUG_INFO
scripts/config --disable CONFIG_KASAN
scripts/config --enable CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
# CPU frequency scaling
scripts/config --enable CONFIG_CPU_FREQ_GOV_PERFORMANCE
scripts/config --enable CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
# Memory optimization
scripts/config --enable CONFIG_TRANSPARENT_HUGEPAGE
scripts/config --enable CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS
make olddefconfig
Troubleshooting
Boot Failures
If the Pi doesn't boot:
- Connect HDMI to see early boot messages
- Use serial console (GPIO 14/15 for UART)
- Restore backup kernel:
# From another machine, mount the SD card
sudo cp /mnt/boot/kernel8.img.bak /mnt/boot/kernel8.img
Missing Modules
If modules fail to load:
# Check module dependencies
depmod -a $(uname -r)
# Verify module path
ls /lib/modules/$(uname -r)/
Device Tree Issues
If hardware isn't detected:
# Check loaded DTB
cat /proc/device-tree/model
# Compare with expected
dtc -I fs /proc/device-tree | grep compatible
Automation Script
Save this as build-pi5-kernel.sh:
#!/bin/bash
set -e
KERNEL_DIR="${1:-rpi-linux}"
PI_HOST="${2:-raspberrypi.local}"
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
cd "$KERNEL_DIR"
echo "Building kernel..."
make -j$(nproc) Image.gz modules dtbs
echo "Installing modules locally..."
rm -rf ../modules_install
make INSTALL_MOD_PATH=../modules_install modules_install
echo "Packaging..."
tar czf ../kernel-package.tar.gz \
arch/arm64/boot/Image.gz \
arch/arm64/boot/dts/broadcom/bcm2712*.dtb \
-C ../modules_install lib
echo "Deploying to $PI_HOST..."
scp ../kernel-package.tar.gz pi@$PI_HOST:/tmp/
ssh pi@$PI_HOST << 'REMOTE'
sudo cp /boot/firmware/kernel8.img /boot/firmware/kernel8.img.bak
cd /tmp && tar xzf kernel-package.tar.gz
sudo cp Image.gz /boot/firmware/kernel8.img
sudo cp bcm2712*.dtb /boot/firmware/
sudo tar xzf kernel-package.tar.gz -C / lib
sudo depmod -a
echo "Kernel deployed. Reboot to activate."
REMOTE
echo "Done!"
Conclusion
Building a custom kernel for the Raspberry Pi 5 enables debugging capabilities unavailable in stock kernels, hardware-specific optimizations, and the foundation for driver development.
Key takeaways:
- Use
bcm2712_defconfigas the starting point - Enable KASAN, LOCKDEP, and ftrace for debugging
- Cross-compile for faster iteration
- Always keep backup kernels
Combined with kernel patching techniques, you can contribute fixes back to the Raspberry Pi kernel tree or the mainline Linux kernel.
Happy hacking!