Kernel Compilation Guide


So you've decided to take on that famous rite of Unix geekdom: compiling the kernel. I will be glad to assist you on such a new and strange journey. Compiling the kernel is not that difficult if you are prepared for the task and that's exactly what this guide sets out to do. As with almost any task, it's helpful to break it down into smaller pieces. These are:


Understanding the Kernel


The kernel, as you know, is the core of the operating system. Linux is one such kernel. The job of the kernel is to serve as a bridge between hardware, such as a USB keyfob, and software, such as a file manager or shell. If I were to open a file manager like ROX on the directory where my keyfob is mounted, the kernel would look through the filesystem (probably a Windows FAT filesystem) on the first partition of the keyfob and return a list of files for examination. Actually, it's more complex than that; ROX would ask an important code library, GNU libc to ask the kernel for this data on its behalf. This way everything is abstracted, neatly-layered, and manageable. The kernel is the most important of these layers. If it works well, everything else above it will improve. If it screws up, the opposite happens and no matter how well the user-level software is written, everything suffers. The kernel is like the basement of a building; nobody likes to go down there, but you would certainly not be happy if the basement collapsed. If you build the basement very well (by compiling your kernel), it can become a really fun place like the VIP lounge at Studio 54, which was, after all, in the basement.

One of the main ways the kernel provides an interface to the hardware is through what are called device files. In the /dev on the filesystem, you will see a lot of files with no size and other unusual characteristics. You will see, upon running ls -l, that they are labeled either b or c and have a pair of numbers which uniquely identify them.

hanuman@ayodhya:~$ ls -l /dev/hdc
brw-rw----  1 root cdrom 22, 0 2005-08-02 16:49 /dev/hdc

The b in the output indicates this is a block device. That is to say simply, the kernel allows access to this device in big chunks. A character device, on the other hand, allows reading and writing in a sequence of characters. Disk drives are always block devices, while things like the system virtual consoles, which you can find in /dev/vc, are character devices. This is because of inherent differences between block and character devices. When typing at a terminal, it's one character at a time. When saving a file on a hard disk, it's working in terms of large pieces of data. Nearly every device the kernel exposes to the userland, or user utilities, is one of these device files, notably excluding network devices, such as wlan0 for wireless, ppp0 for PPP phone-line networking, and eth0 for Ethernet. Or wlan1, ppp1, and eth1 for that matter, and any other networking devices you might have. Your modem, however, is represented by something along the lines of /dev/ttyS0 for a PCI modem or /dev/ttyACM0 for a USB modem. The abstract idea of the connection is not represented there though.

All device files can be read from and written to like any other. However, it wouldn't be great to open /dev/hda1 in vi and try editing the disk partition. This is, however, a great convenience for programs that need low-level access to the devices. And, as mentioned, there are a pair of numbers you see in ls -l called the major and minor device numbers. For hdc. The major device number is 22 and the minor is 0. Regardless the name of the device file, whether it's hdc, foobaz, or nonesuch, those numbers identify a file with a device. Any device file with a major number of 22 and a minor number of 0 points to the master IDE device on the secondary controller. In this case, that's my CD-ROM drive. However, if I moved hdc to nonesuch, any programs looking for the traditional name would be lost in the woods. So don't do it. :D

I should add: it is not the job of the kernel, or, at least, the Linux kernel, to provide high-level graphics functionality like window management. All of the high-level and even most of the low-level graphics drivers on Linux are located in the X server. There are certain graphical device functionalities which must be exposed in the kernel because of design restraints. For example, direct rendering, a technology which allows X to circumvent the rigamarole usually involved in accessing a graphics card, thereby speeding up the drawing, needs to be written at the kernel level because of how low-level it is.

That being said, let's go!


Getting the Source


The first thing to do is to go to the Linux kernel's main website and grab the latest stable kernel sources. As of this writing, version 2.6.12.3 is the latest stable version. You want to click on the capital 'F'; this will give you the entire kernel source, as opposed to a collection of patches to make the current version, which isn't what you want. Also, because the ALSA sound drivers in the kernel are usually not as recent as they should be, you should also get the latest stable drivers from the ALSA project. As of now, the latest stable drivers are version 1.0.9b. I will explain how to disable the ALSA drivers that come with the kernel so that they don't conflict with the drivers from the ALSA website.

But what about those version numbers? The kernel has a pretty simple versioning system once you get used to it. There's the version to begin with. This is, without a doubt, two for anyone. Then there is the patchlevel after that. Even are stable; odd are considered bleeding-edge and probably unstable. This scheme is used for many software projects. The old patchlevel was four; the one we will be compiling is six. 2.6 kernels have much more advanced functionality, recent hardware support, and higher performance than 2.4 kernels and are almost as stable. After this comes the sublevel, which works on the same odd/even scheme, and extra version, which takes into account very minor changes. So you see, the numbers on the left indicate large differences, whereas the numbers on the right indicate smaller differences. Unless you are using a Semitic language like Hebrew or Arabic. :D. We are compiling 2.6.12.3, and because extra version numbers do not have the odd/even scheme, this is considered stable. ALSA works on a very similar system, although the release numbers are completely different.


Identifying Your Hardware


For those of you who have never had to investigate your hardware like this before, this step may be daunting, and it may be necessary to get a basic idea of how all that stuff interacts before you can move on! If you know all this stuff, then read on; otherwise bear with me:

The core of a computer, as you know, is the central processing unit, which connects to that flat board of chips called the motherboard. And on that motherboard, there are a number of devices called a bus. A bus is any device which is used to coordinate the devices attached to it, whether they are sound cards, printers, video adapters, hard drives, CD-ROM writers, you name it. Well, that's not entirely true; some devices are so simple they don't even have a bus. This includes serial ports and most floppy drives (unless they are IDE floppy drives). All devices also have what is called an IRQ, unless they are represented by another device that has an IRQ. IRQ means 'Interrupt Request'; it is basically a way for a device to get the CPU's attention, saying, "I'm ready to read data" or "I'm ready to send data". Specifically, devices attached to the motherboard, whether hardwired in or plugged into extension slots, use what are called I/O ports to do so. There are 65,536 on PC hardware, and under very rare circumstances, you may have to tell the kernel exactly which ones a device must use. Having said that, an IRQ lets the CPU know that a device is ready to use an I/O port, whether for reading or writing. Under certain circumstances, two devices can share an IRQ. However, if they do not have that capability, an IRQ conflict is what results. But that is a rarity in this time. Because there are only 16 IRQs available on a PC-type computer, sharing is important, as is representation. For example, the IDE bus, which coordinates the most common type of disk and CD-ROM devices, has one IRQ, which it uses to represent both my IDE hard drive and IDE CD-writer.

But what are the most common types of buses?

Bus Description
IDE The most common, least expensive way of supporting hard disks and CD/DVD-ROM drives and writers. Tape and floppy devices are also made for IDE, but are less common.
SCSI A more sophisticated, usually more expensive way of using a litany of disk devices. Most PCs support SCSI devices through a controller card that has to be plugged in to a device slot.
PCI The most common method of attaching low-level devices to a computer. Your IDE bus is probably attached to the PCI bus. Many PCI devices will be attached directly to the motherboard, but PCI cards can be added by use of the short white slots. PCI does a pretty good job of handing out IRQs properly.
PCI Express This is a next-generation of PCI, which has faster speeds than regular PCI. However, this technology is still relatively uncommon. PCI Express was meant to replace AGP in time, and offers substantial advantages over that technology. For example, due to design restraints, it is impossible to wire more than one AGP slot into a motherboard. PCI Express eliminates that limitation. Speed is also configurable to cooperate with various hardware.
ISA An outdated, kludgy bus that was the first to support Plug and Play (though it was really more like Plug and Pray). ISA tries to allocate IRQs so that they don't conflict, but doesn't do a great job of it. Please don't use ISA.
AGP A variant of PCI made for high-performance graphics cards. If there is a slot for an AGP card on your motherboard, it will be a little shorter than a regular PCI slot and sitting there all by itself. Sometimes your onboard video has AGP functionality.
USB A widespread, richly-functional bus for specially-designed serial devices. There are three main types of controllers, and two versions of the protocol. A USB bus with a UHCI controller only supports v1 USB, which is relatively slow compared to v2, supported by EHCI and OHCI controllers. Often times, a single USB bus will support more than one of these controller protocols.
PCMCIA A type of hotplugging bus commonly used on laptops. Often used for network cards, disk drives and the like.
I2C I2C is a slow serial bus most commonly associated with things like hardware sensors for temperature, power, and othe system monitoring tasks. However, much of the I2C functionality is being replaced by ACPI. (See below.)

That covers most of the devices on your computer. However, there are a few more worth mentioning. Power management devices immediately come to mind, as they are especially important for laptop users. The emerging power management standard is ACPI, which is supplanting the older APM. You may hardware supporting both protocols on your system, but the Linux kernel will prefer ACPI if it is found. What's neat about ACPI is that it doesn't just do power management alone; in fact, the latest 2.6 series kernels use ACPI to give the PCI bus its IRQ.

Of course, there are also the serial ports on your computer, which are almost always of the 8250 variety. Unless you have some kind of very special serial hardware, there is no need to be concerned with anything else. It is worth noting, however, that many modems are emulated through a serial device; therefore, it is necessary to have serial support for modems even if you don't use your physical serial port for anything. (Correct me if I'm wrong.)

There isn't anything special to be said about parallel, keyboard or mice devices, other than that you simply need to get the kernel to support them. Not very hard.

Now there are several methods of finding out what hardware you have. The surest is checking the manual. You can also check the output of various system commands to see what you have. lspci, lsusb, pnpdump, and even dmesg are all your friends. You can even run a live distro like Knoppix or Ubuntu to help you. However, the tools you have, as well as the manual, are usually good enough.

Looking through my VIA motherboard manual I see that I have:

Device Class
CPU Athlon XP, 1.2 GHz
Video Card VESA and AGP capable
Disk Controller IDE
Sound Card Some kind of AC97 chipset
USB Controller EHCI, UHCI

The manual also tells me I have some kind of Ethernet card, though it doesn't go into specifics beyond basic capabilities. I also have a serial and parallel port in addition to what else you would expect, several USB ports, and of course the keyboard and mouse ports. Running lspci -v as root will give me more detailed information on these devices, beyond the fluff in the manual:

hanuman@ayodhya:~$ su -c 'lspci -v'
Password: 
00:00.0 Host bridge: VIA Technologies, Inc. VT8378 [KM400] Chipset
Host Bridge
				Subsystem: VIA Technologies, Inc.: Unknown device 0000
				Flags: bus master, 66Mhz, medium devsel, latency 8
				Memory at e0000000 (32-bit, prefetchable) [size=64M]
				Capabilities: [80] AGP version 3.5
				Capabilities: [c0] Power Management version 2

00:01.0 PCI bridge: VIA Technologies, Inc. VT8237 PCI Bridge (prog-if
00 [Normal decode])
				Flags: bus master, 66Mhz, medium devsel, latency 0
				Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
				Memory behind bridge: dde00000-dfefffff
				Prefetchable memory behind bridge: d5d00000-ddcfffff
				Capabilities: [80] Power Management version 2

00:10.0 USB Controller: VIA Technologies, Inc. VT6202 [USB 2.0
controller] (rev 80) (prog-if 00 [UHCI])
			 	Subsystem: VIA Technologies, Inc. VT6202 [USB 2.0 controller]
				Flags: medium devsel, IRQ 11
				I/O ports at e400 [size=32]
				Capabilities: [80] Power Management version 2

00:10.1 USB Controller: VIA Technologies, Inc. VT6202 [USB 2.0
controller] (rev 80) (prog-if 00 [UHCI])
				Subsystem: VIA Technologies, Inc. VT6202 [USB 2.0 controller]
				Flags: medium devsel, IRQ 5
				I/O ports at e800 [size=32]
				Capabilities: [80] Power Management version 2

00:10.2 USB Controller: VIA Technologies, Inc. VT6202 [USB 2.0
controller] (rev 80) (prog-if 00 [UHCI])
				Subsystem: VIA Technologies, Inc. VT6202 [USB 2.0 controller]
				Flags: medium devsel, IRQ 5
				I/O ports at ec00 [size=32]
				Capabilities: [80] Power Management version 2

00:10.3 USB Controller: VIA Technologies, Inc. USB 2.0 (rev 82)
(prog-if 20 [EHCI])
				Subsystem: VIA Technologies, Inc. USB 2.0
				Flags: bus master, medium devsel, latency 32, IRQ 10
				Memory at dfffff00 (32-bit, non-prefetchable) [size=256]
				Capabilities: [80] Power Management version 2

00:11.0 ISA bridge: VIA Technologies, Inc. VT8235 ISA Bridge
				Subsystem: VIA Technologies, Inc.: Unknown device 0000
				Flags: bus master, stepping, medium devsel, latency 0
				Capabilities: [c0] Power Management version 2

00:11.1 IDE interface: VIA Technologies, Inc.
VT82C586A/B/VT82C686/A/B/VT823x/A/C/VT8235 PIPC Bus Master IDE (rev
06) (prog-if 8a [Master SecP PriP])
				Subsystem: VIA Technologies, Inc.
				VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE
				Flags: bus master, medium devsel, latency 32, IRQ 255
				I/O ports at fc00 [size=16]
				Capabilities: [c0] Power Management version 2

00:11.5 Multimedia audio controller: VIA Technologies, Inc.
VT8233/A/8235/8237 AC97 Audio Controller (rev 50)
				Subsystem: Elitegroup Computer Systems: Unknown device a101
				Flags: medium devsel, IRQ 5
				I/O ports at dc00 [size=256]
				Capabilities: [c0] Power Management version 2

00:11.6 Communication controller: VIA Technologies, Inc. Intel 537
[AC97 Modem] (rev 80)
				Subsystem: SILICON Laboratories: Unknown device 4c21
				Flags: medium devsel, IRQ 5
				I/O ports at e000 [size=256]
				Capabilities: [d0] Power Management version 2

00:12.0 Ethernet controller: VIA Technologies, Inc. VT6102 [Rhine-II]
(rev 74)
				Subsystem: VIA Technologies, Inc. VT6102 [Rhine II] Embeded
				Ethernet Controller on VT8235
				Flags: bus master, medium devsel, latency 32, IRQ 11
				I/O ports at d800 [size=256]
				Memory at dffffe00 (32-bit, non-prefetchable) [size=256]
				Capabilities: [40] Power Management version 2

01:00.0 VGA compatible controller: VIA Technologies, Inc. VT8378 [S3
UniChrome] Integrated Video (rev 01) (prog-if 00 [VGA])
				Subsystem: VIA Technologies, Inc.: Unknown device 0000
				Flags: bus master, 66Mhz, medium devsel, latency 32, IRQ 11
				Memory at d8000000 (32-bit, prefetchable) [size=64M]
				Memory at de000000 (32-bit, non-prefetchable) [size=16M]
				Expansion ROM at dfef0000 [disabled] [size=64K]
				Capabilities: [60] Power Management version 2
				Capabilities: [70] AGP version 2.0

Much better. I find I have a modem which evidently uses the same chipset as my chipset as my sound card (this can happen; a sound card and a modem, after all, both convert digital to analog and vice-versa). However, I'm not using it, so no need to worry. I have a Via Rhine II ethernet card, and most of my other hardware is, being on a Via motherboard, also Via hardware. My sound card is a VT8233 variety. I have a crappy old ISA bus, but I'm not using it, so I don't care about it. I find my video adapter is a Via Unichrome with AGP, too. All of this is essential to configuring my custom kernel. lsusb tells me I have a flash drive plugged in, but I only had to look to see that. A superficial glance over the system tells me I have a CD writer as well as a floppy drive, and of course I have a hard disk! Both the CD and the HDD are obviously IDE, as I have no SCSI devices.

With info in hand, I now move on to the big adventure! Configuring the kernel...


Kernel Configuration


Unpack the kernel source somewhere. Personally, I prefer to do this in my home partition, as it doesn't require any special permissions to do so. I actually have a directory for all my sources, and the kernel goes into the os directory as well as the ALSA sources.

hanuman@ayodhya:~$ cd /home/src/os/
hanuman@ayodhya:os$ ls
alsa-driver-1.0.9b.tar.bz2  linux-2.6.12.3.tar.bz2
slax-popcorn-5.0.6.iso
hanuman@ayodhya:os$ tar xjf linux-2.6.12.3.tar.bz2 &

This will unpack the kernel sources in the background. When the unpacking finishes, I can change directory into linux-2.6.12.3 and have a look around:

hanuman@ayodhya:os$ cd linux-2.6.12.3
hanuman@ayodhya:linux-2.6.12.3$ ls
COPYING         Makefile        crypto/   init/    mm/        sound/
CREDITS         README          drivers/  ipc/     net/       usr/
Documentation/  REPORTING-BUGS  fs/       kernel/  scripts/
MAINTAINERS     arch/           include/  lib/     security/

There are directories for the various components of the kernel, as well as one for all the geeky bathroom-reading material in Documentation, something called a Makefile, which is used to conduct the build, and a few other miscellaneous files. The file we are concerned with is one called .config (yes, with the dot in front). Because filenames beginning with a period are usually hidden, you will not see it unless you run ls -a. This secrecy belies the importance of .config; it dictates what goes into your kernel, what doesn't, and ultimately dictates whether it will kick ass or bomb miserably.

The generic .config supplied with Vector is a good starting point. But before we start using it to configure the kernel, we need to make absolutely sure the kernel sources are clean. This can be done by running make mrproper. What this does is consults the Makefile for a section called mrproper, and runs all the commands therein. Additionally, the mrproper stanza has dependencies, which are other sections (called rules to the make utility) that need to be run for mrproper to complete. make does that automagically, and as a result the kernel sources are completely clean of any detritus a careless developer might have left in there.

The other thing that needs to be done is getting rid of old header files in /usr/include. Header files are essentially a way for one source file to tell things about itself to the other source files, and they are used extensively in the programming language most of the Linux kernel is written in, C. If you installed Vector Standard like me, these packages are probably present: kernel-headers-2.4.29-noarch-4vl5, kernel-modules-2.4.29-i486-1, kernel-sata-2.4.29-i486-4vl5, kernel26-headers-2.6.10-noarch-4vl5. Get rid of them, either with removepkg or pkgtool. Then, assuming you have already changed directories into the kernel sources:

su
cp -R include/linux /usr/include
cp -R include/asm-generic /usr/include
cp -R include/asm-i386 /usr/include
cd /usr/include
ln -s asm-i386 asm
exit

By doing this, the new kernel headers are installed into /usr/include, where other programs that need them, including the kernel configurator, can use them. The asm-generic and asm-i386 are both for interfacing with a very low-level programming language called assembly, and the latter is specifically for Intel, AMD, and other so-called 386 processors (because they descended from the original 32-bit processor for the PC, the Intel 80386). This is the only processor type supported by Vector, so if it's running on your Sparc, you probably know how to compile a kernel. The asm link is there to tell various program builds what architecture your system is; they don't just guess.

Finally, we can move the config into place. cp /boot/config-2.6.12 .config with working directory the location of the kernel source, of course. Actually, this is only true for VL 5.0 Standard RC2 and 5.1 Standard. Check for a similar file under 5.0 Standard RC1, and with SOHO, which comes with the 2.4 kernel only, you have to get the config.

The next task cut out is to configure the kernel with one of several methods available. This is done by typing make followed by one of the following:

config The crappy old way which interviews you on how you want your kernel configured. Trust me, you won't like it.
menuconfig A menu interface which is a dead ringer for VASM on the command line. My personal reccommendation.
xconfig Qt-based configuration. You need to install Qt if you intend to you this in Standard.
gconfig GTK2-based configuration

This is what the GTK configurator looks like. There are a few special features, such as different views for the tree of kernel features, but they are really not worth it, in my opinion. You should try either of the graphical configurators and contrast them with the menu-based one, though, to see which one you are most comfortable with. You will be presented with a tree of menus in either case. There are specific instructions for either program; menuconfig tells you exactly what to do at the top, but they will both read the defaults from .config. Another universal truth of the configuration programs is that an option can be on or off, or sometimes, a module. Certain options set very general behavior which is either yes or no, others refer to specific pieces of code which can become kernel modules if desired. If you get confused on a particular option, there will be usually help for that option to help you decide, including a description of that option's effects and what to do when in doubt. If that is not good enough for you to decide, stick with the default; it got your system this far, after all.

But what about those kernel modules? In the beginning, Linux and many other related Unix-like kernels were what you would call monolithic. That doesn't mean you heard wailing operatic voices and monkeys when you saw them, it means all the drivers and everything were packed into a single file of code. This scheme was very inflexible. If you compiled most things out, the damn thing would fit on a floppy, but wouldn't run on everyone's system. And if you put everything in, it would become an unmanageable mess and you'd have multiple drivers trying to manage the same device. So, as the installed base grew larger, it became necessary for Linux to support modular code. There is still a monolithic base; the file /boot/vmlinuz-2.6.12 is the core of the version 2.6.12 kernel that comes with VL Standard. However, the modules for this kernel are of course found in /lib/modules/2.6.12 in several directories there. Each kernel module file ends in .ko, and you can find out about a module with the command modinfo:

hanuman@ayodhya:~$ /sbin/modinfo /lib/modules/2.6.12/kernel/drivers/usb/host/ehci-hcd.ko               
filename:       /lib/modules/2.6.12/kernel/drivers/usb/host/ehci-hcd.ko
parmtype:       log2_irq_thresh:int
parm:           log2_irq_thresh:log2 IRQ latency, 1-64 microframes
parmtype:       park:uint
parm:           park:park setting; 1-3 back-to-back async packets
description:    10 Dec 2004 USB 2.0 'Enhanced' Host Controller (EHCI) Driver
author:         David Brownell
license:        GPL
vermagic:       2.6.12 586 gcc-3.3
depends:        
alias:          pci:v*d*sv*sd*bc0Csc03i20*

The link build should point to the location of the kernel sources, but it's rarely used, so you should only cross that bridge when you come to it. You will also find several utility files there. modules.dep has all the dependencies for when you run modprobe; that is, if any modules are needed by the one you are trying to load, it will load them first. Think of it like dependencies for make rules or getting a package through slapt-get. There are also files ending in map that identify devices of a certain class (such as USB for modules.usbmap) with drivers. This way, the kernel can attempt to automatically load a driver for a device, whether that driver is built into the monolithic image or is a module.

Usually, modules are enabled for anything that is extraneous to the basic function of the system or should be modularised due to design, such as my two USB controllers. This is the good rule of thumb. If I don't need it to boot, it can be a module.

That being said, I can give you a few more general pointers on configuring your kernel. If you see some random piece of hardware in there and you don't have it, disable it altogether, even if it is a module (indicated by <M>). It wastes time in the compilation. If you have a certain piece of hardware, but never use it, or don't plan to use it anytime soon, then you can disable that. Sure, I have ISA slots and a parallel port. I might as well not, and the kernel might as well ignore them. If you come to a point where you have two devices of the same class, see if you can compile them as modules, which allows for more flexibility. For example, I have a UHCI and EHCI USB controller, so I want to 'modularise' support for those two. Certainly, don't add drivers you're sure you don't need at all; it'll mash up everything.

The default Vector config has Sound card support there as a module, but does not enable either ALSA or the older OSS drivers. We will also compile the ALSA drivers separately, so leave the option to include ALSA drivers off; however, leave Sound card support, as it is needed for using ALSA.

SCSI emulation for IDE devices is no longer needed to burn CD's in 2.6 kernels. Why did they do it anyway? It sounds ass-backwards, but to make a long story short, it had something to do with a deficiency in the IDE command set; it didn't include support for things like fixating the disk, presumably. So the kernel developers decided to make it possible for CD-writers to look just like SCSI devices in order to use the more complex SCSI commands. This has since been scrapped, and now it is enough to have regular IDE CD drive support to burn CD's. However, a lot of other types of devices are emulated as SCSI, because SCSI has the richest command set available. For example, the USB Mass Storage driver makes flash drives look like a SCSI device with its own bus, and only one device attached to it. The poopy Low Performance USB Block Driver does things differently, but few people use it, because it's poopy. You may want to check documentation for particular devices; for such devices you need SCSI device support and frequently SCSI generic support, as well as others depending on the situation.

Also, you really should set the option Local version in General setup. You should put a hyphen to separate it, followed by a brief string to describe your new ass-kicking kernel. For example, -hanuman. This way, the modules will install to, for instance, /lib/modules/2.6.12.3-hanuman, and you're absolutely sure nothing gets clobbered, because the name is unique. But it's also a way to express yourself. Here, I make a literary / cultural / religious reference to the awesomest monkey ever. It could be about soccer, it could be about television, it could be about your dog. And it shows up in the output of uname -r and dmesg no less.

Sometimes, you see an option you want to turn off because you obviously don't need it, because the configurator just won't let you. Turn off more extraneous stuff you don't need, then go back and try again.

Another cool thing you can do is set the Processor family option. In my case, I set it to Athlon/Duron/K7; this will optimise the kernel for my processor by using instructions that are only available on this type of processor. Enough with the geek stuff, that means it will run faster. Ever see Windows Athlon Edition? But make sure you don't set it to something your processor is not. This will just give you an unusable mess.

Leave Loopback device support in; it's a good thing to have. But you can leave out support for RAM Disk Support, those are only needed in special cases, and they are a PITA to work with. And make sure you turn on Preemptible kernel. I'm still a little foggy on what this does, but the gist of it is that it manages the processes on your system in a way that is favourable for a desktop. Unless you are running a server, turn it on; it was actually a big selling point for the 2.6 kernel.

And I'm sure this sounds stupid, but don't compile the code that supports your root filesystem as a module. I've done it before, actually. This means, in my case, anyway, that I want Reiserfs support to be built into the kernel. If it wasn't I couldn't mount the root file system at boot and I'd be screwed.

It's fun to turn on security features such as Cryptoloop, but don't go overboard unless you actually plan to use it and there are black helicopters circling over your house, Colonel.

If there is mention of fixes for your IDE chipset in the section ATA/ATAPI/MFM/RLL support, turn them on. In my case, this is VIA82CXXX chipset support, because I have a VIA IDE chipset of that type. They might be important, or at least enhance performance. I'm pretty sure, for example, that DMA for hard drives does not work without that fix, and that's no good.

You will see mention of PCI hotplugging. Make sure you have PCI hardware that supports hotplugging if you plan to use it; if you don't, and try to 'hotplug' a PCI card, you will notice an acrid smell and might see smoke coming out of your motherboard. The kernel, by the way, has no way of handling this special case, other than dying horribly along with the rest of your system.


Building the Kernel


Once that's out of the way, run make. Actually, it's better to run make &> make.log &. This way, all of the output, including errors, is directed to a file called make.log. Moreover, it runs in the background so you can do other stuff. You can check on the progress with tail make.log, or tail -f make.log; this gives you continuous output which you can interrupt with Ctrl-C.


Installing the Kernel


If make doesn't crash and die (you'll know by checking the log), you will have the monolithic part of the kernel in arch/i386/bzImage. Copy this file to /boot/vmlinuz-version, (e.g., vmlinuz-2.6.12.3-hanuman). You must also run make modules_install, and I'm sure you can guess what that does. Then:

cd /boot
ln -sf vmlinuz-version vmlinuz
vasm

Navigate FILESYSTEM, then LILO, and configure LILO as you usually would. You want to hold on to the generic kernel, which will show up as Linux 2.6.12 (/dev/hda1), or something to that effect. In any case, it will have the same root partition as your new custom kernel, but named differently. If something goes wrong, you can just boot into generic and try to fix it.


Installing ALSA


The last step is to install ALSA. This is actually a lot simpler than the kernel, because the project is smaller, and they also use GNU autoconf (yes, as in, configure, make, and make install). You should set the CFLAGS environment variable so that it matches the optimisations for the kernel. This can be done with: export CFLAGS="-O2 -march=foobar", where foobar is a CPU architecture as defined by GCC. And I quote the GCC manual itself:

The choices for cpu-type are i386, i486, i586, i686, pentium,
pentium-mmx, pentiumpro, pentium2, pentium3, pentium4, prescott,
nocona, k6, k6-2, k6-3, athlon, athlon-tbird, athlon-4, athlon-xp,
athlon-mp, winchip-c6, winchip2 and c3.

These more or less correspond to those in the kernel. I would use export CFLAGS="-O2 -march=athlon-xp", given my hardware. What this does is sets a variable in the shell that configure finds and passes to the C compiler, gcc. -O2 tells it to use general optimisations within reason, and the -march option enables special optimisations for the processor type.

The most important options for the configure script are --with-isapnp=yes/no, --with-sequencer=yes/no, --with-oss=yes/no, --with-cards=soundcards, and --with-kernel=locationofkernelsource. The instructions go into more detail about this, but --with-oss=yes for OSS emulation; some apps need it, and of course turn of PNP support if you don't use ISA anymore. I would do ./configure --with-isapnp=no --with-sequencer=no --with-oss=yes --with-cards=via82xx --with-kernel=/home/src/os/linux-2.6.12.3. Over here! And the rest is pretty routine, make and make install.