Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

linux: simplify and document kernel customisation #207095

Merged
merged 6 commits into from
Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/tests/misc.nix
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,21 @@ runTests {
expected = [ "1" "2" "3" ];
};

testPadVersionLess = {
expr = versions.pad 3 "1.2";
expected = "1.2.0";
};

testPadVersionLessExtra = {
expr = versions.pad 3 "1.3-rc1";
expected = "1.3.0-rc1";
};

testPadVersionMore = {
expr = versions.pad 3 "1.2.3.4";
expected = "1.2.3";
};

testIsStorePath = {
expr =
let goodPath =
Expand Down
15 changes: 15 additions & 0 deletions lib/versions.nix
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,19 @@ rec {
builtins.concatStringsSep "."
(lib.take 2 (splitVersion v));

/* Pad a version string with zeros to match the given number of components.
Example:
pad 3 "1.2"
=> "1.2.0"
pad 3 "1.3-rc1"
=> "1.3.0-rc1"
pad 3 "1.2.3.4"
=> "1.2.3"
*/
pad = n: version: let
numericVersion = lib.head (lib.splitString "-" version);
versionSuffix = lib.removePrefix numericVersion version;
in lib.concatStringsSep "." (lib.take n (lib.splitVersion numericVersion ++ lib.genList (_: "0") n)) + versionSuffix;

}
83 changes: 45 additions & 38 deletions nixos/doc/manual/configuration/linux-kernel.chapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,61 +82,68 @@ boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120;
sets the kernel's TCP keepalive time to 120 seconds. To see the
available parameters, run `sysctl -a`.

## Customize your kernel {#sec-linux-config-customizing}
## Building a custom kernel {#sec-linux-config-customizing}

The first step before compiling the kernel is to generate an appropriate
`.config` configuration. Either you pass your own config via the
`configfile` setting of `linuxKernel.manualConfig`:
You can customize the default kernel configuration by overriding the arguments for your kernel package:

```nix
custom-kernel = let base_kernel = linuxKernel.kernels.linux_4_9;
in super.linuxKernel.manualConfig {
inherit (super) stdenv hostPlatform;
inherit (base_kernel) src;
version = "${base_kernel.version}-custom";
configfile = /home/me/my_kernel_config;
allowImportFromDerivation = true;
};
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;
};
}
```

You can edit the config with this snippet (by default `make
menuconfig` won\'t work out of the box on nixos):
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.

```ShellSession
nix-shell -E 'with import <nixpkgs> {}; kernelToOverride.overrideAttrs (o: {nativeBuildInputs=o.nativeBuildInputs ++ [ pkg-config ncurses ];})'
To use your custom kernel package in your NixOS configuration, set

```nix
boot.kernelPackages = pkgs.linuxPackagesFor yourCustomKernel;
```

or you can let nixpkgs generate the configuration. Nixpkgs generates it
via answering the interactive kernel utility `make config`. The answers
depend on parameters passed to
`pkgs/os-specific/linux/kernel/generic.nix` (which you can influence by
overriding `extraConfig, autoModules,
modDirVersion, preferBuiltin, extraConfig`).
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
mptcp93.override ({
name="mptcp-local";
let
baseKernel = pkgs.linux_latest;
in pkgs.linuxManualConfig {
inherit (baseKernel) src modDirVersion;
version = "${baseKernel.version}-custom";
configfile = ./my_kernel_config;
allowImportFromDerivation = true;
}
```

ignoreConfigErrors = true;
autoModules = false;
kernelPreferBuiltin = true;
::: {.note}
The build will fail if `modDirVersion` does not match the source's `kernel.release` file,
so `modDirVersion` should remain tied to `src`.
:::

enableParallelBuilding = true;
To edit the `.config` file for Linux X.Y, proceed as follows:

extraConfig = ''
DEBUG_KERNEL y
FRAME_POINTER y
KGDB y
KGDB_SERIAL_CONSOLE y
DEBUG_INFO y
'';
});
```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
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.

Expand Down
105 changes: 61 additions & 44 deletions nixos/doc/manual/from_md/configuration/linux-kernel.chapter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,65 +96,82 @@ boot.kernel.sysctl.&quot;net.ipv4.tcp_keepalive_time&quot; = 120;
available parameters, run <literal>sysctl -a</literal>.
</para>
<section xml:id="sec-linux-config-customizing">
<title>Customize your kernel</title>
<title>Building a custom kernel</title>
<para>
The first step before compiling the kernel is to generate an
appropriate <literal>.config</literal> configuration. Either you
pass your own config via the <literal>configfile</literal> setting
of <literal>linuxKernel.manualConfig</literal>:
You can customize the default kernel configuration by overriding
the arguments for your kernel package:
</para>
<programlisting language="bash">
custom-kernel = let base_kernel = linuxKernel.kernels.linux_4_9;
in super.linuxKernel.manualConfig {
inherit (super) stdenv hostPlatform;
inherit (base_kernel) src;
version = &quot;${base_kernel.version}-custom&quot;;

configfile = /home/me/my_kernel_config;
allowImportFromDerivation = true;
};
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;
};
}
</programlisting>
<para>
You can edit the config with this snippet (by default
<literal>make menuconfig</literal> won't work out of the box on
nixos):
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.
</para>
<programlisting>
nix-shell -E 'with import &lt;nixpkgs&gt; {}; kernelToOverride.overrideAttrs (o: {nativeBuildInputs=o.nativeBuildInputs ++ [ pkg-config ncurses ];})'
<para>
To use your custom kernel package in your NixOS configuration, set
</para>
<programlisting language="bash">
boot.kernelPackages = pkgs.linuxPackagesFor yourCustomKernel;
</programlisting>
<para>
or you can let nixpkgs generate the configuration. Nixpkgs
generates it via answering the interactive kernel utility
<literal>make config</literal>. The answers depend on parameters
passed to
<literal>pkgs/os-specific/linux/kernel/generic.nix</literal>
(which you can influence by overriding
<literal>extraConfig, autoModules, modDirVersion, preferBuiltin, extraConfig</literal>).
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>:
</para>
<programlisting language="bash">
mptcp93.override ({
name=&quot;mptcp-local&quot;;

ignoreConfigErrors = true;
autoModules = false;
kernelPreferBuiltin = true;

enableParallelBuilding = true;

extraConfig = ''
DEBUG_KERNEL y
FRAME_POINTER y
KGDB y
KGDB_SERIAL_CONSOLE y
DEBUG_INFO y
'';
});
let
baseKernel = pkgs.linux_latest;
in pkgs.linuxManualConfig {
inherit (baseKernel) src modDirVersion;
version = &quot;${baseKernel.version}-custom&quot;;
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 '&lt;nixpkgs&gt;' -A linuxKernel.kernels.linux_X_Y.configEnv
$ unpackPhase
$ cd linux-*
$ make nconfig
</programlisting>
</section>
<section xml:id="sec-linux-config-developing-modules">
<title>Developing kernel modules</title>
<para>
When developing kernel modules it's often convenient to run
When developing kernel modules its often convenient to run
edit-compile-run loop as quickly as possible. See below snippet as
an example of developing <literal>mellanox</literal> drivers.
</para>
Expand Down
3 changes: 2 additions & 1 deletion nixos/lib/testing/legacy.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ let
inherit (lib) mkIf mkOption types;
in
{
# This needs options.warnings, which we don't have (yet?).
# This needs options.warnings and options.assertions, which we don't have (yet?).
# imports = [
# (lib.mkRenamedOptionModule [ "machine" ] [ "nodes" "machine" ])
# (lib.mkRemovedOptionModule [ "minimal" ] "The minimal kernel module was removed as it was broken and not used any more in nixpkgs.")
# ];

options = {
Expand Down
10 changes: 1 addition & 9 deletions nixos/lib/testing/nodes.nix
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ let
nixpkgs.config.allowAliases = false;
})
testModuleArgs.config.extraBaseModules
] ++ optional config.minimal ../../modules/testing/minimal-kernel.nix;
];
};


Expand Down Expand Up @@ -78,14 +78,6 @@ in
'';
};

minimal = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
Enable to configure all [{option}`nodes`](#test-opt-nodes) to run with a minimal kernel.
'';
};

ncfavier marked this conversation as resolved.
Show resolved Hide resolved
nodesCompat = mkOption {
internal = true;
description = mdDoc ''
Expand Down
28 changes: 0 additions & 28 deletions nixos/modules/testing/minimal-kernel.nix

This file was deleted.

20 changes: 15 additions & 5 deletions pkgs/os-specific/linux/kernel/generic.nix
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
structuredExtraConfig ? {}

, # The version number used for the module directory
modDirVersion ? version
# If unspecified, this is determined automatically from the version.
modDirVersion ? null

, # An attribute set whose attributes express the availability of
# certain features in this kernel. E.g. `{iwlwifi = true;}'
Expand Down Expand Up @@ -194,17 +195,26 @@ let
};
}; # end of configfile derivation

kernel = (callPackage ./manual-config.nix { inherit buildPackages; }) (basicArgs // {
inherit modDirVersion kernelPatches randstructSeed lib stdenv extraMakeFlags extraMeta configfile;
kernel = (callPackage ./manual-config.nix { inherit lib stdenv buildPackages; }) (basicArgs // {
inherit kernelPatches randstructSeed extraMakeFlags extraMeta configfile;
pos = builtins.unsafeGetAttrPos "version" args;

config = { CONFIG_MODULES = "y"; CONFIG_FW_LOADER = "m"; };
});
} // lib.optionalAttrs (modDirVersion != null) { inherit modDirVersion; });

passthru = basicArgs // {
features = kernelFeatures;
inherit commonStructuredConfig structuredExtraConfig extraMakeFlags isZen isHardened isLibre modDirVersion;
inherit commonStructuredConfig structuredExtraConfig extraMakeFlags isZen isHardened isLibre;
isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true;

# Adds dependencies needed to edit the config:
# nix-shell '<nixpkgs>' -A linux.configEnv --command 'make nconfig'
configEnv = kernel.overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs or [] ++ (with buildPackages; [
pkg-config ncurses
]);
});

passthru = kernel.passthru // (removeAttrs passthru [ "passthru" ]);
tests = let
overridableKernel = finalKernel // {
Expand Down
4 changes: 2 additions & 2 deletions pkgs/os-specific/linux/kernel/linux-4.14.nix
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{ lib, buildPackages, fetchurl, perl, buildLinux, nixosTests, modDirVersionArg ? null, ... } @ args:
{ lib, buildPackages, fetchurl, perl, buildLinux, nixosTests, ... } @ args:

with lib;

buildLinux (args // rec {
version = "4.14.302";

# modDirVersion needs to be x.y.z, will automatically add .0 if needed
modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg;
modDirVersion = versions.pad 3 version;

# branchVersion needs to be x.y
extraMeta.branch = versions.majorMinor version;
Expand Down
Loading