about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDS <commits@sidhion.com>2023-10-23 19:37:04 -0700
committerDS <commits@sidhion.com>2023-11-23 08:50:16 -0800
commit1d7ee9ff0901b780f0d9398735307933ac518d77 (patch)
tree510b3ac91e7d7d6ca9698424bd085fe8f5543b08
parenta68bc4feaf4bbf4b626226ff8f0f8110588d4ebc (diff)
downloadnixlib-1d7ee9ff0901b780f0d9398735307933ac518d77.tar
nixlib-1d7ee9ff0901b780f0d9398735307933ac518d77.tar.gz
nixlib-1d7ee9ff0901b780f0d9398735307933ac518d77.tar.bz2
nixlib-1d7ee9ff0901b780f0d9398735307933ac518d77.tar.lz
nixlib-1d7ee9ff0901b780f0d9398735307933ac518d77.tar.xz
nixlib-1d7ee9ff0901b780f0d9398735307933ac518d77.tar.zst
nixlib-1d7ee9ff0901b780f0d9398735307933ac518d77.zip
doc: consolidate info on manual linux kernel configs
The Nixpkgs documentation on the linux kernel builders focused on
using and extending kernels that were already packaged, but never
mentioned that it's possible to also build a kernel almost "from
scratch".
The NixOS documentation went a bit deeper on manual linux kernel
configs, but that information wasn't particularly NixOS-specific.

This commit consolidates the information related to building the
kernel on Nixpkgs's documentation, while keeping any additional
NixOS-specific information on NixOS's documentation.

An additional README.md was created for contributor-facing
documentation.
-rw-r--r--doc/packages/linux.section.md122
-rw-r--r--nixos/doc/manual/configuration/linux-kernel.chapter.md66
-rw-r--r--pkgs/os-specific/linux/kernel/README.md33
3 files changed, 140 insertions, 81 deletions
diff --git a/doc/packages/linux.section.md b/doc/packages/linux.section.md
index b64da85791a0..0edf40043361 100644
--- a/doc/packages/linux.section.md
+++ b/doc/packages/linux.section.md
@@ -2,9 +2,21 @@
 
 The Nix expressions to build the Linux kernel are in [`pkgs/os-specific/linux/kernel`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/os-specific/linux/kernel).
 
-The function that builds the kernel has an argument `kernelPatches` which should be a list of `{name, patch, extraConfig}` attribute sets, where `name` is the name of the patch (which is included in the kernel’s `meta.description` attribute), `patch` is the patch itself (possibly compressed), and `extraConfig` (optional) is a string specifying extra options to be concatenated to the kernel configuration file (`.config`).
+The function [`pkgs.buildLinux`](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/generic.nix) builds a kernel with [common configuration values](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/common-config.nix).
+This is the preferred option unless you have a very specific use case.
+Most kernels packaged in Nixpkgs are built that way, and it will also generate kernels suitable for NixOS.
+[`pkgs.linuxManualConfig`](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/manual-config.nix) requires a complete configuration to be passed.
+It has fewer additional features than `pkgs.buildLinux`, which provides common configuration values and exposes the `features` attribute, as explained below.
 
-The kernel derivation exports an attribute `features` specifying whether optional functionality is or isn’t enabled. This is used in NixOS to implement kernel-specific behaviour. For instance, if the kernel has the `iwlwifi` feature (i.e., has built-in support for Intel wireless chipsets), then NixOS doesn’t have to build the external `iwlwifi` package:
+Both functions have an argument `kernelPatches` which should be a list of `{name, patch, extraConfig}` attribute sets, where `name` is the name of the patch (which is included in the kernel’s `meta.description` attribute), `patch` is the patch itself (possibly compressed), and `extraConfig` (optional) is a string specifying extra options to be concatenated to the kernel configuration file (`.config`).
+
+The kernel derivation created with `pkgs.buildLinux` exports an attribute `features` specifying whether optional functionality is or isn’t enabled. This is used in NixOS to implement kernel-specific behaviour.
+
+:::{.example #ex-skip-package-from-kernel-feature}
+
+# Skipping an external package because of a kernel feature
+
+For instance, if the kernel has the `iwlwifi` feature (i.e., has built-in support for Intel wireless chipsets), then NixOS doesn’t have to build the external `iwlwifi` package:
 
 ```nix
 modulesTree = [kernel]
@@ -12,30 +24,104 @@ modulesTree = [kernel]
   ++ ...;
 ```
 
-How to add a new (major) version of the Linux kernel to Nixpkgs:
+:::
+
+If you are using a kernel packaged in Nixpkgs, you can customize it by overriding its arguments. For details on how each argument affects the generated kernel, refer to [the `pkgs.buildLinux` source code](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/generic.nix).
+
+:::{.example #ex-overriding-kernel-derivation}
+
+# Overriding the kernel derivation
+
+Assuming you are using the kernel from `pkgs.linux_latest`:
+
+```nix
+pkgs.linux_latest.override {
+  ignoreConfigErrors = true;
+  autoModules = false;
+  kernelPreferBuiltin = true;
+  extraStructuredConfig = with lib.kernel; {
+    DEBUG_KERNEL = yes;
+    FRAME_POINTER = yes;
+    KGDB = yes;
+    KGDB_SERIAL_CONSOLE = yes;
+    DEBUG_INFO = yes;
+  };
+}
+```
+
+:::
 
-1.  Copy the old Nix expression (e.g., `linux-2.6.21.nix`) to the new one (e.g., `linux-2.6.22.nix`) and update it.
+## Manual kernel configuration {#sec-manual-kernel-configuration}
 
-2.  Add the new kernel to the `kernels` attribute set in `linux-kernels.nix` (e.g., create an attribute `kernel_2_6_22`).
+Sometimes it may not be desirable to use kernels built with `pkgs.buildLinux`, especially if most of the common configuration has to be altered or disabled to achieve a kernel as expected by the target use case.
+An example of this is building a kernel for use in a VM or micro VM. You can use `pkgs.linuxManualConfig` in these cases. It requires the `src`, `version`, and `configfile` attributes to be specified.
 
-3.  Now we’re going to update the kernel configuration. First unpack the kernel. Then for each supported platform (`i686`, `x86_64`, `uml`) do the following:
+:::{.example #ex-using-linux-manual-config}
 
-    1.  Make a copy from the old config (e.g., `config-2.6.21-i686-smp`) to the new one (e.g., `config-2.6.22-i686-smp`).
+# Using `pkgs.linuxManualConfig` with a specific source, version, and config file
 
-    2.  Copy the config file for this platform (e.g., `config-2.6.22-i686-smp`) to `.config` in the kernel source tree.
+```nix
+{ pkgs, ... }: {
+  version = "6.1.55";
+  src = pkgs.fetchurl {
+    url = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${version}.tar.xz";
+    hash = "sha256:1h0mzx52q9pvdv7rhnvb8g68i7bnlc9rf8gy9qn4alsxq4g28zm8";
+  };
+  configfile = ./path_to_config_file;
+  linux = pkgs.linuxManualConfig {
+    inherit version src configfile;
+    allowImportFromDerivation = true;
+  };
+}
+```
+
+If necessary, the version string can be slightly modified to explicitly mark it as a custom version. If you do so, ensure the `modDirVersion` attribute matches the source's version, otherwise the build will fail.
+
+```nix
+{ pkgs, ... }: {
+  version = "6.1.55-custom";
+  modDirVersion = "6.1.55";
+  src = pkgs.fetchurl {
+    url = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${modDirVersion}.tar.xz";
+    hash = "sha256:1h0mzx52q9pvdv7rhnvb8g68i7bnlc9rf8gy9qn4alsxq4g28zm8";
+  };
+  configfile = ./path_to_config_file;
+  linux = pkgs.linuxManualConfig {
+    inherit version modDirVersion src configfile;
+    allowImportFromDerivation = true;
+  };
+}
+```
 
-    3.  Run `make oldconfig ARCH={i386,x86_64,um}` and answer all questions. (For the uml configuration, also add `SHELL=bash`.) Make sure to keep the configuration consistent between platforms (i.e., don’t enable some feature on `i686` and disable it on `x86_64`).
+:::
 
-    4.  If needed, you can also run `make menuconfig`:
+Additional attributes can be used with `linuxManualConfig` for further customisation. You're encouraged to read [the `pkgs.linuxManualConfig` source code](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/manual-config.nix) to understand how to use them.
 
-        ```ShellSession
-        $ nix-env -f "<nixpkgs>" -iA ncurses
-        $ export NIX_CFLAGS_LINK=-lncurses
-        $ make menuconfig ARCH=arch
-        ```
+To edit the `.config` file for Linux X.Y from within Nix, proceed as follows:
 
-    5.  Copy `.config` over the new config file (e.g., `config-2.6.22-i686-smp`).
+```ShellSession
+$ nix-shell '<nixpkgs>' -A linuxKernel.kernels.linux_X_Y.configEnv
+$ unpackPhase
+$ cd linux-*
+$ make nconfig
+```
+
+## Developing kernel modules {#sec-linux-kernel-developing-modules}
+
+When developing kernel modules it's often convenient to run the edit-compile-run loop as quickly as possible.
+See the snippet below as an example.
 
-4.  Test building the kernel: `nix-build -A linuxKernel.kernels.kernel_2_6_22`. If it compiles, ship it! For extra credit, try booting NixOS with it.
+:::{.example #ex-edit-compile-run-kernel-modules}
+
+# Edit-compile-run loop when developing `mellanox` drivers
+
+```ShellSession
+$ nix-build '<nixpkgs>' -A linuxPackages.kernel.dev
+$ nix-shell '<nixpkgs>' -A linuxPackages.kernel
+$ unpackPhase
+$ cd linux-*
+$ make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules
+# insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko
+```
 
-5.  It may be that the new kernel requires updating the external kernel modules and kernel-dependent packages listed in the `linuxPackagesFor` function in `linux-kernels.nix` (such as the NVIDIA drivers, AUFS, etc.). If the updated packages aren’t backwards compatible with older kernels, you may need to keep the older versions around.
+:::
diff --git a/nixos/doc/manual/configuration/linux-kernel.chapter.md b/nixos/doc/manual/configuration/linux-kernel.chapter.md
index f5bce99dd1bb..9d1b2bc2f9b8 100644
--- a/nixos/doc/manual/configuration/linux-kernel.chapter.md
+++ b/nixos/doc/manual/configuration/linux-kernel.chapter.md
@@ -84,26 +84,7 @@ available parameters, run `sysctl -a`.
 
 ## Building a custom kernel {#sec-linux-config-customizing}
 
-You can customize the default kernel configuration by overriding the arguments for your kernel package:
-
-```nix
-pkgs.linux_latest.override {
-  ignoreConfigErrors = true;
-  autoModules = false;
-  kernelPreferBuiltin = true;
-  extraStructuredConfig = with lib.kernel; {
-    DEBUG_KERNEL = yes;
-    FRAME_POINTER = yes;
-    KGDB = yes;
-    KGDB_SERIAL_CONSOLE = yes;
-    DEBUG_INFO = yes;
-  };
-}
-```
-
-See `pkgs/os-specific/linux/kernel/generic.nix` for details on how these arguments
-affect the generated configuration. You can also build a custom version of Linux by calling
-`pkgs.buildLinux` directly, which requires the `src` and `version` arguments to be specified.
+Please refer to the Nixpkgs manual for the various ways of [building a custom kernel](https://nixos.org/nixpkgs/manual#sec-linux-kernel).
 
 To use your custom kernel package in your NixOS configuration, set
 
@@ -111,50 +92,9 @@ To use your custom kernel package in your NixOS configuration, set
 boot.kernelPackages = pkgs.linuxPackagesFor yourCustomKernel;
 ```
 
-Note that this method will use the common configuration defined in `pkgs/os-specific/linux/kernel/common-config.nix`,
-which is suitable for a NixOS system.
-
-If you already have a generated configuration file, you can build a kernel that uses it with `pkgs.linuxManualConfig`:
-
-```nix
-let
-  baseKernel = pkgs.linux_latest;
-in pkgs.linuxManualConfig {
-  inherit (baseKernel) src modDirVersion;
-  version = "${baseKernel.version}-custom";
-  configfile = ./my_kernel_config;
-  allowImportFromDerivation = true;
-}
-```
-
-::: {.note}
-The build will fail if `modDirVersion` does not match the source's `kernel.release` file,
-so `modDirVersion` should remain tied to `src`.
-:::
-
-To edit the `.config` file for Linux X.Y, proceed as follows:
-
-```ShellSession
-$ nix-shell '<nixpkgs>' -A linuxKernel.kernels.linux_X_Y.configEnv
-$ unpackPhase
-$ cd linux-*
-$ make nconfig
-```
-
 ## Developing kernel modules {#sec-linux-config-developing-modules}
 
-When developing kernel modules it's often convenient to run
-edit-compile-run loop as quickly as possible. See below snippet as an
-example of developing `mellanox` drivers.
-
-```ShellSession
-$ nix-build '<nixpkgs>' -A linuxPackages.kernel.dev
-$ nix-shell '<nixpkgs>' -A linuxPackages.kernel
-$ unpackPhase
-$ cd linux-*
-$ make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules
-# insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko
-```
+This section was moved to the [Nixpkgs manual](https://nixos.org/nixpkgs/manual#sec-linux-kernel-developing-modules).
 
 ## ZFS {#sec-linux-zfs}
 
@@ -163,7 +103,7 @@ available Linux kernel. It is recommended to use the latest available LTS that's
 with ZFS. Usually this is the default kernel provided by nixpkgs (i.e. `pkgs.linuxPackages`).
 
 Alternatively, it's possible to pin the system to the latest available kernel
-version *that is supported by ZFS* like this:
+version _that is supported by ZFS_ like this:
 
 ```nix
 {
diff --git a/pkgs/os-specific/linux/kernel/README.md b/pkgs/os-specific/linux/kernel/README.md
new file mode 100644
index 000000000000..92d5308e1c05
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/README.md
@@ -0,0 +1,33 @@
+# How to add a new (major) version of the Linux kernel to Nixpkgs:
+
+1.  Copy the old Nix expression (e.g., `linux-2.6.21.nix`) to the new one (e.g., `linux-2.6.22.nix`) and update it.
+
+2.  Add the new kernel to the `kernels` attribute set in [`linux-kernels.nix`](./linux-kernels.nix) (e.g., create an attribute `kernel_2_6_22`).
+
+3.  Update the kernel configuration. First unpack the kernel. Then for each supported platform (`i686`, `x86_64`, `uml`) do the following:
+
+    1.  Make a copy from the old config (e.g., `config-2.6.21-i686-smp`) to the new one (e.g., `config-2.6.22-i686-smp`).
+
+    2.  Copy the config file for this platform (e.g., `config-2.6.22-i686-smp`) to `.config` in the kernel source tree.
+
+    3.  Run `make oldconfig ARCH={i386,x86_64,um}` and answer all questions. (For the uml configuration, also add `SHELL=bash`.) Make sure to keep the configuration consistent between platforms (i.e., don’t enable some feature on `i686` and disable it on `x86_64`).
+
+    4.  If needed, you can also run `make menuconfig`:
+
+        ```ShellSession
+        $ nix-env -f "<nixpkgs>" -iA ncurses
+        $ export NIX_CFLAGS_LINK=-lncurses
+        $ make menuconfig ARCH=arch
+        ```
+
+    5.  Copy `.config` over the new config file (e.g., `config-2.6.22-i686-smp`).
+
+4.  Test building the kernel:
+
+```ShellSession
+nix-build -A linuxKernel.kernels.kernel_2_6_22
+```
+
+If it compiles, ship it! For extra credit, try booting NixOS with it.
+
+5.  It may be that the new kernel requires updating the external kernel modules and kernel-dependent packages listed in the `linuxPackagesFor` function in `linux-kernels.nix` (such as the NVIDIA drivers, AUFS, etc.). If the updated packages aren’t backwards compatible with older kernels, you may need to keep the older versions around.