Linux kernel: Difference between revisions

Sdht0 (talk | contribs)
Copy edit
Jopejoe1 (talk | contribs)
Add sysfs example
 
(30 intermediate revisions by 19 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 109: Line 141:
</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 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.


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
Line 116: Line 148:
     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;
Line 132: Line 164:
{{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";
      };
    };
   });
   });
}
}
Line 150: Line 182:
{{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 xconfig and menuconfig ==
== Embedded Linux Cross-compile ==


This section details the on how to get an environment that can be used to configure and cross-compile the kernel for embedded Linux development. The kernel source won't come from nix unpack phase but rather gotten externally(such as from the chip vendor github). So first clone the kernel source, then use the shell.nix below to set up the dev environment(example below is for aarch64):
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:  


<syntaxHighlight lang=nix>
{{file|shell.nix|nix|3=let
let
   pkgs = import <nixpkgs> { };
   pkgs = import <nixpkgs> { };
in
in
Line 162: Line 193:
   targetPkgs = pkgs: (with pkgs;
   targetPkgs = pkgs: (with pkgs;
     [
     [
       pkgconfig
       pkg-config
       ncurses
       ncurses
       qt5.qtbase
       qt5.qtbase
Line 179: Line 210:
     exec bash
     exec bash
   '';
   '';
}).env
}).env}}
</syntaxHighlight>


Finally, cd to the kernel source dir and 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 246: Line 276:
=== 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 287:
     repo = "droidcam";
     repo = "droidcam";
     rev = "v${version}";
     rev = "v${version}";
     sha256 = "1d9qpnmqa3pfwsrpjnxdz76ipk4w37bbxyrazchh4vslnfc886fx";
     hash = "1d9qpnmqa3pfwsrpjnxdz76ipk4w37bbxyrazchh4vslnfc886fx";
   };
   };


Line 264: Line 294:
   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 300:
   ];
   ];


   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 323:


=== 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 389:
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 423:
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 432:
   # 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 549:
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 561:
     (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 ==