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

This project was realized and is maintained to be a "tool", in order to help me configure the Kernel as I please, allowing me to also apply patches in order to make it more efficient and performant, optimizing it for the available hardware, in the slightest detail.

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

N.B.: 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-11400MQ, 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 surely 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 flag Long flag Description
-b --skip-build Skip Kernel compilation.
-c --skip-cfg Do not copy the Kernel config file (config).
-d --distcc Use distcc to speed up Kernel compilation
-e --ccache Use ccache to speed up Kernel compilation
-f --fastmath Compile the Kernel with unsafe fast math options.
-h --help Show the help menu and exit.
-l --clearl-ps Apply Clear Linux patches.
-m --menuconfig Execute make menuconfig in the Kernel directory and exit without compiling.
-o --cpu-opts Compile the Kernel with CPU family optimizations.
-p --patches Apply user patches.
-v --v4l2 Compile the v4l2loopback module.

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.

It's good to specify 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.