Linux kernel configuration

While we talked before about kernel compilation and configuration, we focused on the general idea. This time we want to dig deeper into the configuration part, giving you useful advice you will need when tailoring a kernel to perfectly match your hardware.

The main idea behind this is that you will need to know your hardware extremely well in order to have a kernel built exactly for it. At the beginning we will cover what you will need in order to compile your kernel and after that we move into Linux kernel configuration, compilation and installation.

Please note that this time it’s not very important if you compile a vanilla kernel or a distribution kernel. We will however, recommend a “modus operandi”, which of course does not mean that you have to follow. After reading this guide you will be able to decide what suits you best. We expect some moderate knowledge about Linux system internals and development tools.

In this tutorial you will learn:

  • How to download Linux kernel source code
  • How to determine what hardware you have
  • How to compile configured Linux kernel
  • How to install and use the newly kernel
Linux kernel configuration
Linux kernel configuration
Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Any Linux system
Software Linux kernel source code
Other Privileged access to your Linux system as root or via the sudo command.
Conventions # – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux commands to be executed as a regular non-privileged user

Download Linux kernel source code

To get started, we will download the Linux source code from GitHub. This can be done with the following git command.

$ git clone

Even though we will make the kernel smaller in our tutorial, it will still need some horsepower in order to get compiled in a decent time. So, while on a modern, multi-core system it will take ~15 minutes, on an older, slower system it might take even a day or so. Compiling large projects puts a lot of stress on the machine, especially memory.

Getting to know your hardware

If you already feel confident you know what lies under the hood of your computer, you may skip this part. If not, or have some doubts, read on. Take your time with this part because it’s crucial to getting a kernel made especially for your machine.

To get some information about the hardware on your system, you can use the lspci command.

$ sudo lspci -vv > lspcioutput

This creates a file named lspcioutput (change the name if you want, of course) and fills it with the info from the command lspci, ran verbosely for more details. Open the created file with your favorite editor and keep it handy. Read it all to get a general idea about your hardware components.

Going further with our example, here’s what appears in our lspci output at the Ethernet controller part:

00:06.0 Ethernet controller: nVidia Corporation MCP65 Ethernet (rev a3)
        Subsystem: Giga-byte Technology Device e000
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- 
SERR- FastB2B- DisINTx+
         Status: Cap+ 66MHz+ UDF- 
FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0 (250ns min, 5000ns max)
        Interrupt: pin A routed to IRQ 42
        Region 0: Memory at f6007000 (32-bit, non-prefetchable) [size=4K]
        Region 1: I/O ports at c800 [size=8]
        Capabilities: [44] Power Management version 2
                Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
                Status: D0 NoSoftRst- PME-Enable+ DSel=0 DScale=0 PME-
        Capabilities: [50] MSI: Enable+ Count=1/8 Maskable+ 64bit+
                Address: 00000000fee0300c  Data: 4171
                Masking: 000000fe  Pending: 00000000
        Capabilities: [6c] HyperTransport: MSI Mapping Enable- Fixed+
        Kernel driver in use: forcedeth

As you can see, you get a lot of information about the hardware, information that we might need to sort in order to get what we need. What we need in this case is the name (nVidia Ethernet MCP65) and the driver in use, that is forcedeth.

If you want to find out what option you need to enable in the kernel config in order to get the forcedeth module, Google for “forcedeth kernel config” and you will find out that what we are looking for is CONFIG_FORCEDETH. Easy.

lspci is not a one-stop shop, as the name implies. As a general rule , /proc and /sys will give you lots of info about your hardware. What you will not find in the lspci output is, for example, CPU info. /proc/cpuinfo helps with exactly the information you needed.

If you have external USB-connected devices you wanna support, lsusb is your buddy. If you don’t know for sure what drivers you’ll need for a specific piece of hardware and Google won’t help, try to leave all the options that seem related enabled. The overhead will be insignificant and after you get some experience you will know better what to leave enabled and what to disable. Don’t expect to get a perfect kernel from the start, practice makes perfect.

Check out our tutorial on Getting to know the hardware of your Linux system in order to see a bunch of commands and tips that will reveal information about the hardware in your system.

After you think you got all the bases covered, sit down and think again: what will you possibly need in the future? An external card reader? An iPod? Enable the drivers and you will avoid future issues with missing hardware support.

We suggest you use the classic pen and paper to write down a list with your hardware configuration, in detail with the kernel modules used, etc. Files come and go, hard disks too, but a piece of paper stuck to the case somewhere will help you and maybe others.

What do you do with the computer? Do you use virtualization? Enable Xen and/or KVM support. Does your distribution enforce SELinux or Tomoyo or other security framework? Do you need it? Enable the respective parts.

Now that we are set, let’s get to the configuration part.

How to configure the Linux kernel

We said earlier that we’ll describe our method: well, here it is. We use the distribution’s configuration, of course if we see it works with our hardware, which usually happens, since we have nothing exotic.

There should be a file config-5.13.0-27-generic inside your /boot directory, although the exact file name will likely be different, since it changes with each new Linux kernel version. We can simply copy this into our cloned Linux kernel directory’s .config file, which in our case is ~/linux/.config.

  1. Adapt the following command to use your own paths and file names.
    $ cp /boot/config-5.13.0-27-generic ~/linux/.config/.config 

    Use the version that’s as close version-wise as possible to the kernel you’re about to compile. Thus you will ensure that you’ll get no compatibility issues.

  2. If you want to just use the config file as it is, just issue:
    $ make oldconfig 

    Then, proceed with the compilation. However, we don’t want that, so we will just execute this command:

    $ make menuconfig 

  3. You will see a curses-based, easy to use menu. Go to “Load an alternate configuration file” and enter the name of your config file (.config, in our example, and recommended). You can now proceed to alter options and save the configuration file in the end.
    Linux kernel configuration ncurses menu
    Linux kernel configuration ncurses menu
  4. In “General setup” we usually leave things as they are, but you, of course, are free to change anything you like. The usual warning applies : do not change what you don’t know. Remember that this type of configuration is dependency-based : if you disable/enable an item, those items that depend on it will also be affected. So, for example, if you disable networking, all network-related options will also be disabled automatically.
  5. “Processor type and features” must be altered to reflect your target processor : we have an AMD K8-based CPU, so we selected “Processor family -> Opteron/Athlon64/Hammer/K8”.
  6. In “Networking support”, since this is a desktop/workstation with a simple Ethernet connection, we disabled Amateur Radio, Infrared, Bluetooth, Wireless and other options that don’t apply. Of course your mileage may and will vary. Remember that each item has an associated Help menu, accessible through the “Help” button in the bottom part of the screen, and you’ll find out what the driver does, what hardware coverage it does have, etc.
  7. Going further to “Device drivers”, here you’ll probably have a lot to disable, since here is the bulk of the hardware drivers that Linux supports. Keep the hardware configuration sheet handy and make sane choices. If at first your new kernel doesn’t boot, boot a working kernel (set your boot loader’s timeout to something like 10 seconds so you can have time to choose) and see what went wrong. Use the in-tree documentation and the Internet.
  8. Going further to “Kernel hacking”, if you want to be(come) a kernel developer, here you’ll find options to help you isolate and document bugs. Otherwise, leave these as they are, as debugging options tend to bloat and slow down your system.
  9. After you’re through, select “Save an alternate configuration file” and enter .config (recommended again), then Exit. You are now ready to compile your kernel. A last word of advice, though: start by playing it safe, then gradually eliminate unneeded drivers until you get a slim, working kernel. It’s easier going from big to smaller than the other way around.

Building and installing Linux kernel

Now that we have our kernel configured with the proper options, we can move on to compiling it. As mentioned earlier, the process of compiling could take quite a while, depending on your system’s hardware.

  1. Building the Linux kernel is actually the same on any system:
    # make

    This will build the kernel image you will install later. You can use -jn as a make argument, where n will be the number of CPU cores in your system + 1 in order to enable parallel building which, of course, will speed up the process.

  2. This next step is also universal:
    # make modules_install
  3. On most distros, this next step will also be identical. On some others, such as Arch, you will be required to use cp instead of make. You will find every distro’s way to install a custom kernel online, or you’ll want to create a kernel package and simply install it with the usual package management tools. However it will be, remember that the distribution’s documentation takes precedence here.
    # make install
  4. And now…you have a fresh kernel installed, let’s test it! Reboot and select the new kernel for booting.

Troubleshooting bugs in your kernel

If you built a vanilla kernel and you find a bug, like some oops or panic, read the documentation (REPORTING-BUGS in the root of the kernel tree) and document your bug as thoroughly as possible. If it’s a distro-patched kernel, use that distro’s bug reporting tools, of course, and the maintainers will talk to upstream to solve the issue.

Closing Thoughts

Always keep a good working kernel and config file handy in order to save yourself some time and energy. A good custom kernel will often give you a more responsive system, especially if you use a general purpose distro that includes almost every kernel driver conceivable. Good luck.

Comments and Discussions
Linux Forum