Linux kernel: Difference between revisions

Sdht0 (talk | contribs)
Axka (talk | contribs)
extraConfig in boot.kernelPatches and pkgs.buildLinux is deprecated
 
(32 intermediate revisions by 21 users not shown)
Line 28: Line 28:


nix-repl> pkgs.linuxPackages
nix-repl> pkgs.linuxPackages
pkgs.linuxPackages                          pkgs.linuxPackages_latest
pkgs.linuxPackages                          pkgs.linuxPackages_custom
pkgs.linuxPackages-libre                    pkgs.linuxPackages_latest-libre
pkgs.linuxPackages-libre                    pkgs.linuxPackages_custom_tinyconfig_kernel
pkgs.linuxPackages-rt                        pkgs.linuxPackages_latest_hardened
pkgs.linuxPackages-rt                        pkgs.linuxPackages_hardened
pkgs.linuxPackages-rt_5_4                    pkgs.linuxPackages_latest_xen_dom0
pkgs.linuxPackages-rt_latest                pkgs.linuxPackages_latest
pkgs.linuxPackages-rt_5_6                    pkgs.linuxPackages_latest_xen_dom0_hardened
pkgs.linuxPackagesFor                        pkgs.linuxPackages_latest-libre
pkgs.linuxPackages-rt_latest                pkgs.linuxPackages_mptcp
pkgs.linuxPackages_4_14                      pkgs.linuxPackages_latest_hardened
pkgs.linuxPackagesFor                        pkgs.linuxPackages_rpi0
pkgs.linuxPackages_4_19                      pkgs.linuxPackages_latest_xen_dom0
pkgs.linuxPackages_4_14                     pkgs.linuxPackages_rpi1
pkgs.linuxPackages_4_19_hardened            pkgs.linuxPackages_latest_xen_dom0_hardened
pkgs.linuxPackages_4_19                      pkgs.linuxPackages_rpi2
pkgs.linuxPackages_4_9                      pkgs.linuxPackages_lqx
pkgs.linuxPackages_4_4                      pkgs.linuxPackages_rpi3
pkgs.linuxPackages_5_10                      pkgs.linuxPackages_rpi0
pkgs.linuxPackages_4_9                      pkgs.linuxPackages_rpi4
pkgs.linuxPackages_5_10_hardened            pkgs.linuxPackages_rpi02w
pkgs.linuxPackages_5_4                      pkgs.linuxPackages_testing
pkgs.linuxPackages_5_15                     pkgs.linuxPackages_rpi1
pkgs.linuxPackages_5_8                       pkgs.linuxPackages_testing_bcachefs
pkgs.linuxPackages_5_15_hardened            pkgs.linuxPackages_rpi2
pkgs.linuxPackages_5_9                       pkgs.linuxPackages_testing_hardened
pkgs.linuxPackages_5_18                      pkgs.linuxPackages_rpi3
pkgs.linuxPackages_custom                    pkgs.linuxPackages_xen_dom0
pkgs.linuxPackages_5_19                      pkgs.linuxPackages_rpi4
pkgs.linuxPackages_custom_tinyconfig_kernel  pkgs.linuxPackages_xen_dom0_hardened
pkgs.linuxPackages_5_4                      pkgs.linuxPackages_rt_5_10
pkgs.linuxPackages_hardened                  pkgs.linuxPackages_zen
pkgs.linuxPackages_5_4_hardened              pkgs.linuxPackages_rt_5_15
pkgs.linuxPackages_hardkernel_4_14
pkgs.linuxPackages_6_0                      pkgs.linuxPackages_rt_5_4
pkgs.linuxPackages_hardkernel_latest
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 86: Line 95:
}
}
</nowiki>}}
</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 ===
Line 95: Line 127:
<syntaxhighlight lang=nix>
<syntaxhighlight lang=nix>
{
{
      boot.kernelPatches = [ {
  boot.kernelPatches = [ {
        name = "crashdump-config";
    name = "crashdump-config";
        patch = null;
    patch = null;
        extraConfig = ''
    structuredExtraConfig = with lib.kernel; {
                CRASH_DUMP y
      CRASH_DUMP = yes;
                DEBUG_INFO y
      DEBUG_INFO = yes;
                PROC_VMCORE y
      PROC_VMCORE = yes;
                LOCKUP_DETECTOR y
      LOCKUP_DETECTOR = yes;
                HARDLOCKUP_DETECTOR y
      HARDLOCKUP_DETECTOR = yes;
              '';
    };
        } ];
  } ];
}
}
</syntaxhighlight>
</syntaxhighlight>


Another way is to create a 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. You may also want to set {{ic|ignoreConfigErrors}} to avoid {{ic|error: unused option}} during builds.
Another way is to create an overlay to configure {{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>.


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
Line 116: Line 149:
     overlays = [
     overlays = [
       (self: super: {
       (self: super: {
         linuxZenWMuQSS = pkgs.linuxPackagesFor (pkgs.linux_zen.kernel.override {
         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 127: Line 160:
}
}
</nowiki>}}
</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 ===
Line 132: Line 167:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{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/v4.x/linux-${version}.tar.xz";
             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>}}
</nowiki>}}
Note that pinning the kernel version will likely require manual recompilation, which may be slow on older hardware. See [https://discourse.nixos.org/t/pin-kernel-version/50630/3 this thread] for a related discussion.


=== Debugging a failed configuration  ===
=== Debugging a failed configuration  ===
Line 154: Line 191:
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:  
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|<nowiki>
{{file|shell.nix|nix|3=let
let
   pkgs = import <nixpkgs> { };
   pkgs = import <nixpkgs> { };
in
in
Line 162: Line 198:
   targetPkgs = pkgs: (with pkgs;
   targetPkgs = pkgs: (with pkgs;
     [
     [
       pkgconfig
       pkg-config
       ncurses
       ncurses
       qt5.qtbase
       qt5.qtbase
Line 179: Line 215:
     exec bash
     exec bash
   '';
   '';
}).env
}).env}}
</nowiki>}}


Clone the kernel sources, enter the environment using {{ic|nix-shell}}, and then do development normally.
Clone the kernel sources, enter the environment using {{ic|nix-shell}}, and then do development normally.


== make menuconfig ==
== make menuconfig ==
It is (currently) not possible to run <code>make menuconfig</code> in the checked out linux kernel sources. 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>.
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>.


This nix-shell hack adds ncurses as a build dependency to the kernel:
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 -E 'with import <nixpkgs> {}; linux.overrideAttrs (o: {nativeBuildInputs=o.nativeBuildInputs ++ [ pkg-config ncurses ];})'
$ nix-shell '<nixpkgs>' -A linuxPackages.kernel.configEnv
[nix-shell] $ unpackPhase && cd linux-*
[nix-shell] $ unpackPhase && cd linux-*
[nix-shell] $ patchPhase
[nix-shell] $ patchPhase
Line 231: Line 266:
           kernelPatches = [];
           kernelPatches = [];


           extraConfig = ''
           structuredExtraConfig = with lib.kernel; {
             INTEL_SGX y
             INTEL_SGX = yes;
           '';
           };


           extraMeta.branch = "5.4";
           extraMeta.branch = "5.4";
Line 246: Line 281:
=== 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>
<syntaxhighlight lang="nix">
{ stdenv, lib, fetchFromGitHub, kernel, kmod }:
{ stdenv, lib, fetchFromGitHub, kernel, kernelModuleMakeFlags, kmod }:


stdenv.mkDerivation rec {
stdenv.mkDerivation rec {
   name = "v4l2loopback-dc-${version}-${kernel.version}";
   pname = "v4l2loopback-dc";
   version = "1.6";
   version = "1.6";


Line 257: Line 292:
     repo = "droidcam";
     repo = "droidcam";
     rev = "v${version}";
     rev = "v${version}";
     sha256 = "1d9qpnmqa3pfwsrpjnxdz76ipk4w37bbxyrazchh4vslnfc886fx";
     hash = "1d9qpnmqa3pfwsrpjnxdz76ipk4w37bbxyrazchh4vslnfc886fx";
   };
   };


Line 264: Line 299:
   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 270: Line 305:
   ];
   ];


   meta = with lib; {
   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>
</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 293: Line 328:


=== Developing out-of-tree kernel modules ===
=== Developing out-of-tree kernel modules ===
See also:  {{manual:nixos|sec=#sec-linux-config-developing-modules|chapter=12.2. Developing kernel modules}}
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 359: Line 394:
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 393: Line 428:
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>
<syntaxhighlight lang="nix">
{ pkgs ? import <nixpkgs> {} }:
{ pkgs ? import <nixpkgs> {} }:
let
let
Line 402: Line 437:
   # 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>
</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 519: Line 554:
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>
<syntaxhighlight lang="nix">
{pkgs, config, ...}:
{pkgs, config, ...}:
let
let
Line 531: Line 566:
     (amdgpu-kernel-module.overrideAttrs (_: {
     (amdgpu-kernel-module.overrideAttrs (_: {
       patches = [ ./patches/amdgpu-foo-bar.patch ];
       patches = [ ./patches/amdgpu-foo-bar.patch ];
     })
     }))
   ];
   ];
}
}
</syntaxHighlight>
</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 `DEBUG_INFO_BTF`
turn off <code>DEBUG_INFO_BTF</code>


== See also ==
== See also ==