Compiling a New Kernel

Created on: April 4, 1998
Last Modified: April 20, 1999
Development stage: Alpha

The kernel is a file that is the most important part of any operating system. The kernel sets up a basic interface between the hardware and software. It's also what distinguishes Linux from other Unix operating systems. Most of what people think is Linux is actually from the Free Software Foundation and other GNU authors. In addition to hardware, the Linux kernel is responsible for supporting protocols like TCP, IP, PPP, and all the filesystems out there.

Compiling the kernel should be one of the easiest things to do, but as with most things dealing with Linux, there are problems people encounter along the way. Let's just save that thought for later.

  1. Downloading and Unpacking the Kernel Source
  2. Compiling the Kernel
  3. Installing LILO
  4. Various Authors' Notes

Downloading and Unpacking the Kernel Source

This is the first (and arguably most frustrating) step in the kernel upgrade process.

Downloading the Kernel

The latest Linux kernel can be downloaded from the following sites with the file name linux-x.y.z.tar.gz, "x" is the "2" in linux-2.2.4, "y" is the "2", and "z" is the "4". When the "y" value is odd-numbered, as such in "2.1.109", it is a development kernel (like beta software, but less stable) and isn't considered to be stable enough for the average Linux user. If you're reading this document, you're probably much better off with a stable kernel. As of the writing of this document, there is no development tree. 2.2.x is your best bet!

Kernel.org Mirror Sites

The Linux kernel source can be downloaded from the following sites.

Once you find the kernel you want to install, download it into the directory /usr/src/. This is a moderately large file (at least 10MB as a gzip'd tarball for the 2.2.x kernel), so go do something else while downloading it. Of course, if you've got a fast connection, then it won't take as long to download. Generally you want the latest version of the latest stable kernel: currently 2.2.zz. Remember that ftp sites go in raw numerical order - linux-2.2.1.tar.gz comes before linux-2.2.12 on the list, even though linux-2.2.12.tar.gz is newer. This should not be an issue for several months, as 2.2.4 is the current version (25mar1999).

Unpacking the Kernel Sources

When you're done downloading it, extract it with tar -zxvf linux-2.2.zz.tar.gz, where linux-2.2.zz.tar.gz is the file that you downloaded. This will extract everything into the linux subdirectory. It might take a while, so be patient. If you have compiled the kernel before (or installed any kernel header/source packages), you will need to mv the old files out of the way before unpacking the kernel. Simply do mv linux/ linux-2.0.35/, or whatever version of the kernel the headers/source is for.

Patching

If you're downloading a new kernel and don't already have the source lying around, you can't patch yet. If you're downloading a kernel for the first time, skip this subsection and go on to the next one.

It's such a big drag to download the entire kernel source tree every time a new version comes out, so I recommend using patches. A patch contains information on the differences between a previous version and the current one. For example, if you have kernel 2.2.5 and want to upgrade to 2.2.6, you need to get the patch that contains the differences between 2.2.5 and 2.2.6.

Kernel patches have filenames such as patch-2.2.6.bz2. In this example, it's the patch to upgrade from 2.2.5 to 2.2.6. You should download patches into the /usr/src/linux/ directory. Depending on what compression format you downloaded the patch in, you uncompress it differently. For bzip2, the compression format this patch uses, you use the commandline bzcat patch-2.2.6.bz2 | patch -p1. If you downloaded it in a gzipped format, you would type zcat patch-2.2.6.gz | patch -p1.

At first, the term patch gave me a connotation that this was only a quick fix. (I had a mental image of a piece of cloth sewed on to cover a hole on a jacket.) It's not really that. It's just something that fixes the source tree accordingly.

Checking Dependencies

When compiling and running the kernel, the system expects certain things to be in place. For example, you need to have a compiler to get from the source code to a binary format the system can execute. You also need the modutils if you plan on using modules, and autofs for automounting, etc. To know what the most recent versions are, see the file linux/Documentation/Changes. This file will list what packages you need, what the base version is (lowest version you need to compile--it's usually a good idea to try out the newest version of a given package), and where to get new copies of them. This file also contains vast amounts of unneeded information. What you're most interested in is the table of most recent versions and the info on getting new versions.

Here's a sample of the most recent version chart (taken from Changes for 2.2.3):

Current Minimal Requirements
****************************

   Upgrade to at *least* these software revisions before thinking you've
encountered a bug!  If you're unsure what version you're currently
running, the suggested command should tell you.

- Kernel modules         2.1.121                 ; insmod -V
- Gnu C                  2.7.2.3                 ; gcc --version
- Binutils               2.8.1.0.23              ; ld -v
- Linux libc5 C Library  5.4.46                  ; ls -l /lib/libc.so.*
- Linux libc6 C Library  2.0.7pre6               ; ls -l /lib/libc.so.*
- Dynamic Linker (ld.so) 1.9.9                   ; ldd --version or ldd -v
- Linux C++ Library      2.7.2.8                 ; ls -l /usr/lib/libg++.so.*
- Procps                 1.2.9                   ; ps --version
- Procinfo               15                      ; procinfo -v

Now, if you run a libc5 system (most older distributions), you will not have a libc6. And some of these packages are entirely optional -- if you don't currently have it, you probably don't need it, assuming your system has the ability to compile C programs.

So, you need to go through the list and double-check your dependencies. If something is old, look further down in Changes for its homepage/distribution site. Let's say your Module utilities were outdated. You'd look further down in Changes and find the lines:

Modules utilities
=================

The 2.1.121 release:
ftp://ftp.us.kernel.org/pub/linux/kernel/v2.1/modutils-2.1.121.tar.gz

Which, gives you the release number and a location to download the most recent version.

After you download the updated files, you will need to move them to an appropriate location (9 out of 10 hackers agree on /usr/local as a stuff-compiled-locally directory), and unpack them (tar xzf foobar-1.2.3.tar.gz). Most kernel packages are well-behaved and will untar into their own subdirectory. cd into this directory and follow their instructions, usually found in INSTALL or README (less INSTALL or less README). If these directions fail, mail us. But not until you've read the instructions. We'll probably grab the package and try installing it ourselves, to see if it's broken or not.

You should now have your kernel downloaded, unpacked into /usr/src/linux, and all the things you need installed.

Compiling the Kernel

Now that most of the hard work is taken care of, it's time to begin the dull part!

Here is a basic outline of the kernel-compilation process:

I will not go into great detail about what every command above does; if you want to know, read the Linux Kernel HOWTO.

Start by doing cd /usr/src/linux and make mrproper. These first two steps simply clean up any cruft that might have accidentally been left in the source tree by the development team. Then read on.

Configuring the Kernel

Like all other powerful software, the Linux kernel has to be configured. This is done during the make menuconfig step. make menuconfig starts an application that allows you to browse through the options available for the kernel and make settings. To move around, use the arrow keys. Enter allows you to open up a menu, and tab gets you down to the "buttons" at the bottom. When you want a specific part of the system compiled into the kernel, hit 'y' while it is highlighted. If you realize that you don't need or don't want something, go back and hit 'n' over it. If you just want to try something out or use it occasionally, you can usually compile it as a module. All this (and more) is documented in menuconfig's docs.

While doing make menuconfig, a lot of the things that you have to configure are pre-set, so if you don't know what it is, leave it alone. However, if you are pretty sure it won't hurt to disable support for something in the kernel, disable it, because the defaults are not always right for everybody. I usually have to change the settings a little bit to keep my kernel small.

If you use make menuconfig, you can hit "?" if you're not sure what an option does. This will bring up a small amount of text describing them, and usually a hint as to what the best option is if you don't know what it is (some things don't have a ? screen, so you're best off to go with the defaults on those if you're not sure what they do)

Compiling the Kernel

After you finish configuring things, do make dep; make clean. This does a few technical things regarding dependencies and old compiliations lying around. Ít's just something you need to do and need not worry about as to why.

Next, do make zImage. This may take a long time depending on your system (on my K6-2-300/64M it takes about 10 minutes with X running. On my friend's 386sx-16/8M it took several hours with nothing else running; on another friend's dual p100/48M it takes about 14mins -jbm). Usually it's a good idea to watch it compile and keep an eye on possible warning messages. In particular, signal 11 messages are Bad News. If you get any signal 11s, see the note on sig11. Another common problem is the kernel being too big. If your kernel is too big, try doing make bzImage after the make zImage. A zImage is a gzip'd kernel--it's compressed down to a more manageble size, which makes booting a little slower. A bzImage is a bigger zImage kernel. (It still uses gzip.) I (jbm) have to use make bzImage because my kernel has gotten too large for zImage. If you have use a bzImage, please replace the references to zImage with bzImage. It's a common problem and most people probably use make bzImage anyway these days.

make modules; make modules_install: these compile and 'install' any modules you selected. You will also need to set up the module dependencies for these, see the Note on modules.

Notes on Compilation

Note on sig11:
A signal 11 error during kernel compilation means that gcc found an error in one of the files while compiling. sig11s, as they are commonly referred to, are typically caused by bad hardware. In my (jbm) experience, they have been caused by bad processors, bad memory, and overclocked memory. With the popularity of 100MHz bus clock systems (ie: k6-2/3 and pII/pIII), there is an increasing number of people overclocking RAM. I know, I do it myself. I often get sig11 messages during compiles, when the computer is getting hot. My general strategy for dealing with these is to lower system load (close x, stop listening to MP3s, etc), and recompile the whole kernel. Because this is a kernel-level file, do not simply remove the .o file and move on. This could lead to system damage.

Where to Copy the Kernel

When you're copying the kernel to where it's supposed to be, that may change from system to system. You can use what I have up there if you're on a standard Red Hat system; if you're using Slackware, it's not in /boot--it's in /. So instead of /boot/vmlinuz-2.2.zz-new, it's /vmlinuz-2.2.zz-new.

We use the vmlinuz-2.2.zz-new for safety's sake. If you forgot something essential in your kernel, your computer wouldn't be able to boot with the new kernel. Unfortunately, this makes life a little more complicated now, but it's not so bad. All you have to do is edit /etc/lilo.conf (a somewhat daunting task, but really pretty simple).

Editing /etc/lilo.conf

/etc/lilo.conf is the settings file for lilo, the LInux LOader. Editing this file can be hazardous to the health of your computer. Before you edit it, make a backup copy of it (cp /etc/lilo.conf /etc/lilo.conf.backup-foo, or some other name you can remember.). This backup is in case you accidentally delete a line in the file. If you need to restore your old lilo.conf, just do cp /etc/lilo.conf.backup-foo /etc/lilo.conf and start anew. Now then - to the real work with lilo.conf

Open up /etc/lilo.conf in your favorite text editor. The file should look something like this:

# LILO configuration file
# generated by 'liloconfig'
#
# Start LILO global section
boot = /dev/hda
#compact        # faster, but won't work on all systems.
delay = 50
vga = normal    # force sane state
# ramdisk = 0     # paranoia setting
# End LILO global section
# Linux bootable partition config begins
image = /vmlinuz
  root = /dev/hda2
  label = Linux
  append = "ether=9,0x310,eth0 mem=64M"
# Linux bootable partition config ends
# DOS bootable partition config begins
other = /dev/hda1
  label = DOS
  table = /dev/hda
# DOS bootable partition config ends

What you want to do is this: copy the section from "image = vmlinuz" through to the "# Linux bootable partition config ends"(or the next "image =" line, if you have one) letter for letter right below where it currently is, like so:

# LILO configuration file
# generated by 'liloconfig'
#
# Start LILO global section
boot = /dev/hda
#compact        # faster, but won't work on all systems.
delay = 50
vga = normal    # force sane state
# ramdisk = 0     # paranoia setting
# End LILO global section
# Linux bootable partition config begins
image = /vmlinuz
  root = /dev/hda2
  label = Linux
  append = "ether=9,0x310,eth0 mem=64M"
image = /vmlinuz
  root = /dev/hda2
  label = Linux
  append = "ether=9,0x310,eth0 mem=64M"
# Linux bootable partition config ends
# DOS bootable partition config begins
other = /dev/hda1
  label = DOS
  table = /dev/hda
# DOS bootable partition config ends

If you don't have a "delay = xx" line, or if xx is equal to 0, change it to "delay = 50" (without the quotes). By adding this line, you instruct LILO to wait 5 seconds for you to enter in a kernel image to load before it automatically boots the first one in the list (in this case Linux). Now change the second "image = /vmlinuz" (or "image = /boot/vmlinuz") line to "image = /vmlinuz-2.2.zz-new" (xx is the version number, like 2.2.4). Also change the second "label = Linux" line to "label = New". This section of the file now looks like this:

image = /vmlinuz
  root = /dev/hda2
  label = Linux
  append = "ether=9,0x310,eth0 mem=64M"
image = /vmlinuz-2.2.zz-new
  root = /dev/hda2
  label = New
  append = "ether=9,0x310,eth0 mem=64M"

Save the file to lilo.conf. Now type in lilo at the command prompt. It should give you output similiar to this:

Added Linux *
Added New
Added DOS

If you encounter any error when you type lilo then there the kernel is probably in a differnt locataion than the image = line says. Check that, and look for capitialization problems.

Reboot, and when the LILO: comes up, hit left-shift (or any other key that happens to please you), and then type in "new" (without quotes, again). This will boot the image labeled new - /vmlinuz-2.2.zz-new. If this boots and works well, just do cp /vmlinuz /vmlinuz-backup and cp /vmlinuz-2.2.zz-new /vmlinuz. Open up /etc/lilo.conf again and change the New section to be name = backup, with the image being /vmlinuz-backup. If you don't want the LILO boot prompt, comment out the delay = 50 line (stick a # in front of it). Now type lilo at a prompt and if lilo installs well, try rebooting to make sure both your new kernel and your backup kernel work.

PPP Support in the Kernel

Before compiling, make sure you enable PPP support during make config or make menuconfig. It's left to be NOT supported on most of the kernels I've compiled so far (maybe because the kernel developers have high-speed digital connections), but if you connect to your ISP through PPP, you better enable this or else you'll have to recompile later on to connect to the Internet.

Math Coprocessor/FPU

If you don't have a math coprocessor (if your CPU is a 386DX or 486SX without a math coprocessor), make sure you say YES on kernel math emulation. This is what stopped me the first two times; I forgot about the EMULATION part. If you have a tape drive, SCSI interface, or any other weird or expensive stuff then go through make config very carefully to optimize your system. If you have a 486DX, Pentium, or higher processor with normal system specs, then just browse through configuration a bit and be careful. This may get boring (especially if you have to do it three times to get it right), but still read through it before jumping to compilation. Eventually you'll know what's there to configure and you'll just zoom past it.

Unresolved Modules?

You might see some errors/complaints about "unresolved modules" when you're booting the new kernel. Whatever the cause is, try moving your old module directory in /lib/modules (or wherever your kernel module directory is) to /lib/oldmodules/. For example, when I boot up and some errors pop up about my 2.2.4 modules being unresolved, I might go into /lib/modules/2.2.4 and move the modules that are being complained about. To avoid these errors, do cp -r /lib/modules/2.2.yy /lib/oldmodules/; rm -rf /lib/modules/2.2.yy before you do make modules and make modules_install. (For example, if I were recompiling Linux 2.2.4 and I already had modules for 2.2.4 installed, I would type cp -r /lib/modules/2.2.4 /lib/oldmodules/; rm -rf /lib/modules/2.2.4 before I went and compiled the modules). The unresolved modules error is quite common for the first few times you complie the kernel and has stumped Linux newbies worldwide. Of course, you could just delete the old modules directory (rm -rf /lib/modules/2.2.4 for example), but it is generally a bad idea to delete things you might wind up needing if the compile doesn't go quite right (also a common problem for your first few compiles ;^) ). So just move things around.

I've had a problem while compiling development kernels (those starting with 2.1) that complains about unresolved modules; I thought I needed to update a few programs, and I was right. I found the page at http://www.linuxhq.com/pgmup21.html.

Comments

You might wish to add that when you use an RPM kernel version, it appears to come in separate kernel-source and kernel-headers files.
Simon Hampton <simon.hampton@tvd.be>

(The bold is my own, to stress the importance of RPM here. This particular problem is due to a broken-by-design strategy on the part of the RPM package maintainers. I guess it keeps package size down, at a large convenience/stability cost. -jbm)

Authors' Notes

Some people using SCSI on their Linux box may have problems compiling the kernel. Since I don't have SCSI installed on my system, I don't know what to do. However, Jeffrey here seems to know. If any of you SCSI users have been having the same problem, please verify this information with me so that I'll sound more confident. :)

Here's a list of my in's and out's of getting the SCSI modules to boot
with your new kernel.

* After you have made the kerenel and modules i.e. "make zImage"
  and "make modules" make sure that your loopback device is
  available try "insmod loop" OR maybe it isn't a module or just
  complied in straight then you don't have RHL installed and this isn't for
  you!, This is default as a module with RHL along with everything else

* Another trap that I found is that with comfiguring the Kerenel with
  "make xconfig" at a res of 640x480 the two buttons at the bottom
  are cut off and I kept on going to just close the window and wonder why
  the kerenel wouldn't compile! 

* After you have inseted the loopback device, do a "make
  modules_install" to install the new modules (including you brand new
  SCSI drivers!) (Don't forget to back up the old set of modules in case you
  stuffed on the "insmod loop" and need to reinsert it later! 

* Now just type "mkinitrd /boot/initrd 2.2.3" where the
  filename points to the image file in the lilo.conf and the version of your
  new kerenel is there and present! The program mkinitrd works off your
  /etc/config.modules file! 

* FEW THINGS TO REMEMBER! - Don't forget to back up your old kernels and
  old initrd image file!, you never know this MAY not work successfully! (I
  know I have stuffed it up completely about 10 times!) :( anyway this
  booted for me on both options the old and linux in LILO then copy your new
  kerenel into it's final home and RUN LILO! 

Jeffrey Borg
jeffrey@tudogs.net.au

Comments, questions, suggestions, corrections? Send them to jbm@intertek.net - if they're my mistake I'll reply, if not I'll forward them on to Joshua.


Copyright © 1997-1999 Joshua Go (joshuago at users dot sourceforge dot net). All rights reserved. Permission to use, distribute, and copy this document is hereby granted. You may modify this document as long as credit to me is given.

jbm hereby grants all copyright permissions he has to Joshua Go. In other words - it's still Joshua's property, although I'd like a little credit if you use this document.