Kernel
Matteo Salonia's Kernel build, optimized 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 zswap
- Initramfs: Dracut
- Bootloader: GRUB
- Init: OpenRC
- Filesystem: FAT32 for the ESP, XFS for the RootFS, ext4 for various things.
- Logind: elogind
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 three default configs:
- config: ThinkPad T470p, with CPU i7-7820HQ (Kaby Lake, 4C8T), Nvidia GeForce 940MX dGPU + Intel HD 630 iGPU, SATAIII/NVMe SSD, 2560x1440 display.
- config.t440p: ThinkPad T440p, with CPU i7-4700MQ (Haswell, 4C8T), Intel HD4600 iGPU, SATAIII SSD, 1366x768 display.
- config.pc: Custom-built PC, with CPU i5-11400 (Rocket Lake, 6C12T), Intel UHD 730 iGPU, NVMe SSD.
Verify your desired components are enabled in the Kernel, if you choose my config as a starting point. For example, components relative to AMD, Nvidia (not on T470p), 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 the one 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.,
Gentoo users: it is highly recommended you use sys-kernel/installkernel to automatically create the initramfs & update the bootloader config, by respecting your system preferences (e.g. initramfs->dracut, bootloader->GRUB).,
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 versions are available, you just need to list the directory contents with ls:
$ ls
6.12.8-gentoo # <-- Kernel config
bore-scheduler
clear-patches
kernel_compiler_patch
patches
v4l2loopback
build.sh
README.mdIn this example, we'll be using Linux 6.12.8-gentoo.
Your Kernel will surely have a different version. No problem: you just need to copy the folder, and rename it according to your version. For example, if your version is 6.12.9-zen, you just need to run: cp -r 6.12.8-gentoo 6.12.9-zen. Don't forget to modify the KVER variable whenever the primary version differs (e.g.: 6.12.8 -> 6.12.9), 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:
-
CUSTDIR: this project's directory. Default:/usr/src/usr-kernel -
KVER: primary Kernel version. -
PVER: secondary/custom Kernel version. -
KERNELDIR: directory where Kernels are stored. Default:/usr/src -
JOBS: how many threads to use for compilation. Recommended: physical core count. -
CONFIGFILE: the Kernel config filename that will be copied from the config directory. Default:config
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 |
|---|---|---|
| Short flag | Long flag | Description |
| -b | --skip-build | Do not build the Kernel. |
| -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. |
| -g | --graphite | Compile the Kernel with Graphite |
| -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. |
| -p | --patches | Apply user patches. |
| -r | --bore | Build Kernel with BORE scheduler |
| -v | --v4l2 | Compile the v4l2loopback module. |
| -y | --flags | Print flags and exit. |
| -z | --vars | Print 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 -pThis will allow us to:
-
-l: Apply Clear Linux patches -
-m: Configure the Kernel viamake menuconfig -
-p: Apply included patches
Once the Kernel config process is done, the new config file will be available as /usr/src/linux/.config (or under $KERNELDIR/.config if KERNELDIR has been set).
Now we need to copy .config from the Kernel directory to the chosen Kernel directory (in this case, 6.12.8-gentoo), to then compare the two files and see any changes:
cp /usr/src/linux/.config 6.12.8-gentoo/config.new
diff -u 6.12.8-gentoo/config{,.new} | vimThe last command 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 needed (example: you use a custom config)
Note the 6.12.8-gentoo in both commands: modify this whenever you use a different Kernel version.
After verifying the differences, let's replace our config file with the config.new file, and move on to the actual Kernel compilation:
mv 6.12.8-gentoo/config{.new,}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 -pNote the repeated presence of the patch options (-l, -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. This behavior is wanted, because it helps us reduce errors caused by patches that are malformed, not applied correctly, not wanted, and/or various errors.
The script will show any compilation error, as well as showing the true compilation time, not considering the time it takes to apply patches, and so on.
Once the script finishes its execution, thanks to installkernel the initramfs will be generated, and the bootloader will be updated. With my configuration these correspond to dracut and grub. Obviously it'll be your responsibility to configure installkernel before trying to install the Kernel.
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 manually update the initramfs, nor the bootloader, because they'll be automatically updated (see above).
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
# dash: include /bin/dash 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
# usrmount: mount /usr
dracutmodules+=" base dash fs-lib kernel-modules rescue resume rootfs-block shutdown udev-rules usrmount "
# Do not include bash (we use dash)
omit_dracutmodules="bash"
# 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 -fReplace 6.8.2-gentoo with your Kernel version. Pay attention to the -f flag: it forces the initramfs generation, 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 we'll only see GRUB2.
Most users, at this point, will surely already have a working system, and a configured bootloader. This then lets us simply update the bootloader config, without modifying any other files.
So, you just need to run as root:
grub-mkconfig -o /boot/grub/grub.cfgThis 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.
