Logo

Kernel

Questa pagina contiene tutti i dettagli necessari per usare il mio script per configurare il Kernel Linux, ottimizzandolo per massimizzare le prestazioni dell'hardware, ed essere più leggero possibile.

Vai a:
Introduzione Setup Extra

Introduzione

I miei setup si basano su un sistema composto dai seguenti componenti:

Nota bene: dato che uso Gentoo, i nomi dei pacchetti potrebbero essere diversi dai nomi dei pacchetti che usa la vostra distro (Arch, Debian, Fedora, ...). Siete pregati di verificare qualora i nomi fossero diversi, e di annotarli per procedere con questa guida.

Vi sono due configurazioni di default:

  1. config: per il mio ThinkPad T440p, con CPU i7-4700MQ, nessuna GPU (iGPU), 8GB RAM, SSD M.2 2242 + SSD SATAIII.
  2. config.pc: per il mio PC fisso, con CPU i5-11400, nessuna GPU (iGPU), 16GB RAM, SSD NVME Samsung 980 Pro.

Dati i cambiamenti effettuati nella configurazione del Kernel, sarà necessario verificare che i componenti desiderati sono abilitati nel Kernel, qualora sceglieste la mia configurazione come punto di partenza. Ad esempio, componenti relativi ad AMD, Nvidia, NUMA, ecc. sono stati disabilitati.
Se non sapete da dove partire, usate una configurazione già esistente che sapete funzioni sul vostro hardware, se disponibile, altrimenti usate la configurazione di default di un qualsiasi Kernel, come quella fornita dalla vostra distro, o la configurazione di default del Kernel.

Setup

Assicuratevi di avere tutti gli strumenti necessari per poter proseguire. Verificate di avere git, gcc, make, ecc. Tipicamente, la maggior parte di strumenti per la compilazione viene fornita da pacchetti come base-devel. Consiglio di verificare anche la presenza di linux-firmware, in modo tale da avere i necessari firmware per eventuali componentistiche nonfree. Non dimenticate di scaricare il microcode adatto, che sia Intel, AMD, o altro. Infine, verificate la presenza di lz4 e zstd, per la compressione di vari componenti del Kernel.

1. Ottenimento repository

Useremo la directory /usr/src/usr-kernel per salvare questo progetto, e tutte le eventuali modifiche.
Assicuratevi di avere permessi di lettura e scrittura, in modo tale da poter creare la directory.

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

Qualora la directory scelta dovesse essere diversa, non dimenticatevi di modificare la variabile CUSTDIR nel file build.sh.

2. Selezione versione

Una volta scaricata la repository, scegliete una versione disponibile. Per vedere quali versioni sono disponibili, basta vedere i contenuti della directory con ls. In questo esempio, utilizzeremo Linux 6.8.2-gentoo.

Il vostro Kernel sicuramente avrà una versione diversa.
Niente panico: basterà copiare la cartella, e rinominarla in base alla vostra versione. Ad esempio, se la vostra versione dovesse essere 6.8.3-zen, basterà eseguire: cp -r 6.8.2-gentoo 6.8.3-zen.
Non dimenticatevi di modificare la variabile KVER qualora la versione primaria dovesse essere diversa (esempio: 6.8.2 -> 6.8.3), e la variabile PVER qualora la versione secondaria dovesse essere diversa (esempio: gentoo -> zen)

3. Modifica script

A questo punto, non ci resta che verificare il contenuto di build.sh. Modifichiamo il file con qualsiasi editor di testo, e osserviamo le seguenti variabili:

  • ARCHVER: codice architettura processore, per ottimizzare il Kernel. Ecco la lista completa di codici:
     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: il nome del file di configurazione, che verrà copiato dalla directory al Kernel.
  • JOBS: quanti thread usare per la compilazione. Si consiglia di impostare al numero di core.
  • KVER: versione primaria Kernel.
  • PVER: versione secondaria/personalizzata Kernel.
  • KERNVER: versione completa Kernel, non modificare.
  • CUSTDIR: directory che contiene questo progetto, da modificare qualora sia diversa dai default.
  • CLEARDIR: nome directory patch Clear Linux, non modificare.
  • PATCHDIR: nome directory patch, non modificare.
  • V4L2DIR: nome directory V4L2loopback, non modificare.
  • CFODIR: nome directory Kernel Compiler Patch, non modificare.
  • USRDIR: directory che contiene la versione scelta del Kernel, non modificare.
  • KERNELDIR: questa variabile va impostata qualora la directory del Kernel sia diversa da /usr/src.

4. Selezione flag

Dopo aver modificato build.sh, bisogna selezionare i necessari parametri per poter stabilire quali azioni intraprendere.
Segue ora una tabella con tutti i vari parametri (flag).

Flag breveFlag estesoDescrizione
Flag breveFlag estesoDescrizione
-b--skip-buildNon compilare il Kernel.
-c--skip-cfgNon copiare il file di configurazione Kernel (config).
-d--distccUsa distcc per velocizzare la compilazione del Kernel.
-e--ccacheUsa ccache per velocizzare la compilazione del Kernel.
-f--fastmathCompila il Kernel con opzioni di matematica veloce non sicura (unsafe fast math).
-h--helpMostra il menu' di aiuto ed esci.
-l--clearl-psApplica le patch di Clear Linux.
-m--menuconfigEsegui make menuconfig nella directory del Kernel ed esci senza compilare.
-o--cpu-optsCompila il Kernel con le ottimizzazioni per la famiglia del processore.
-p--patchesApplica le patch utente.
-r--boreCompila Kernel con scheduler BORE
-v--v4l2Compila il modulo v4l2loopback.
-z--varsMostra variabili ed esci.

5. Configurazione Kernel

Tipicamente, sarà necessario andare a configurare il Kernel, partendo da un file di configurazione. Per fare ciò, basterà eseguire il seguente comando come utente root:

./build.sh -l -m -o -p
Questo ci permetterà di:
  • -l: Applicare le patch di Clear Linux
  • -m: Configurare il Kernel, potendo partire da una configurazione già impostata, o caricarne una personalizzata da cui avere un punto di partenza
  • -o: Applicare le ottimizzazioni per la famiglia del processore
  • -p: Applicare le patch utente
Una volta terminato il processo di configurazione del Kernel, il nuovo file di configurazione sarà disponibile presso /usr/src/linux/.config (oppure sotto $KERNELDIR/.config qualora KERNELDIR fosse stato impostato).

A questo punto bisognerà copiare il file .config dalla directory del Kernel alla directory attuale, per poi confrontare i due file e controllare eventuali cambiamenti.

cp /usr/src/linux/.config config.new
diff -u config config.new | vim
L'ultimo comando qui sopra esegue il comando diff, mostrando le differenze tra il nostro file di partenza config ed il nuovo file config.new, per poi mostrare il tutto con l'editor Vim. Ovviamente, bisogna modificare il nome del file config nel comando sopra qualora fosse necessario.

Dopo aver verificato le eventuali differenze, sostituiamo il nostro file config con il file config.new, e passiamo alla vera e propria compilazione del Kernel.

6. Compilazione Kernel

Dopo essere sicuri di avere tutto il necessario, è possibile compilare il Kernel con il seguente comando, eseguendolo come utente root:

./build.sh -f -l -o -p
Notate la presenza ripetuta delle opzioni di patch (-l, -o, -p). Questo perchè lo script, in automatico, ripristina tutti i cambiamenti effettuati dalle patch presenti nella directory del Kernel, ove possibile, e rimuove gli eventuali file patch. Ho programmato lo script in questo modo in quanto mi capita spesso di dover ripristinare e rimuovere varie patch, soprattutto dopo molteplici compilazioni.

È bene specificare che lo script ci mostrerà tutti gli eventuali errori di compilazione e non solo, in aggiunta al calcolo del tempo effettivo di compilazione, non considerando quindi patch ed altro.

Al termine dell'esecuzione, lo script installerà il Kernel, eseguendo in automatico dracut per generare l'initramfs, ed aggiornerà grub, grazie ad installkernel, che tipicamente tutte le distro hanno. Se la vostra configurazione non prevede l'uso di dracut o di grub, verificate la configurazione di installkernel, sarà già impostato per usare quello che state usando attualmente.

Extra

Questa sezione specifica gli eventuali passaggi da effettuare dopo aver terminato la compilazione del Kernel, che non dipendono dallo script. Usando lo script, non sarà necessario eseguire nè dracut nè grub manualmente, perchè verranno eseguiti in automatico.

V4L2loopback

Lo script andrà in automatico ad installare questo modulo per la versione del Kernel compilata. L'unico passaggio da effettuare è aggiungere le impostazioni del modulo, in quanto lo script non controlla se sono già presenti o meno.

Modificate il file /etc/modprobe.d/v4l2loopback.conf, ed inserite il seguente contenuto:

options v4l2loopback exclusive_caps=1 card_label="Camera2"
Qui potete modificare card_label per impostare il nome del dispositivo, qualora fosse necessario, ad esempio se si volesse mascherare il fatto che questo è un dispositivo virtuale, o se semplicemente volete un nome migliore.

Initramfs

Per avviare il Kernel è necessario un initramfs. Per generarlo, userò dracut.
Prima di tutto, accertatevi di aver configurato dracut. Ad esempio, ecco il mio /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"

È sufficiente eseguire, come utente root, il seguente comando:

dracut --kver 6.8.2-gentoo -f
Modificate 6.8.2-gentoo qualora non fosse la versione del Kernel interessata. Attenzione al flag -f, che forza la rigenerazione dell'initramfs anche se già esiste per la versione del Kernel interessata.
Fatto ciò, l'initramfs sarà disponibile sotto /boot, insieme ai file del Kernel precedentemente compilato.

Bootloader

Per avviare il nostro nuovo Kernel, sarà necessario configurare il bootloader. In questa sezione, sarà trattato esclusivamente GRUB2.

La maggior parte degli utenti, arrivati a questo punto, sicuramente avranno già un sistema funzionante, ed un bootloader configurato. Questo fatto ci allevia il carico, richiedendo semplicemente un aggiornamento della configurazione, senza modificare ulteriori file.

Perciò, è necessario eseguire come utente root:

grub-mkconfig -o /boot/grub/grub.cfg
Il comando ci comunicherà i Kernel (ed eventuali altri sistemi operativi) trovati, che saranno disponibili al riavvio del nostro sistema, oltre a comunicarci i microcode trovati.