Logo

Kernel

This page contains all the details necessary to use my script to configure the Linux Kernel, optimizing it to maximize the hardware's performance, and be as light as possible.

Go to:
Introduction Setup Extra

Introduction

My setups are based on a system comprised of the following components:

  • Distro:  Gentoo Linux
  • Kernel Compression: LZ4 for the initramfs, zstd for modules
  • Initramfs:  Dracut
  • Bootloader:  GRUB
  • Init:  OpenRC
  • Filesystem: FAT32 for the ESP, XFS for the rootfs, ext4 for various things.
  • Logind:  elogind

Note: since I use Gentoo, the package names may vary from your distro's (Arch, Debian, Fedora, ...) packages. Please verify whether the names may vary, and take note of them.

There are two default configs:

  1. config: for my ThinkPad T440p, with CPU i7-4700MQ, no GPU (iGPU), 8GB RAM, SSD M.2 2242 + SSD SATAIII.
  2. config.pc: for my desktop PC, with CPU i5-11400, no GPU (iGPU), 16GB RAM, SSD NVME Samsung 980 Pro.

Since the changes made to the Kernel config, it'll be necessary to verify the desired components are enabled in the Kernel, whenever you'd choose my config as a starting point. For example, components relative to AMD, Nvidia, NUMA, etc. have been disabled.
If you don't know where to start, use an already existing config that you know works on your hardware, if available, or else use any Kernel's default config, like that provided by your distro, or the Kernel's very own default config.

Setup

Make sure to have all the tools necessary to proceed. Verify you have git, gcc, make, etc. Tipically, most compilation tools are provided by packages like base-devel. I suggest you also verify the presence of linux-firmware, in order to have the necessary firmware for any nonfree hardware. Don't forget to download the microcode that is most appropriate, whether it be Intel, AMD, or any other. Finally, make sure you have lz4 and zstd, in order to compress various Kernel components.

1. Get the repository

We'll use the /usr/src/usr-kernel directory in order to save this project. Make sure you have read and write permissions, in order to create the directory.

git clone --recurse-submodules "https://github.com/saloniamatteo/kernel" /usr/src/usr-kernel
cd /usr/src/usr-kernel

Whenever the chosen directory differs from the default, don't forget to modify the CUSTDIR variable in build.sh

2. Version selection

Once you get the repository, choose an available version. To see which version is available, you just need to list the directory contents with ls. In this example, we'll use Linux 6.8.2-gentoo.

Your Kernel will definitely have a different version.
Don't panic: you just need to copy the folder, and rename it according to your version. For example, if your version would be 6.8.3-zen, you just need to execute: cp -r 6.8.2-gentoo 6.8.3-zen.
Don't forget to modify the KVER variable whenever the primary version differs (e.g.: 6.8.2 -> 6.8.3), and PVER whenever the secondary/custom version differs (e.g.: gentoo -> zen)

3. Modify the script

Now, we need to verify the contents of build.sh. Modify the file with any text editor, and note the following variables:

  • ARCHVER: CPU architecture code, to optimize the Kernel. Here is the full list of codes:
     1. AMD Opteron/Athlon64/Hammer/K8 (MK8)
    2. AMD Opteron/Athlon64/Hammer/K8 with SSE3 (MK8SSE3)
    3. AMD 61xx/7x50/PhenomX3/X4/II/K10 (MK10)
    4. AMD Barcelona (MBARCELONA)
    5. AMD Bobcat (MBOBCAT)
    6. AMD Jaguar (MJAGUAR)
    7. AMD Bulldozer (MBULLDOZER)
    8. AMD Piledriver (MPILEDRIVER)
    9. AMD Steamroller (MSTEAMROLLER)
    10. AMD Excavator (MEXCAVATOR)
    11. AMD Zen (MZEN)
    12. AMD Zen 2 (MZEN2)
    13. AMD Zen 3 (MZEN3)
    14. AMD Zen 4 (MZEN4)
    15. Intel P4 / older Netburst based Xeon (MPSC)
    16. Intel Core 2 (MCORE2)
    17. Intel Atom (MATOM)
    18. Intel Nehalem (MNEHALEM)
    19. Intel Westmere (MWESTMERE)
    20. Intel Silvermont (MSILVERMONT)
    21. Intel Goldmont (MGOLDMONT)
    22. Intel Goldmont Plus (MGOLDMONTPLUS)
    23. Intel Sandy Bridge (MSANDYBRIDGE)
    24. Intel Ivy Bridge (MIVYBRIDGE)
    25. Intel Haswell (MHASWELL)
    26. Intel Broadwell (MBROADWELL)
    27. Intel Skylake (MSKYLAKE)
    28. Intel Skylake X (MSKYLAKEX)
    29. Intel Cannon Lake (MCANNONLAKE)
    30. Intel Ice Lake (MICELAKE)
    31. Intel Cascade Lake (MCASCADELAKE)
    32. Intel Cooper Lake (MCOOPERLAKE)
    33. Intel Tiger Lake (MTIGERLAKE)
    34. Intel Sapphire Rapids (MSAPPHIRERAPIDS)
    35. Intel Rocket Lake (MROCKETLAKE)
    36. Intel Alder Lake (MALDERLAKE)
    37. Intel Raptor Lake (MRAPTORLAKE)
    38. Intel Meteor Lake (MMETEORLAKE)
    39. Intel Emerald Rapids (MEMERALDRAPIDS)
    40. Generic-x86-64 (GENERIC_CPU)
    41. Generic-x86-64-v2 (GENERIC_CPU2)
    42. Generic-x86-64-v3 (GENERIC_CPU3)
    43. Generic-x86-64-v4 (GENERIC_CPU4)
    44. Intel-Native optimizations autodetected by GCC (MNATIVE_INTEL)
    45. AMD-Native optimizations autodetected by GCC (MNATIVE_AMD)
  • CONFIGFILE: config file name, that will be copied from the directory to the Kernel.
  • JOBS: how many threads to use for the compilation. I recommend setting the number of cores.
  • KVER: primary Kernel version.
  • PVER: secondary/custom Kernel version.
  • KERNVER: full Kernel version, do not modify.
  • CUSTDIR: this project's directory, modify whenever it differs from the defaults.
  • CLEARDIR: Clear Linux directory name, do not modify.
  • PATCHDIR: patch directory name, do not modify.
  • V4L2DIR: V4L2loopback directory name, do not modify.
  • CFODIR: Kernel Compiler Patch directory name, do not modify.
  • USRDIR: chosen Kernel version directory name, do not modify.
  • KERNELDIR: set this variable whenever the Kernel directory differs from /usr/src.

4. Flag selection

After modifying build.sh, we have to set the correct parameters in order to decide what to do.
Here's a table with all the parameters (flags).

Short flagLong flagDescription
Short flagLong flagDescription
-b--skip-buildDo not build the Kernel.
-c--skip-cfgDo not copy the Kernel config file (config).
-d--distccUse distcc to speed up Kernel compilation
-e--ccacheUse ccache to speed up Kernel compilation
-f--fastmathCompile the Kernel with unsafe fast math options.
-h--helpShow the help menu and exit.
-l--clearl-psApply Clear Linux patches.
-m--menuconfigExecute make menuconfig in the Kernel directory and exit without compiling.
-o--cpu-optsCompile the Kernel with CPU family optimizations.
-p--patchesApply user patches.
-r--boreBuild Kernel with BORE scheduler
-v--v4l2Compile the v4l2loopback module.
-z--varsPrint variables and exit.

5. Kernel configuration

Tipically, it'll be necessary to configure the Kernel, starting from a config file. To do so, you need to run the following as root:

./build.sh -l -m -o -p
This will allow us to:
  • -l: Apply Clear Linux patches
  • -m: Configure the Kernel, starting from an existing config, or load a custom config file
  • -o: Apply the CPU family optimization patches
  • -p: Apply user patches
Once the Kernel config process is done, the new config file will be available as /usr/src/linux/.config (or under $KERNELDIR/.config whenever KERNELDIR would've been set).

Now we need to copy .config from the Kernel directory to the current directory, to then compare the two files and see any changes.

cp /usr/src/linux/.config config.new
diff -u config config.new | vim
The last command above executes the diff command, showing the differences between our starting config file, and the new config.new file, to then show everything with the Vim editor. Obviously, it's necessary to modify the name of the config file in the command above whenever appropriate.

After verifying the differences, let's replace our config file with the config.new file, and move on to the actual Kernel compilation.

6. Kernel compilation

After making sure we have everything that's necessary, we can proceed with compiling the Kernel with the following command, executing it as root:

./build.sh -f -l -o -p
Note the repeated presence of the patch options (-l, -o, -p). This is because the script automatically reverts all changes made by the patches present in the Kernel directory, where possible, and removes said patches. I programmed the script this way because I often have to revert and remove various patches, especially after multiple compilations.

Note that the script will show any compilation error, as well as showing the true compilation time, not considering patches and so on.

Once the script finishes its execution, it'll install the Kernel, automatially executing dracut to generate the initramfs, and it'll update grub, thanks to installkernel, which most distros tipically have. If your setup does not use dracut nor grub, check your installkernel config, it'll be set up to use whatever you're currently using.

Extra

This section specifies any extra steps to take after Kernel compilation, that do not depend on the script. Using the script, it won't be necessary to execute dracut nor grub manually, because they'll be automatically executed.

V4L2loopback

The script will automatically install this module for the compiled Kernel version. The only step you need to take is add the module settings, because the script does not check whether they exist or not.

Modify /etc/modprobe.d/v4l2loopback.conf, and add the following:

options v4l2loopback exclusive_caps=1 card_label="Camera2"
Here you can modify card_label to set the device name, whenever necessary, for example if you want to hide the fact this is a virtual device, or if you simply would like a better name.

Initramfs

To run the Kernel an initramfs is necessary. To generate it, I'll use dracut.
First of all, make sure you configured dracut. For example, here's my /etc/dracut.conf:

# Equivalent to -H
hostonly="yes"

# Add various modules
# Module Description
# base include basic utilities
# bash include /bin/bash as /bin/sh
# fs-lib include filesystem tools like mount
# kernel-modules include kernel modules
# rescue include various utils for rescue mode
# resume allow initramfs to resume from low-power state
# rootfs-block mount block device that contains rootfs
# shutdown set up hooks to run on shutdown
# udev-rules include udev and some basic rules
# uefi-lib include UEFI tools
# usrmount mount /usr
dracutmodules+=" base bash fs-lib kernel-modules rescue resume rootfs-block shutdown udev-rules uefi-lib usrmount "

# Include elogind
install_items="/lib64/elogind/elogind-uaccess-command"

# Use lz4 to compress the initramfs
compress="lz4"

# Add early microcode loading
early_microcode="yes"

It's sufficient to execute the following command as root:

dracut --kver 6.8.2-gentoo -f
Replace 6.8.2-gentoo whenever the Kernel version is different. Be careful to the -f flag, that forces the initramfs regeneration, even if it already exists for the chosen Kernel.
The initramfs will be available under /boot, together with the previously compiled Kernel's files.

Bootloader

To boot our new Kernel, we need to configure the bootloader. In this section, I'll only talk about GRUB2.

Most users, at this point, will surely already have a working system, and a configured bootloader. This fact allows us to just update the bootloader config, without modifying any other files.

So, you just need to run as root:

grub-mkconfig -o /boot/grub/grub.cfg
This command will tell us the available Kernels (and any other OS), that will be available once we reboot our system, in addition to telling us which microcode(s) were found.