Dhammapada
Restrained of hand, restrained of foot, restrained of speech and restrained in his highest faculty, with his joy turned inwards, his mind still, alone and contented - that is what they call a bhikkhu.
Introduction
Reasons to compile a custom kernel:
- You distributions default kernel does not support your hardware or you need to apply a patch. Personally I have used the staging driver for the GMA500 (psb), an occasional wireless driver, openvz, grsecurity, and fbcondecor.
- To reconfigure (optimize) your kernel. This can vary from performance tuning to removing 'unnecessary' drivers included in your distributions 'generic' kernel. For example see this page for kernel optimization used with KVM guests.
- To learn more about the kernel or if you are a kernel developer.
Reasons NOT to compile a custom kernel:
- You will lose support from your distro. The support for kernel customization is zero on Launchpad, bugzilla, etc.
- Fedora 'one should NOT expect support from the Fedora kernel team, you're pretty much on your own here if something doesn't work as you'd hoped or expected.'
- Ubuntu 'Building and using a custom kernel will make it very difficult to get support for your system. While it is a learning experience to compile your own kernel, you will not be allowed to file bugs on the custom-built kernel (if you do, they will be Rejected without further explanation).'
Compile as root or as a user:
Although you may compile the kernel either as root or as a user, you will need root access to install the kernel, install the kernel modules, and configure the boot loader.
When compiling as root, most tutorials will use /usr/src/linux as a working directory. The source code is extracted into /usr/src/linux-x.y.x (x.y.z = kernel version #) and a link is made from /usr/src/linux-x.y.x to /usr/src/linux .
When compiling as a user, use a location in your home directory. I personally use ~/src
Vanilla kernel
A "Vanilla" or stable kernel is obtained from The Linux Kernel Archives .
Kernel development follows a time-based process with new features / patches added during the release cycle.
At the beginning of each release cycle, the features and patches deemed stable enough for inclusion are merged into the mainline kernel.
The next kernel is the set of patches submitted for consideration for inclusion the "next" release cycle.
For a more detailed discussion of the kernel development cycle and terminology see : kernel.org - HOW THE DEVELOPMENT PROCESS WORKS
Distribution kernels
Many distributions, Fedora and Ubuntu included, provide a modified kernel with patches or customized configurations, selinux and apparmor for example. In addition, scripts are provided to automate kernel compilation including configuration, packaging (.deb or .rpm), installation, and updating grub. While these scripts automate the process, they are going to by definition be somewhat distribution centric.
Ubuntu offers several optimized kernels called Ubuntu kernel flavors. Common flavors are generic, pae, server, virtual, xen-dom0 and you may examine the .config file for additional details.
For distribution specific guides see:
Other kernels
In addition pre-compiled kernels are supplied by other third parties. For example, the zen kernel AKA liquorix on Debian/Ubuntu is optimized for desktops and multimedia. The zen (liquorix) includes code (patches) outside the mainline kernel and uses configuration options to gain performance at the potential expense of stability.
Building a vanilla kernel
Learning to compile a Vanilla kernel is a great first step , and will help you to understand some of the automated tool sets used by some distros.
In this tutorial I will be be compiling as a user using ~/src as a working directory.
mkdir ~/src
cd ~/src
Install the development tools needed to compile
Debian / Ubuntu:
sudo apt-get install build-essential libncurses5-dev
Fedora:
yum install ncurses-devel
yum groupinstall "Development Tools"
Obtain the kernel source code
The kernel source can be obtained from http://www.kernel.org/ . linux-3.0.8 was the highest stable version available at the time of this writing.
wget http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.0.8.tar.bz2
Extract the source
tar xvf linux-3.0.8.tar.bz2
cd ~/src/linux-3.0.8
Apply any needed patches
In this example I will use fbcondecor as it is a small, but fun patch that adds decoration to you console.
Note: fbcondecor requires additional configuration beyond patching and compiling the kernel. See the links below for distribution specific advice (I have only done this in gentoo, not sure if it works for ubuntu).
cd ~/src/linux-3.0.8
wget http://dev.gentoo.org/~spock/projects/fbcondecor/archive/fbcondecor-0.9.6-3.0-rc2.patch
Test the patch:
patch --dry-run -p1 < fbcondecor-0.9.6-3.0-rc2.patch
Assuming there are no errors, apply the patch:
patch -p1 < fbcondecor-0.9.6-3.0-rc2.patch
patching file Documentation/fb/00-INDEX
patching file Documentation/fb/fbcondecor.txt
patching file drivers/Makefile
patching file drivers/video/Kconfig
patching file drivers/video/console/Kconfig
patching file drivers/video/console/Makefile
patching file drivers/video/console/bitblit.c
patching file drivers/video/console/cfbcondecor.c
patching file drivers/video/console/fbcon.c
patching file drivers/video/console/fbcondecor.c
patching file drivers/video/console/fbcondecor.h
patching file drivers/video/fbcmap.c
patching file drivers/video/fbmem.c
patching file include/linux/console_decor.h
patching file include/linux/console_struct.h
patching file include/linux/fb.h
patching file kernel/sysctl.c
Kernel configuration
Kernel configuration is where the rubber hits the pavement.The most common mistake made when learning to compile a kernel is to try to write a configuration file from scratch. The result is either you compile a kernel without sufficient drivers to run on your hardware or rapidly become overwhelmed with the options.
The configuration file is called ".config" and is written by make using one of the configuration options. Common options are:
config - Update current config utilising a line-oriented program
menuconfig - Update current config utilising a menu based program
xconfig - Update current config utilising a QT based front-end
gconfig - Update current config utilising a GTK based front-end
oldconfig - Update current config utilising a provided .config as base
localmodconfig - Update current config disabling modules not loaded
localyesconfig - Update current config converting local mods to core
silentoldconfig - Same as oldconfig, but quietly, additionally update deps
defconfig - New config with default from ARCH supplied defconfig
If you are building a kernel for the fist time, I highly suggest you start with make oldconfig . Once you are comfortable with the configuration options move to make localmodconfig .
Use one of the methods listed below and then proceed to Compile section.
The config option is a command line tool and will ask, in order, each and every option, do not use this tool.
Easy configuration
The easy way to start with a custom kernel is to use an old, working configuration file from any distribution. A copy of the configuration file is saved for you in /boot. Simply copy the configuration, use make oldconfig to generate a .config file using the old as a template. You will be asked to answer any questions regarding new features and are safe using the defaults (hit the enter key). It is the prudent to review the configuration changes with make menuconfig .
cp /boot/config-2.6.40.6-0.fc15.x86_64 ~/src/linux-3.0.8/.config
make oldconfig
make menuconfig
menuconfig
menuconfig is a command line, ncurses, menu driven interface used to configure your kernel options. I typically use menuconfig to review and fine tune my configuration after using other tools such a oldconfig or localmodconfig .
You can obtain additional information at any time using the "h" hotkey.
Use the arrow keys to navigate up and down through the menu options. Items marked with a ---> are sub menus, use the enter key to enter into the sub menu.
To configure a driver, use "n" to remove a driver, "y" to compile the driver into the kernel, and "m" to compile it as a module. The modules you are currently using can be listed with lsmod
The linux kernel is modular and modules (drivers)can be loaded as needed. In fact, if you examine the configuration file from most distros you will see, rather then building a large kernel image, many drivers are loaded as modules.
See this link for a discussion on kernel modules.
Graphical tools
xconfig and gconfig are graphical tools to configure your kernel. To use them you will need to install some dependencies.
Ubuntu / Debian
menuconfig: libncurses5-dev
xconfig: libqt3-mt-dev
gconfig: libgtk2.0-dev libglib2.0-dev libglade2-dev
Fedora
menuconfig: ncurses-devel
xconfig: qt3-devel libXi-devel
gconfig: gtk2-devel libglade2-devel
localmodconfig
If you feel ready to build a more custom kernel, use localmodconfig . This will use lsmod to examine what modules are currently in use, and then configure your .config to build only those modules. The result is a shorter compilation time and a kernel and modules specific to your hardware.
localmodconfig must be run from a working 'generic' kernel with the drivers for your hardware loaded as modules. Otherwise, lsmod will not identify drivers built into the kernel, and localmodconfig will not work as expected.
After running localmodconfig , review the configuration with make menuconfig
If you get an error:
No config file found at scripts/kconfig/streamline_config.pl line 110.
make[1]: *** [localmodconfig] Error 2
make: *** [localmodconfig] Error 2
copy your configuration file from /boot
cp /boot/config-2.6.40.6-0.fc15.x86_64 ~/src/linux-3.0.8/.config
make localmodconfig
make menuconfig
localyesconfig is similar, but builds the drivers into the kernel. The result is a larger kernel that will boot faster.
Kernel configuration from scratch using a kernel seed
For a minimal, default configuration see kernel seeds. If you want to learn kernel configuration in detail, this site has a wealth of additional information and the kernel seeds are a great start. BE WARNED - These seeds are minimal and you will almost certainly need to know your hardware in order to add in drivers.
The "problem" with using the above method is that the kernel seed is indeed a minimal configuration and anticipate the need to identify your hardware and enable additional drivers.
Use lspci -v to identify your hardware and kernel drivers required.
lspci -v
00:04.0 Audio device: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (rev 01)
Subsystem: Red Hat, Inc Device 1100
Flags: bus master, fast devsel, latency 0, IRQ 11
Memory at f8040000 (32-bit, non-prefetchable) [size=16K]
Capabilities: [50] MSI- Enable- Count=1/1 Maskable- 64bit+
Kernel driver in use: HDA Intel
00:01.2 USB Controller: Intel Corporation 82371SB PIIX3 USB [Natoma/Triton II[ (rev 01) (prog-if 00 [UHCI])
Subsystem: Red Hat, Inc Qemu virtual machine
Flags: bus master, fast devsel, latency 0, IRQ 11
I/O ports at c020 [size=32]
Kernel driver in use: uhci_hcd
From the above output we can determine we need to compile a kernel with the HAD Intel and uhci_hcd drivers. To find and enable them, run make menuconfig and enable the driver or if you can not locate them use the search function. To search for a driver option, hit the "/" key and enter your search parameters in the box. If all else fails, use google.
Select configuration options
This section is optional and is for advice on enabling specific drivers. The information will be helpful to those using a kernel seed .
GMA500
As of kernel 3.1.4, support for the GMA500 is in the staging drivers. The option may he hidden or may not be obvious.
To compile the driver, DRM_PSB, you have to enable the following options in the Device Drivers section :
- Graphics Support -> Direct Rendering Manager
- Staging Drivers -> Intel GMA5/600 KMS Framebuffer
fbcondecor
The fbcondecor option will be hidden unless you disable Tile Blitting Support.
Navigate to:
Device Drivers ->
Graphics support ->
Support for frame buffer devices ->
Disable (hit "n" )'Enable Tile Blitting Support'
Enable fbcondecor
Navigate to:
Device Drivers ->
Graphics Support ->
Console Display Driver Support ->
Support for Framebuffer Console Decorations #hit "y"
LVM and RAID
Device Drivers --->
Multiple devices driver support (RAID and LVM) --->
[*] Multiple devices driver support (RAID and LVM)
< > RAID support
<M> Device mapper support
KVM optimization
KVM Guests see KVM Kernel Tuning .
The spice vdagent needs the kernel configuration option INPUT_UINPUT
I do have some .config you can use as a seed for KVM guests including server with selinux and server without selinux and desktop with selinux.
SELinux
Selinux is a part of the mainline kernel and thus no patch is required.
See the gentoo selinux page for a concise overview of the kernel configuration options.
grsecurity
grsecurity is a kernel patch to increase security and is used in the gentoo-hardened kernel.
See the gentoo grsecurity page for a concise overview of kernel configuration options.
Ecryptfs
To enable Ecryptfs see Ecryptfs FAQ .
Compile
Compiling the kernel is the easy part, but may take some time depending on the speed of your processor. You can speed up the process by running multiple jobs. Typically the number of jobs is specified with the -j option and is = the number of CPU + 1
make -j5
Recite the ancient incantations
Then compile the modules
make -j5 modules
Recompile a kernel
Somewhere in the course of compiling kernels you will inevitably need a re-do. You have a few options to make things faster.
First, if you simply need to compile a module, edit your .config file and run make modules && sudo make modules_install .
If you are compiling new options into the kernel itself, simply re-run make make -j5
If you want a fresh start, run make clean
Install
Installation requires root access. You may use su or sudo, I will use sudo to indicate root access is required.
sudo make modules_install
Copy the new kernel to boot (arch/x86_64/boot/bzImage is a link to arch/x86/boot/bzImage so the following command works on both 32 AND 64 bit arch.)
sudo cp arch/x86/boot/bzImage /boot/vmlinuz-3.0.8
Copy the config and System.map
sudo cp System.map /boot/System.map-3.0.8
sudo cp .config /boot/config-3.0.8
Make a initramfs
Debian/Ubuntu:
sudo update-initramfs -c -k 3.0.8
Fedora
sudo dracut /boot/initramfs-3.0.8.img 3.0.8
configure your boot loader
Fedora 16 is now using grub2 so it is trivial to update your boot menu.
sudo update-grub
Reboot
Finally, time to boot into your new kernel. If all goes well you will have a nice new toy.
Troubleshooting
The most common reason a kernel will not boot is a missing driver. Boot an older, working kernel and review the modules and drivers in use and check to see the appropriate drives are compiled.
lsmod lspci -v
google search any driver listed in lspci you are unfamiliar with.
You can also try using make localmodconfig
make localmodconfig
make menuconfig
If all else fails, fall back to make oldconfig
cp /boot/config-x.y.z . #copy a working config file from /boot
make oldconfig
Results
I built a custom kernel on Fedora 15 optimized to be used in a KVM guest with selinux enabled.
Default kernel 2.6.40.6-0.fc15.x86_64
size = 3.8M
free -m
total used free
Mem: 999 446 552
-/+ buffers/cache: 283 715
root@Fedora:~#systemd-analyze
Startup finished in 991ms (kernel) + 2604ms (initrd) + 13815ms (userspace) = 17411ms
custom (virtual) kernel
size = 2.9 M
free -m
total used free
Mem: 998 309 689
-/+ buffers/cache: 157 841
root@Fedora:~#systemd-analyze
Startup finished in 5636ms (kernel) + 2507ms (initrd) + 9431ms (userspace) = 17575ms