Linux kernel: Difference between revisions
m Remove empty lines |
→Custom configuration: emphasise structuredExtraConfig and note what actually causes the "unused option" errors |
||
(33 intermediate revisions by 21 users not shown) | |||
Line 3: | Line 3: | ||
== Configuration == | == Configuration == | ||
You can | You can change the installed kernel using {{nixos:option|boot.kernelPackages}}. To use the latest release: | ||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
{ | |||
boot.kernelPackages = pkgs | boot.kernelPackages = pkgs.linuxPackages_latest; | ||
</ | } | ||
</nowiki>}} | |||
Then rebuild your system and reboot to use your new kernel: | |||
<syntaxHighlight lang="console"> | <syntaxHighlight lang="console"> | ||
$ sudo nixos-rebuild boot | $ sudo nixos-rebuild boot | ||
Line 17: | Line 19: | ||
=== List available kernels === | === List available kernels === | ||
You can list available kernels using <code>nix repl</code> (previously <code>nix-repl</code>) by typing the package name and using the tab completion: | You can list available kernels using <code>nix repl</code> (previously <code>nix-repl</code>) by typing the package name and using the tab completion: | ||
<syntaxHighlight lang="console"> | <syntaxHighlight lang="console"> | ||
$ nix repl | $ nix repl | ||
Line 26: | Line 28: | ||
nix-repl> pkgs.linuxPackages | nix-repl> pkgs.linuxPackages | ||
pkgs.linuxPackages pkgs. | pkgs.linuxPackages pkgs.linuxPackages_custom | ||
pkgs.linuxPackages-libre pkgs. | pkgs.linuxPackages-libre pkgs.linuxPackages_custom_tinyconfig_kernel | ||
pkgs.linuxPackages-rt pkgs. | pkgs.linuxPackages-rt pkgs.linuxPackages_hardened | ||
pkgs.linuxPackages- | pkgs.linuxPackages-rt_latest pkgs.linuxPackages_latest | ||
pkgs. | pkgs.linuxPackagesFor pkgs.linuxPackages_latest-libre | ||
pkgs. | pkgs.linuxPackages_4_14 pkgs.linuxPackages_latest_hardened | ||
pkgs. | pkgs.linuxPackages_4_19 pkgs.linuxPackages_latest_xen_dom0 | ||
pkgs. | pkgs.linuxPackages_4_19_hardened pkgs.linuxPackages_latest_xen_dom0_hardened | ||
pkgs. | pkgs.linuxPackages_4_9 pkgs.linuxPackages_lqx | ||
pkgs. | pkgs.linuxPackages_5_10 pkgs.linuxPackages_rpi0 | ||
pkgs. | pkgs.linuxPackages_5_10_hardened pkgs.linuxPackages_rpi02w | ||
pkgs.linuxPackages_5_4 pkgs.linuxPackages_testing | pkgs.linuxPackages_5_15 pkgs.linuxPackages_rpi1 | ||
pkgs. | pkgs.linuxPackages_5_15_hardened pkgs.linuxPackages_rpi2 | ||
pkgs. | pkgs.linuxPackages_5_18 pkgs.linuxPackages_rpi3 | ||
pkgs. | pkgs.linuxPackages_5_19 pkgs.linuxPackages_rpi4 | ||
pkgs. | pkgs.linuxPackages_5_4 pkgs.linuxPackages_rt_5_10 | ||
pkgs. | pkgs.linuxPackages_5_4_hardened pkgs.linuxPackages_rt_5_15 | ||
pkgs. | pkgs.linuxPackages_6_0 pkgs.linuxPackages_rt_5_4 | ||
pkgs.linuxPackages_6_1 pkgs.linuxPackages_rt_6_1 | |||
pkgs.linuxPackages_6_1_hardened pkgs.linuxPackages_testing | |||
pkgs.linuxPackages_6_2 pkgs.linuxPackages_testing_bcachefs | |||
pkgs.linuxPackages_6_3 pkgs.linuxPackages_xanmod | |||
pkgs.linuxPackages_6_4 pkgs.linuxPackages_xanmod_latest | |||
pkgs.linuxPackages_6_5 pkgs.linuxPackages_xanmod_stable | |||
pkgs.linuxPackages_6_6 pkgs.linuxPackages_xen_dom0 | |||
pkgs.linuxPackages_6_6_hardened pkgs.linuxPackages_xen_dom0_hardened | |||
pkgs.linuxPackages_6_7 pkgs.linuxPackages_zen | |||
pkgs.linuxPackages_6_8 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 51: | Line 62: | ||
Note that if you deviate from the default kernel version, you should also take extra care that extra kernel modules must match the same version. The safest way to do this is to use <code>config.boot.kernelPackages</code> to select the correct module set: | Note that if you deviate from the default kernel version, you should also take extra care that extra kernel modules must match the same version. The safest way to do this is to use <code>config.boot.kernelPackages</code> to select the correct module set: | ||
< | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
{ config, ... }: | { config, ... }: | ||
{ | { | ||
boot.extraModulePackages = with config.boot.kernelPackages; [ bbswitch ]; | boot.extraModulePackages = with config.boot.kernelPackages; [ bbswitch ]; | ||
} | } | ||
</ | </nowiki>}} | ||
=== Customizing kernel module parameters === | === Customizing kernel module parameters === | ||
You can use | You can use {{nixos:option|boot.extraModprobeConfig}}, which is analogous to creating modprobe.conf files in /etc/modprobe.d/ in regular Linux distributions. This can be used for both built-in and loadable kernel modules. | ||
< | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
boot.extraModprobeConfig = '' | { | ||
boot.extraModprobeConfig = '' | |||
# example settings | |||
options yourmodulename optionA=valueA optionB=valueB # syntax | |||
options thinkpad_acpi fan_control=1 # example #1 kernel module parameter | |||
''; | options usbcore blinkenlights=1 # example #2 kernel module parameter | ||
</ | ''; | ||
} | |||
</nowiki>}} | |||
{{nixos:option|boot.kernelParams}} can be used to set additional kernel command line arguments at boot time. It can only be used for built-in modules. For example: | |||
< | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
{ | { | ||
boot.kernelParams = [ | boot.kernelParams = [ | ||
"quiet" | "quiet" | ||
"splash" | "splash" | ||
"usbcore.blinkenlights=1" | "usbcore.blinkenlights=1" | ||
]; | ]; | ||
} | } | ||
</ | </nowiki>}} | ||
=== Enable SysRq === | |||
The Linux kernel is known<ref>https://github.com/hakavlad/nohang?tab=readme-ov-file#what-is-the-problem</ref> to not handle out-of-memory situation properly and can freeze for a long time, often leaving no option but doing a hard reboot. The [https://en.wikipedia.org/wiki/Magic_SysRq_key SysRq shortcuts] can be used to trigger a more graceful reboot. However, most keys are disabled by default on NixOS. To enable: | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
{ | |||
boot.kernel.sysctl."kernel.sysrq" = 1; | |||
} | |||
</nowiki>}} | |||
Useful shortcuts, triggered using {{ic|Alt+SysRq+<key>}}: | |||
* {{ic|h}}: Print help to the system log. | |||
* {{ic|f}}: Trigger the kernel oom killer. | |||
* {{ic|s}}: Sync data to disk before triggering the reset options below. | |||
* {{ic|e}}: SIGTERM all processes except PID 0. | |||
* {{ic|i}}: SIGKILL all processes except PID 0. | |||
* {{ic|b}}: Reboot the system. | |||
Check <code>journalctl</code> to see if you are triggering the shortcuts correctly, which might be different for your keyboard, as noted in the Wikipedia page. | |||
Also see {{nixos:option|services.earlyoom.enable}} and {{nixos:option|systemd.oomd.enable}}. | |||
=== Custom configuration === | === Custom configuration === | ||
It is sometimes desirable to change the configuration of your kernel, while keeping the kernel version itself managed through Nixpkgs | It is sometimes desirable to change the configuration of your kernel, while keeping the kernel version itself managed through Nixpkgs. | ||
One way is to use {{nixos:option|boot.kernelPatches}}<ref>[https://logs.nix.samueldr.com/nixos/2018-05-09#1525898458-1525898534; #nixos 2018-05-09]</ref><ref>[https://github.com/NixOS/nixpkgs/blob/03d4694e6110fa9c16e88ee74085ea2068c27494/nixos/modules/misc/crashdump.nix#L63-L73 <tt>nixos/modules/misc/crashdump.nix#L63-L73</tt>]</ref>. For example, {{nixos:option|boot.crashDump.enable}} is configured as shown below. Note that the {{ic|CONFIG_}} prefix is not used in the configuration names. | |||
<syntaxhighlight lang=nix> | <syntaxhighlight lang=nix> | ||
{ | { | ||
boot.kernelPatches = [ { | |||
name = "crashdump-config"; | |||
patch = null; | |||
structuredExtraConfig = { | |||
CRASH_DUMP = lib.kernel.yes; | |||
DEBUG_INFO = lib.kernel.yes; | |||
PROC_VMCORE = lib.kernel.yes; | |||
LOCKUP_DETECTOR = lib.kernel.yes; | |||
HARDLOCKUP_DETECTOR = lib.kernel.yes; | |||
}; | |||
} ]; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Alternatively, you can pass a string as <code>extraConfig</code>, with option names and answers formatted like so: | |||
< | <pre> | ||
CRASH_DUMP y | |||
DEBUG_INFO y | |||
PROC_VMCORE y | |||
LOCKUP_DETECTOR y | |||
HARDLOCKUP_DETECTOR y | |||
</pre> | |||
Another way is to create an overlay to configure either {{ic|extraConfig}} or {{ic|structuredExtraConfig}}. This allows for more flexibility, since you can basically override any available kernel option<ref>[https://github.com/NixOS/nixpkgs/blob/e6db435973160591fe7348876a5567c729495175/pkgs/os-specific/linux/kernel/generic.nix#L11-L56<tt>pkgs/os-specific/linux/kernel/generic.nix#L11-L56</tt>]</ref>. Using {{ic|structuredExtraConfig}} is recommended as it checks if the configured option are correct. | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
{ | { | ||
nixpkgs = { | nixpkgs = { | ||
overlays = [ | overlays = [ | ||
(self: super: { | (self: super: { | ||
linuxZenWMuQSS = pkgs.linuxPackagesFor (pkgs.linux_zen | linuxZenWMuQSS = pkgs.linuxPackagesFor (pkgs.linuxKernel.kernels.linux_zen.override { | ||
structuredExtraConfig = with lib.kernel; { | structuredExtraConfig = with lib.kernel; { | ||
SCHED_MUQSS = yes; | SCHED_MUQSS = yes; | ||
}; | }; | ||
ignoreConfigErrors = true; | ignoreConfigErrors = true; # not necessarily a good idea | ||
}); | }); | ||
}) | }) | ||
Line 124: | Line 169: | ||
}; | }; | ||
} | } | ||
</ | </nowiki>}} | ||
If the kernel config fails to build with messages like <code>error: unused option: DRM_I915_GVT</code>, try setting e.g. <code>DRM_I915_GVT = lib.kernel.unset</code>. Setting {{ic|ignoreConfigErrors}} will also silence these errors, at the cost of ignoring potential problems. ([https://github.com/NixOS/nixpkgs/blob/3ab9a9d12ba76f6a544c207e1364da5b3087b77c/pkgs/os-specific/linux/kernel/generate-config.pl generate-config.pl] is responsible for these; they are often produced when [https://github.com/NixOS/nixpkgs/blob/3ab9a9d12ba76f6a544c207e1364da5b3087b77c/pkgs/os-specific/linux/kernel/common-config.nix the default config] doesn't use <code>lib.kernel.option</code> for an option that is implicitly disabled by whatever change you made.) | |||
=== Pinning a kernel version === | === Pinning a kernel version === | ||
< | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux_4_19.override { | { | ||
boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linuxKernel.kernels.linux_4_19.override { | |||
argsOverride = rec { | argsOverride = rec { | ||
src = pkgs.fetchurl { | src = pkgs.fetchurl { | ||
url = "mirror://kernel/linux/kernel/ | url = "mirror://kernel/linux/kernel/v${lib.versions.major version}.x/linux-${version}.tar.xz"; | ||
sha256 = "0ibayrvrnw2lw7si78vdqnr20mm1d3z0g6a0ykndvgn5vdax5x9a"; | sha256 = "0ibayrvrnw2lw7si78vdqnr20mm1d3z0g6a0ykndvgn5vdax5x9a"; | ||
}; | }; | ||
version = "4.19.60"; | version = "4.19.60"; | ||
modDirVersion = "4.19.60"; | modDirVersion = "4.19.60"; | ||
}; | |||
}); | }); | ||
</ | } | ||
</nowiki>}} | |||
=== Debugging a failed configuration === | === Debugging a failed configuration === | ||
As dependencies between kernel configurations | As dependencies between kernel configurations need to be addressed manually, use [https://nixos.org/manual/nix/stable/command-ref/nix-build#opt-keep-failed --keep-failed] to inspect the intermediate nix config file after any build failures: | ||
{{bc|note: keeping build directory '/tmp/nix-build-linux-config-4.19.0-mptcp_v0.94.1.drv-0'}} | {{bc|note: keeping build directory '/tmp/nix-build-linux-config-4.19.0-mptcp_v0.94.1.drv-0'}} | ||
== Embedded Linux Cross-compile | == Embedded Linux Cross-compile == | ||
To configure and cross-compile Linux kernels for embedded development, often distributed separately instead of using the stock kernel, you can setup a development environment as shown below: | |||
{{file|shell.nix|nix|3=let | |||
let | |||
pkgs = import <nixpkgs> { }; | pkgs = import <nixpkgs> { }; | ||
in | in | ||
Line 157: | Line 206: | ||
targetPkgs = pkgs: (with pkgs; | targetPkgs = pkgs: (with pkgs; | ||
[ | [ | ||
pkg-config | |||
ncurses | ncurses | ||
qt5.qtbase | qt5.qtbase | ||
Line 174: | Line 223: | ||
exec bash | exec bash | ||
''; | ''; | ||
}).env | }).env}} | ||
Clone the kernel sources, enter the environment using {{ic|nix-shell}}, and then do development normally. | |||
== make menuconfig == | == make menuconfig == | ||
It is | It is not possible to run <code>make menuconfig</code> in the standard kernel shell. This is because <code>ncurses</code> is not part of your working environment when you start it with <code>nix-shell '<nixpkgs>' -A linuxPackages.kernel</code>. | ||
Use <code>linuxPackages.kernel.configEnv</code> instead, which adds ncurses as a build dependency to the kernel: | |||
<syntaxHighlight lang=console> | <syntaxHighlight lang=console> | ||
$ nix-shell | $ nix-shell '<nixpkgs>' -A linuxPackages.kernel.configEnv | ||
[nix-shell] $ unpackPhase && cd linux-* | [nix-shell] $ unpackPhase && cd linux-* | ||
[nix-shell] $ patchPhase | [nix-shell] $ patchPhase | ||
Line 241: | Line 289: | ||
=== Packaging out-of-tree kernel modules === | === Packaging out-of-tree kernel modules === | ||
There are a couple of steps that you will most likely need to do a couple of things. Here is an annotated example: | There are a couple of steps that you will most likely need to do a couple of things. Here is an annotated example: | ||
< | <syntaxhighlight lang="nix"> | ||
{ stdenv, lib, fetchFromGitHub, kernel, kmod }: | { stdenv, lib, fetchFromGitHub, kernel, kernelModuleMakeFlags, kmod }: | ||
stdenv.mkDerivation rec { | stdenv.mkDerivation rec { | ||
pname = "v4l2loopback-dc"; | |||
version = "1.6"; | version = "1.6"; | ||
Line 252: | Line 300: | ||
repo = "droidcam"; | repo = "droidcam"; | ||
rev = "v${version}"; | rev = "v${version}"; | ||
hash = "1d9qpnmqa3pfwsrpjnxdz76ipk4w37bbxyrazchh4vslnfc886fx"; | |||
}; | }; | ||
Line 259: | Line 307: | ||
nativeBuildInputs = kernel.moduleBuildDependencies; # 2 | nativeBuildInputs = kernel.moduleBuildDependencies; # 2 | ||
makeFlags = [ | makeFlags = kernelModuleMakeFlags ++ [ | ||
"KERNELRELEASE=${kernel.modDirVersion}" # 3 | "KERNELRELEASE=${kernel.modDirVersion}" # 3 | ||
"KERNEL_DIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build" # 4 | "KERNEL_DIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build" # 4 | ||
Line 265: | Line 313: | ||
]; | ]; | ||
meta = | meta = { | ||
description = "A kernel module to create V4L2 loopback devices"; | description = "A kernel module to create V4L2 loopback devices"; | ||
homepage = "https://github.com/aramg/droidcam"; | homepage = "https://github.com/aramg/droidcam"; | ||
license = licenses.gpl2; | license = lib.licenses.gpl2; | ||
maintainers = [ maintainers.makefu ]; | maintainers = [ lib.maintainers.makefu ]; | ||
platforms = platforms.linux; | platforms = lib.platforms.linux; | ||
}; | }; | ||
} | } | ||
</ | </syntaxhighlight> | ||
1. For kernel modules it is necessary to disable <code>pic</code> in compiler hardenings as the kernel need different compiler flags. | 1. For kernel modules it is necessary to disable <code>pic</code> in compiler hardenings as the kernel need different compiler flags. | ||
Line 288: | Line 336: | ||
=== Developing out-of-tree kernel modules === | === Developing out-of-tree kernel modules === | ||
See also: {{ | See also: {{Nixpkgs Manual|name=Nixpkgs Manual, Developing kernel modules|anchor=#sec-linux-kernel-developing-modules}} | ||
If you work on an out-of-tree kernel module the workflow could look as follow: | If you work on an out-of-tree kernel module the workflow could look as follow: | ||
Line 354: | Line 402: | ||
and the module will be automatically loaded after a reboot. If you want instead to load it at stage 1 (before the root is even mounted), you need to add it to <code>boot.initrd.availableKernelModules</code> and <code>boot.initrd.kernelModules</code>. | and the module will be automatically loaded after a reboot. If you want instead to load it at stage 1 (before the root is even mounted), you need to add it to <code>boot.initrd.availableKernelModules</code> and <code>boot.initrd.kernelModules</code>. | ||
Note that if you don't reboot, you can still load manually the module using <code>modprobe yourmodulename></code>, and to automatically enable a module during configuration switch/reboot, you can put <code>modprobe yourmodulename || true</code> inside the script of a systemctl service (it is for example what does wireguard). | Note that if you don't reboot, you can still load manually the module using <code>modprobe <yourmodulename></code>, and to automatically enable a module during configuration switch/reboot, you can put <code>modprobe yourmodulename || true</code> inside the script of a systemctl service (it is for example what does wireguard). | ||
Finally, if you want to define some options by default (used when you load manually a module using <code>modprobe</code>, or when the system boots), you can specify them in: | Finally, if you want to define some options by default (used when you load manually a module using <code>modprobe</code>, or when the system boots), you can specify them in: | ||
Line 388: | Line 436: | ||
Save the following as <code>shell.nix</code> for your nix-shell: | Save the following as <code>shell.nix</code> for your nix-shell: | ||
< | <syntaxhighlight lang="nix"> | ||
{ pkgs ? import <nixpkgs> {} }: | { pkgs ? import <nixpkgs> {} }: | ||
let | let | ||
Line 397: | Line 445: | ||
# the override is optional if you need for example more build dependencies | # the override is optional if you need for example more build dependencies | ||
nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.gllvm ]; | nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.gllvm ]; | ||
} | }) | ||
</ | </syntaxhighlight> | ||
Then you can run the following commands (in the nix-shell <code>$makeFlags</code> will contain | Then you can run the following commands (in the nix-shell <code>$makeFlags</code> will contain | ||
Line 514: | Line 562: | ||
After packaging the kernel module you can add it to your system just like an out-of-tree kernel module, it will replace the default module provided by the linux package because it has the same name: | After packaging the kernel module you can add it to your system just like an out-of-tree kernel module, it will replace the default module provided by the linux package because it has the same name: | ||
< | <syntaxhighlight lang="nix"> | ||
{pkgs, config, ...}: | {pkgs, config, ...}: | ||
let | let | ||
Line 526: | Line 574: | ||
(amdgpu-kernel-module.overrideAttrs (_: { | (amdgpu-kernel-module.overrideAttrs (_: { | ||
patches = [ ./patches/amdgpu-foo-bar.patch ]; | patches = [ ./patches/amdgpu-foo-bar.patch ]; | ||
}) | })) | ||
]; | ]; | ||
} | } | ||
</ | </syntaxhighlight> | ||
== Sysctls == | |||
Example of configuring kernel sysctls: | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
boot.kernel.sysctl."net.ipv4.tcp_ecn" = 1; | |||
} | |||
</syntaxhighlight> | |||
== Sysfs == | |||
Example of configuring kernel sysfs: | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
boot.kernel.sysfs = { | |||
kernel.mm.transparent_hugepage = { | |||
enabled = "always"; | |||
defrag = "defer"; | |||
shmem_enabled = "within_size"; | |||
}; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
== Troubleshooting == | == Troubleshooting == | ||
=== Build fails === | === Build fails === | ||
==== Too high ram usage ==== | ==== Too high ram usage ==== | ||
turn off | turn off <code>DEBUG_INFO_BTF</code> | ||
== See also == | == See also == |