2021-07-03 19:40:22 +08:00
|
|
|
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-kernel-config">
|
|
|
|
|
<title>Linux Kernel</title>
|
|
|
|
|
<para>
|
|
|
|
|
You can override the Linux kernel and associated packages using the
|
|
|
|
|
option <literal>boot.kernelPackages</literal>. For instance, this
|
|
|
|
|
selects the Linux 3.10 kernel:
|
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-09-07 15:30:10 +08:00
|
|
|
|
boot.kernelPackages = pkgs.linuxKernel.packages.linux_3_10;
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
Note that this not only replaces the kernel, but also packages that
|
|
|
|
|
are specific to the kernel version, such as the NVIDIA video
|
|
|
|
|
drivers. This ensures that driver packages are consistent with the
|
|
|
|
|
kernel.
|
|
|
|
|
</para>
|
2021-09-07 15:30:10 +08:00
|
|
|
|
<para>
|
|
|
|
|
While <literal>pkgs.linuxKernel.packages</literal> contains all
|
|
|
|
|
available kernel packages, you may want to use one of the
|
|
|
|
|
unversioned <literal>pkgs.linuxPackages_*</literal> aliases such as
|
|
|
|
|
<literal>pkgs.linuxPackages_latest</literal>, that are kept up to
|
|
|
|
|
date with new versions.
|
|
|
|
|
</para>
|
2022-12-06 13:47:40 +01:00
|
|
|
|
<para>
|
|
|
|
|
Please note that the current convention in NixOS is to only keep
|
|
|
|
|
actively maintained kernel versions on both unstable and the
|
|
|
|
|
currently supported stable release(s) of NixOS. This means that a
|
|
|
|
|
non-longterm kernel will be removed after it’s abandoned by the
|
|
|
|
|
kernel developers, even on stable NixOS versions. If you pin your
|
|
|
|
|
kernel onto a non-longterm version, expect your evaluation to fail
|
|
|
|
|
as soon as the version is out of maintenance.
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
Longterm versions of kernels will be removed before the next stable
|
|
|
|
|
NixOS that will exceed the maintenance period of the kernel version.
|
|
|
|
|
</para>
|
2021-07-03 19:40:22 +08:00
|
|
|
|
<para>
|
|
|
|
|
The default Linux kernel configuration should be fine for most
|
|
|
|
|
users. You can see the configuration of your current kernel with the
|
|
|
|
|
following command:
|
|
|
|
|
</para>
|
|
|
|
|
<programlisting>
|
|
|
|
|
zcat /proc/config.gz
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
If you want to change the kernel configuration, you can use the
|
|
|
|
|
<literal>packageOverrides</literal> feature (see
|
|
|
|
|
<xref linkend="sec-customising-packages" />). For instance, to
|
|
|
|
|
enable support for the kernel debugger KGDB:
|
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-09-07 15:30:10 +08:00
|
|
|
|
nixpkgs.config.packageOverrides = pkgs: pkgs.lib.recursiveUpdate pkgs {
|
|
|
|
|
linuxKernel.kernels.linux_5_10 = pkgs.linuxKernel.kernels.linux_5_10.override {
|
|
|
|
|
extraConfig = ''
|
|
|
|
|
KGDB y
|
|
|
|
|
'';
|
2021-07-03 19:40:22 +08:00
|
|
|
|
};
|
2021-09-07 15:30:10 +08:00
|
|
|
|
};
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
<literal>extraConfig</literal> takes a list of Linux kernel
|
|
|
|
|
configuration options, one per line. The name of the option should
|
|
|
|
|
not include the prefix <literal>CONFIG_</literal>. The option value
|
|
|
|
|
is typically <literal>y</literal>, <literal>n</literal> or
|
|
|
|
|
<literal>m</literal> (to build something as a kernel module).
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
Kernel modules for hardware devices are generally loaded
|
|
|
|
|
automatically by <literal>udev</literal>. You can force a module to
|
2021-07-04 08:24:44 +08:00
|
|
|
|
be loaded via <xref linkend="opt-boot.kernelModules" />, e.g.
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-07-03 19:40:22 +08:00
|
|
|
|
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
If the module is required early during the boot (e.g. to mount the
|
|
|
|
|
root file system), you can use
|
2021-07-04 08:24:44 +08:00
|
|
|
|
<xref linkend="opt-boot.initrd.kernelModules" />:
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-07-03 19:40:22 +08:00
|
|
|
|
boot.initrd.kernelModules = [ "cifs" ];
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
This causes the specified modules and their dependencies to be added
|
|
|
|
|
to the initial ramdisk.
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
Kernel runtime parameters can be set through
|
2021-07-04 08:24:44 +08:00
|
|
|
|
<xref linkend="opt-boot.kernel.sysctl" />, e.g.
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-07-03 19:40:22 +08:00
|
|
|
|
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120;
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
sets the kernel’s TCP keepalive time to 120 seconds. To see the
|
|
|
|
|
available parameters, run <literal>sysctl -a</literal>.
|
|
|
|
|
</para>
|
|
|
|
|
<section xml:id="sec-linux-config-customizing">
|
2022-12-20 16:49:27 +01:00
|
|
|
|
<title>Building a custom kernel</title>
|
2021-07-03 19:40:22 +08:00
|
|
|
|
<para>
|
2022-12-20 16:49:27 +01:00
|
|
|
|
You can customize the default kernel configuration by overriding
|
|
|
|
|
the arguments for your kernel package:
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2022-12-20 16:49:27 +01:00
|
|
|
|
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;
|
|
|
|
|
};
|
|
|
|
|
}
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
2022-12-20 16:49:27 +01:00
|
|
|
|
See <literal>pkgs/os-specific/linux/kernel/generic.nix</literal>
|
|
|
|
|
for details on how these arguments affect the generated
|
|
|
|
|
configuration. You can also build a custom version of Linux by
|
|
|
|
|
calling <literal>pkgs.buildLinux</literal> directly, which
|
|
|
|
|
requires the <literal>src</literal> and <literal>version</literal>
|
|
|
|
|
arguments to be specified.
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</para>
|
2022-12-20 16:49:27 +01:00
|
|
|
|
<para>
|
|
|
|
|
To use your custom kernel package in your NixOS configuration, set
|
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2022-12-20 16:49:27 +01:00
|
|
|
|
boot.kernelPackages = pkgs.linuxPackagesFor yourCustomKernel;
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
2022-12-20 16:49:27 +01:00
|
|
|
|
Note that this method will use the common configuration defined in
|
|
|
|
|
<literal>pkgs/os-specific/linux/kernel/common-config.nix</literal>,
|
|
|
|
|
which is suitable for a NixOS system.
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
If you already have a generated configuration file, you can build
|
|
|
|
|
a kernel that uses it with
|
|
|
|
|
<literal>pkgs.linuxManualConfig</literal>:
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2022-12-20 16:49:27 +01:00
|
|
|
|
let
|
|
|
|
|
baseKernel = pkgs.linux_latest;
|
|
|
|
|
in pkgs.linuxManualConfig {
|
|
|
|
|
inherit (baseKernel) src modDirVersion;
|
|
|
|
|
version = "${baseKernel.version}-custom";
|
|
|
|
|
configfile = ./my_kernel_config;
|
|
|
|
|
allowImportFromDerivation = true;
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
|
|
|
|
<note>
|
|
|
|
|
<para>
|
|
|
|
|
The build will fail if <literal>modDirVersion</literal> does not
|
|
|
|
|
match the source’s <literal>kernel.release</literal> file, so
|
|
|
|
|
<literal>modDirVersion</literal> should remain tied to
|
|
|
|
|
<literal>src</literal>.
|
|
|
|
|
</para>
|
|
|
|
|
</note>
|
|
|
|
|
<para>
|
|
|
|
|
To edit the <literal>.config</literal> file for Linux X.Y, proceed
|
|
|
|
|
as follows:
|
|
|
|
|
</para>
|
|
|
|
|
<programlisting>
|
|
|
|
|
$ nix-shell '<nixpkgs>' -A linuxKernel.kernels.linux_X_Y.configEnv
|
|
|
|
|
$ unpackPhase
|
|
|
|
|
$ cd linux-*
|
|
|
|
|
$ make nconfig
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</programlisting>
|
|
|
|
|
</section>
|
|
|
|
|
<section xml:id="sec-linux-config-developing-modules">
|
|
|
|
|
<title>Developing kernel modules</title>
|
|
|
|
|
<para>
|
2022-12-20 16:49:27 +01:00
|
|
|
|
When developing kernel modules it’s often convenient to run
|
2021-07-03 19:40:22 +08:00
|
|
|
|
edit-compile-run loop as quickly as possible. See below snippet as
|
|
|
|
|
an example of developing <literal>mellanox</literal> drivers.
|
|
|
|
|
</para>
|
|
|
|
|
<programlisting>
|
|
|
|
|
$ 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
|
|
|
|
|
</programlisting>
|
|
|
|
|
</section>
|
2022-12-06 13:47:40 +01:00
|
|
|
|
<section xml:id="sec-linux-zfs">
|
|
|
|
|
<title>ZFS</title>
|
|
|
|
|
<para>
|
|
|
|
|
It’s a common issue that the latest stable version of ZFS doesn’t
|
2022-12-09 11:34:05 +01:00
|
|
|
|
support the latest available Linux kernel. It is recommended to
|
|
|
|
|
use the latest available LTS that’s compatible with ZFS. Usually
|
|
|
|
|
this is the default kernel provided by nixpkgs (i.e.
|
|
|
|
|
<literal>pkgs.linuxPackages</literal>).
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
Alternatively, it’s possible to pin the system to the latest
|
|
|
|
|
available kernel version <emphasis>that is supported by
|
|
|
|
|
ZFS</emphasis> like this:
|
2022-12-06 13:47:40 +01:00
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2022-12-06 13:47:40 +01:00
|
|
|
|
{
|
|
|
|
|
boot.kernelPackages = pkgs.zfs.latestCompatibleLinuxPackages;
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
Please note that the version this attribute points to isn’t
|
|
|
|
|
monotonic because the latest kernel version only refers to kernel
|
|
|
|
|
versions supported by the Linux developers. In other words, the
|
|
|
|
|
latest kernel version that ZFS is compatible with may decrease
|
|
|
|
|
over time.
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
An example: the latest version ZFS is compatible with is 5.19
|
|
|
|
|
which is a non-longterm version. When 5.19 is out of maintenance,
|
|
|
|
|
the latest supported kernel version is 5.15 because it’s longterm
|
|
|
|
|
and the versions 5.16, 5.17 and 5.18 are already out of
|
|
|
|
|
maintenance because they’re non-longterm.
|
|
|
|
|
</para>
|
|
|
|
|
</section>
|
2021-07-03 19:40:22 +08:00
|
|
|
|
</chapter>
|