How to Compile A Linux Kernel

Lets begin by asking, why would anyone want to compile their own linux kernel when there are so many already-compiled kernels to chose from? Most distros have a variant of their own idea of a “best” kernel optimization, shouldn’t they know better than the average user? Most of the time the answer is yes. However, sometimes a user is running hardware that the developers had not intended it to be run on, or support for it was dropped to reduce the kernel’s footprint. Remember, the distro’s goal is to run on as much hardware as possible (to make it general enough) but to run as optimally as possible on all the different hardware.
So why might we want to tweak and recompile the kernel? Perhaps you’ve obtained an older model server, with only 32-bit processors, but more than 4GB of RAM. To access the RAM beyond 4GB you’ll have to recompile the kernel with the Physical Address Extension (PAE) module available. Or perhaps a newer kernel version has been released, but your distro hasn’t updated theirs yet and you want some of the newer features or increased performance.
Let’s begin this journey by choosing our linux distribution. I have an affinity for Arch linux, and so I will choose to recompile the kernel on that (I will also be doing this in a virtual machine, however there is no difference in method). The instructions here should be pretty much the same for any flavor of linux as well, so just pick your favorite.

Once you’re done researching the kernel you want to compile, you will need to get the download link for it from kernel.org. I am going to go with the brand new (as of this writing) 3.0 rc4 kernel, available at: http://kernel.org/pub/linux/kernel/v3.0/testing/linux-3.0-rc4.tar.bz2. Download the link on your machine by using the command:

After it’s done downloading, untar it with:
$ tar -xvjf linux-3.0-rc4.tar.bz2

Now cd into the new directory (linux-3.0-rc4) and run:
$ make mrproper


That command is like “clean” but it does a little more than clean, and it is recommended to use that command after untaring a new kernel. (Incidentally, Mr. Proper (mrproper) is another name for Mr. Clean in various non-U.S. countries)
Now we can begin configuring our new kernel. It is recommended to only make minor changes, or only a few at a time, however the time cost of recompiling a failed kernel can be discouraging. I recommend only making the one or two that you want for your machine and recompiling a second time with more changes if you have good results. Generally, if you compile a bad kernel you will be able to still use an old good one. In our example here I will walk you through enabling the PAE module for expanded memory capacity on a 32-bit system.
If you wish to import your current kernel config file, just copy it over from it’s default location; this varies from distro to distro. (Ubuntu uses /usr/src/linux/.config, if you download the kernel development packages from synaptic/apt-get)
To start the configuring, run:
$ make menuconfig


Or:
$ make xconfig #for a Qt-based interface

Or:
$make gconfig #for a GTK-based interface

One of the first things you should do is to browse to General Setup → and select the (-ARCH) Local Version - append to kernel release and add your own appendix to the kernel. It can really be anything here, a name, date, and or version number, just something to identify it by. Feel free to go looking around for interesting options in the kernel, just remember, if you don’t know exactly what it does, DON’T TOUCH IT! Changing a bunch of options willy-nilly will usually not end with a usable kernel.
To enable the PAE option, go to “Processor type and features” > “High Memory Support” > and highlight the 64GB option and hit the spacebar. now exit out to the top level of the menu and save the configuration file with the option at the bottom of the menu, and then exit.
Now, this step will take a long time. This is where the new kernel actually compiles. On a quad core system, run:
$ make -j5 #make -j[num of CPU cores +1]

The -j5 option will help it compile faster by using all of your available cores (assuming you have 4 cores), rather than just in a single thread. This does not tie you down to a maximum of 4 cores for your CPU using your new kernel.
Using 4 out of 6 cores on an i7 970 (3.2GHz), the total compile time was only about 1 hour, but compile times may vary, depending on settings selected. Once the compilation completes, there are only a few more steps to take to put your new kernel in place and use it. If you’re not root already, su to root, and then to install the kernel modules for this particular kernel, type:
$ make modules_install


Now all that is left is to copy over the kernel:
$ cp -v arch/x86/boot/bzImage /boot/vmlinuz-3.0.0-[whatever you named it]

And the system map:
$ cp -v System.map /boot/System.map-3.0.0-[whatever you named it]

Then you will want to run mkinitcpio to create the bootable ramdisk for your kernel:
$ mkinitcpio -k 3.0.0-[whatever you called it] -g /boot/kernel30-[whatever you called it].img

We’re almost done. Right now we have a kernel, system map, and ramdisk to boot the system. We have everything we need, and all in the right place, except for the GRUB configuration. (That is, assuming you use GRUB. I have never used LILO, so I am useless there, I assume a quick google search should yield good results)
At this time is where, maybe if you cross-compiled your kernel for a different system, you could move those three files (in /boot/*[whatever you called it]) over to another system for installation. This next step assumes the kernel is at it’s final destination.



Open up vim (or any other of your favorite editors) and edit /boot/grub/menu.lst. Look for a section of lines that begin with “title” “root” “kernel” and “initrd.” You will want to copy those four lines and paste the copy above the first one (this is so that your new kernel will be the default selected on boot up). Once you copy those lines, edit the first part of the kernel line so that the line:
kernel /vmlinuz26 root=....

Matches the name of your vmlinuz file that you copied over to /boot. (If you dont recall what it is exactly, just $ ls /boot and you should see it) Then edit the line:
initrd /kernel26.img

To the name of your kernel located in /boot. The ending section should look something like mine, with a differing name however:
title Arch Linux 3.0.0
root (hd0,0)
kernel /vmlinuz30-geno-0 root/dev/disk/by-uuid/.......
initrd /kernel30-geno-0.img




And there you go! Now just reboot the machine and it the option to boot into your new kernel should be the top choice. Select it and see how it turns out! (Notice the total memory available, compared with the first screenshot without PAE enabled)




I hope this was helpful and fairly easy to follow. If you have any questions, I’m by no means an expert but I’ll try my best. Leave a comment or shoot me an email: nullfree (dot) geno (at) gmail (dot) com.



geno

Comments