Compiling your own Linux kernel is the first step in optimizing your system performance. Creating it with exactly what you need, will decrease your boot time and memory usage and this will also be a good way to support recent devices that your distribution kernel do not support yet. Nevertheless, you will need a deep knowledge of the computer capabilities and device you have inside it. As an example I will take the Intel DH67 motherboard family with a base Debian Squeeze system installed. That family of card use the new Sandy Bridge chipset where Ethernet chip is supported since 2.6.38 version of the kernel and graphic chip the 3.0.0 version. To be able to install the Debian Squeeze I was forced to put a temporary network card on the only PCI slot of the board (a RTL8139 family card). Please note that some version of that board family have an unsupported PCI-Express to PCI bridge (like on DH67GD-B3, while it’s working on DH67BL-B3), so you may need a PCI-Express card if you are in that case. An other possibility to install the system and what you need to build your own kernel is to put the hard drive in an other computer with older and well supported devices. Note that if you proceed with this tutorial without any modification you have to be root nearly all the time so use the “su” or sudo “/bin/bash” command now to login as root. All this is fully functionnal with Debian based systems (including Ubuntu).
The only needed package to be installed on a Debian system to build a new kernel is build-essential and libncurses5-dev:
apt-get install build-essential libncurses5-dev
build-essential is a meta package that will install make, gcc, g++ (unneeded for the kernel), libc6-dev and make. libncurses5-dev will allow you to use ncurses interface to configure your build options (optional but highly recommended). Note that autoconf, automake and libtool are not needed for the kernel oppositely to most of the classic source packages on Linux systems. Note that if you are not using Debian you will need the GNU Make tool, the GNU C compiler and the GNU libc6 headers and the NCurses library headers. This could work as well with non-GNU tools but this is at your own risk and may require different procedure that the one given here. Nevertheless, BSD tools are known to work correctly. Now you have to download a Linux kernel. The better is to download the latest, unless you are stability/security paranoid. If you are in that case, you can choose a kernel with four numbers. I explain: new versions are noted x.y.z but security revision have an extra version number x.y.z.r. Note that there’s no big changes in 3.0.0 series of the kernel. The major version change was only chosen to celebrate the 20th anniversary of Linux so for packagers it’s still the 2.6 series. You will find source code archives for the kernel here: http://www.kernel.org or on mirrors (mirror list available here: http://www.kernel.org/mirrors/). For the motherboard of my example I recommend 3.0.4 version of the kernel so the commands will be:
# be sure to be root before proceeding cd /usr/src wget "ftp://ftp.free.fr/pub/linux/kernel/v3.0/linux-3.0.4.tar.bz2" tar -xvf linux-3.0.4.tar.bz2 ln -sv linux-3.0.4 linux
Now let’s explain that. We go in /usr/src where some extra kernel module suspect to find kernel source code (eg. NVidia drivers). Then, we download kernel source code archive and extract it. The last line is a compatibility symlink to the version of the kernel we will use (this suppose this will be our default kernel version) to allow compilation of extra kernel modules (some packages may also need access to kernel source code in order to compile). If you do not project to compile anything else you can safely place your kernel source in a home directory and not be root (skip first and second line).
Now this will be the hard things… You’ll have to configure your kernel accordingly with what you have. There’s way to get informations on your system: commands like lspci and lsmod will give you respectively the name of the devices on the motherboard and lsmod the list of the modules that the current kernel is using (but you may need more). The more useful is lsmod but this will not help you with current kernel’s unsupported hardware and with hardware that are not managed by modules. So for that second reason I recommend to start that way:
cd /usr/src/linux make mrproper cp /boot/config-<your-current-version-of-the-kernel> ./.config lsmod > hard-infos.txt echo "--------------------------------------------------------------------" >> hard-infos.txt lspci >> hard-infos.txt #you should print the hard-infos.txt file now or display it on an other screen using ssh or a new console (alt+f1 to alt+f6 to change console) make menuconfig
The “make mrproper” line will deeply clean the source tree and any previous configuration. If you want to keep an old configuration to recompile the kernel, just replace mrproper by clean. The cp line allow us to get the actually running configuration of the kernel. This is a good idea as this allow to get some distribution specific configuration options. All the lines finishing with hard-infos.txt will create that file containing all the useful information you may need about your hardware. Last but not least the make menuconfig line will show you the kernel configuration menu after a short compile time.
Now there’s no secret, take your time and go everywhere. You will need about two hours of brain torture doing that correctly and deeply. If you don’t understand a config option try the help button or googlise it, and if you still do not understand, leave it as default. Here is some advises:
- In “Processor type and feature” take the nearest processor you have. Depending on running 64 bits or 32 bits system (or non intel architectures) the list will change accordingly to what is possible. In doubt choose the option beginning by “Generic”.
- For more performance it’s a good thing to change all your needed device modules in integrated version, but you will loose in flexibility so the kernel you will have will be specific to your motherboard and devices installed. If you change hardware you will need a generic kernel (eg. from your distribution). [ ] mean not compiled at all, [M] mean compiled as module and [*] mean compiled as integrated in the core kernel (habitually called vmlinuz-<version> in the boot directory. Sometimes you will have < >, <M> or <*> instead of [ ], [M] or [*]: that means that the option will allow access to more options either in an other menu or in a direct submenu of that option. Be careful, do not try to put everything as integrated, the kernel will be to big and will not boot. Sometimes you will not be able to turn modules in integrated. This is because of dependencies: you can’t turn integrated modules that depends on an other module: you’ll have to turn parent module integrated before. That’s why I recommend two pass to do it.
- To know what device you’ll need the generated file hard-info.txt will provide you a good help. The lsmod part will give you the name of the modules. In configuration the help button will give you informations about the option. You will find at the end of the description a line beginning that way: “Symbol:”. What is following is either the name of the module or a part of it (you may have a prefix on some submenus).
- I think it’s a good idea to leave USB part as unchanged. That way every devices you may connect on the machine via USB will be supported correctly and the corresponding module loaded as needed.
- Even if you do not have SCSI devices, do not try to turn off SCSI subsystem as all hard-drive (or CD-ROM drives) technologies are using an SCSI emulation since 2.6 series of the kernel. Elsewhere your system will not boot.
- The network feature part is by far the more complicated. It is safe to turn modules in their integrated versions but I do not recommend make any other change unless you know exactly what you’re doing.
- If you plan to compile a kernel for a server in a critical zone in term of security or stability, you should disable every experimental features. Nevertheless, some recent devices may be unusable.
- If you have the chance to have an Intel DH67 series motherboard you can directly download my .config file (75 KB) and skip configuration… If you are very lazy you can even download a precompiled version (30.2 MB). Just untar the file from the root directory and skip the next paragraph. Be careful: those both files are for Intel DH67 series motherboard ONLY with no extra hardware except eventual USB devices. This will not work on any other motherboard.
When configuration is done, you can start compilation. Just run the command “make”. This will take some time so you can go take a well deserved break. If compilation fail (in some rare case) that mean something is wrong with your configuration. After the compilation is done with no error, you need to install the freshly compiled kernel correctly that way (I suppose you are root and in your kernel source directory):
make modules_install cp -fv arch/x86_64/boot/bzImage /boot/vmlinuz-3.0.4 cp -fv .config /boot/config-3.0.4 cp -fv System.map /boot/System.map-3.0.4 mkinitramfs -o /boot/initrd.img-3.0.4 3.0.4
The first line will install modules in a predefined and correct place of the file hierarchy. The second line install the kernel itself but may change if you have non Intel or AMD 64 bits architecture. In that case, you will have to replace x86_64 with the good directory corresponding on your architecture. The next lines copy files needed by the kernel or the bootloader to boot correctly. Note that if we have done a correct configuration without modules (except USB) the mkinitramfs will not be needed (unless you have USB keyboard). mkinitramfs create a RAM disk image mounted by the kernel allowing it to find modules needed to boot before it mount the root filesystem.
Now we just have to make our new kernel bootable. And this is a problem, the procedure and/or config files regarding your distribution, may be quite different. If you have a Debian based distribution this is very simple. Just run:
This command will generate a new set of Grub configuration files and install the bootloader. Default kernel will be the latest (more recent by date of change) of the /boot directory. It will also generate menu entries for any other operating systems installed. Even if your kernel is fully functional, I recommend to keep a generic kernel from your distribution in case of problem or changes in your hardware.
If despite the previous warning you choose to uninstall your distribution’s kernel, or if you need updated kernel header you should install Linux header in order to compile anything (most of the source packages will need that). Be sure that you uninstall any previous kernel headers before continuing with the following instructions. On Debian:
apt-get remove linux-headers-2.6
Be careful the end of the package name may change (2.6) depending on the version of Debian you have: this one is for Squeeze only. Pleasge change it accordingly. To install kernel headers correctly you have to enter the following lines in a console:
make headers_check make INSTALL_HDR_PATH=dest headers_install find dest/include \( -name .install -o -name ..install.cmd \) -delete # you need to be root for the next line cp -rv dest/include/* /usr/include
First line will make a census of the file to install and prepare a script for future installation. The second line install the needed files inside the “dest” subdirectory. The “find” line will erase some dust then the “cp” line will place all the files in a correct place.