Table of Contents
- Building a vanilla kernel
- Select configuration options
- Install the kernel
- Install the kernel modules
An ignorant man ages like an ox. His flesh may increase, but not his understanding.
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
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
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:
- Debian short guide
- Debian kernel handbook (detailed)
- Gentoo (genkern)
- Compile the mainline Linux kernel for Ubuntu
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, and will help you to understand some of the automated tool sets used by some distros.
In this tutorial I will be compiling as a user using ~/src as a working directory.
Install the development tools needed to compile
Debian / Ubuntu:
sudo apt-get install build-essential libncurses5-dev libssl-dev
dnf install ncurses-devel openssl-devel
dnf group install "Development Tools"
Obtain the kernel source code
The kernel source can be obtained from http://www.kernel.org/ . linux-4.11.6 was the most recent stable release available at the time of this update.
Extract the source
tar xvf linux-4.11.6.tar.xz
Apply any needed patches
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).
Test the patch:
patch --dry-run -p1 < 4200_fbcondecor.patch
Assuming there are no errors, apply the patch:
Note: fbcondecor is long in the tooth and there have been no comitts since 2012. With kernel 4.x I get messages about missing files in the kernel source, but the patches apply without problems except the missing source files.
Note: fbcondecor is long in the tooth and it is difficult to find themes. You can search the gentoo packages, but
patch -p1 < 4200_fbcondecor.patch
patch --dry-run -p1 > 4200_fbcondecor.patch
checking file Documentation/fb/00-INDEX
checking file Documentation/fb/fbcondecor.txt
checking file drivers/Makefile
Hunk #1 succeeded at 20 with fuzz 1 (offset 3 lines).
Hunk #2 succeeded at 54 (offset 5 lines).
checking file drivers/video/console/Kconfig
Hunk #1 succeeded at 151 (offset 21 lines).
checking file drivers/video/console/Makefile
checking file drivers/video/console/bitblit.c
checking file drivers/video/console/cfbcondecor.c
checking file drivers/video/console/fbcon.c
Hunk #3 succeeded at 281 (offset -2 lines).
Hunk #4 succeeded at 543 (offset -4 lines).
Hunk #5 succeeded at 1005 (offset -4 lines).
Hunk #6 succeeded at 1040 (offset -4 lines).
Hunk #7 succeeded at 1270 (offset 1 line).
Hunk #8 succeeded at 1294 (offset 1 line).
Hunk #9 succeeded at 1318 (offset 1 line).
Hunk #10 succeeded at 1844 (offset 1 line).
Hunk #11 succeeded at 1937 (offset 1 line).
Hunk #12 succeeded at 2087 (offset 1 line).
Hunk #13 succeeded at 2164 (offset 1 line).
Hunk #14 succeeded at 2201 (offset 1 line).
Hunk #15 succeeded at 2235 (offset 1 line).
Hunk #16 succeeded at 2278 (offset 1 line).
Hunk #17 succeeded at 2398 (offset 1 line).
Hunk #18 succeeded at 2594 with fuzz 1 (offset 9 lines).
Hunk #19 succeeded at 2738 (offset 9 lines).
Hunk #20 succeeded at 2768 (offset 9 lines).
Hunk #21 succeeded at 3033 (offset 9 lines).
Hunk #22 succeeded at 3085 (offset 9 lines).
Hunk #23 succeeded at 3727 (offset 9 lines).
checking file drivers/video/console/fbcondecor.c
checking file drivers/video/console/fbcondecor.h
checking file drivers/video/fbdev/Kconfig
Hunk #1 succeeded at 1228 (offset 12 lines).
checking file drivers/video/fbdev/core/fbcmap.c
Hunk #2 succeeded at 258 (offset 2 lines).
checking file drivers/video/fbdev/core/fbmem.c
checking file include/linux/console_decor.h
checking file include/linux/console_struct.h
checking file include/linux/fb.h
checking file include/uapi/linux/fb.h
checking file kernel/sysctl.c
Hunk #1 succeeded at 150 (offset 1 line).
Hunk #2 succeeded at 266 (offset -4 lines).
Kernel configuration is where the rubber hits the pavement. One of the most common mistakes 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 localmodconfig as this will detect and compile the modules (drivers) your system is currently using and write a .config file. Once you are comfortable with the configuration options move to make oldconfig or other options.
The config option is a command line tool and will ask, in order, each and every option, I do not advise using this method to write a .config file.
The option localmodconfig will use lsmod to examine what modules are currently in use, and then write 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
The localyesconfig option is similar to localmodconfg, but builds the drivers into the kernel rather then as modules. The result is a larger kernel that will boot faster.
Configuration using an oldconfig option
This option generates a configuration file 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-4.11.5-200.fc25.x86_64 ~/src/linux-4.11.6/.config
After running oldconfig , review the configuration with make 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 as localmodconfig or oldconfig .
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 than building a large kernel image, many drivers are loaded as modules.
See Modifying the Kernel to Improve Performance for a discussion on optimizing kernel performance.
xconfig and gconfig are graphical tools to configure your kernel. To use them you will need to install some dependencies.
Ubuntu / Debian
gconfig: libgtk2.0-dev libglib2.0-dev libglade2-dev
xconfig: qt3-devel libXi-devel
gconfig: gtk2-devel libglade2-devel
If you get an error:
No config file found at scripts/kconfig/streamline_config.pl line 110.
make: *** [localmodconfig] Error 2
make: *** [localmodconfig] Error 2
you need to first write a configuartion file using localmodconfig or oldconfig
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.
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:  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.
Use one of the methods listed below and then proceed to Compile section.
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 .
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
The fbcondecor option will be hidden unless you disable Tile Blitting Support.
Device Drivers ->
Graphics support ->
Support for frame buffer devices ->
Disable (hit "n" )'Enable Tile Blitting Support'
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 Guests see KVM Kernel Tuning .
The spice vdagent needs the kernel configuration option INPUT_UINPUT
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 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.
To enable Ecryptfs see Ecryptfs FAQ .
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
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
Installation requires root access. You may use su or sudo, I will use sudo to indicate root access is required.
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-4.11.6
Copy the config and System.map
sudo cp /boot/System.map-4.11.5-200.fc25.x86_64 /boot/System.map-4.11.6
sudo cp .config /boot/config-4.11.6
By default the modules will be built with debug information resulting in a huge /lib/modules/3.x.x directory, as much as 2 Gb or larger.
To reduce the size of your installed modules, set the INSTALL_MOD_STRIP environment variable to 1 when installing the modules
sudo INSTALL_MOD_STRIP=1 make modules_install
Make an initramfs
sudo update-initramfs -c -k 4.11.6
sudo dracut /boot/initramfs-4.11.6.img 4.11.6
configure your boot loader
For Fedora the grub menu is updated using grub2-mkconfig.
#Non EFI sudo update-grub Finally, time to boot into your new kernel. If all goes well you will have a nice new toy. 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 If all else fails, fall back to make oldconfig cp /boot/config-x.y.z . #copy a working config file from /boot I built a custom kernel on Fedora 15 optimized to be used in a KVM guest with selinux enabled. Default kernel 18.104.22.168-0.fc15.x86_64 custom (virtual) kernel
grub2-mkconfig -o /boot/grub2/grub.cfg
grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
size = 3.8M
total used free
Mem: 999 446 552
-/+ buffers/cache: 283 715
Startup finished in 991ms (kernel) + 2604ms (initrd) + 13815ms (userspace) = 17411ms
size = 2.9 M
total used free
Mem: 998 309 689
-/+ buffers/cache: 157 841
Startup finished in 5636ms (kernel) + 2507ms (initrd) + 9431ms (userspace) = 17575ms
Finally, time to boot into your new kernel. If all goes well you will have a nice new toy.
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
If all else fails, fall back to make oldconfig
cp /boot/config-x.y.z . #copy a working config file from /boot
I built a custom kernel on Fedora 15 optimized to be used in a KVM guest with selinux enabled.
Default kernel 22.214.171.124-0.fc15.x86_64
custom (virtual) kernel