1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 crashdump = config.boot.crashDump;
7
8 kernelParams = concatStringsSep " " crashdump.kernelParams;
9
10in
11###### interface
12{
13 options = {
14 boot = {
15 crashDump = {
16 enable = mkOption {
17 type = types.bool;
18 default = false;
19 description = lib.mdDoc ''
20 If enabled, NixOS will set up a kernel that will
21 boot on crash, and leave the user in systemd rescue
22 to be able to save the crashed kernel dump at
23 /proc/vmcore.
24 It also activates the NMI watchdog.
25 '';
26 };
27 reservedMemory = mkOption {
28 default = "128M";
29 type = types.str;
30 description = lib.mdDoc ''
31 The amount of memory reserved for the crashdump kernel.
32 If you choose a too high value, dmesg will mention
33 "crashkernel reservation failed".
34 '';
35 };
36 kernelParams = mkOption {
37 type = types.listOf types.str;
38 default = [ "1" "boot.shell_on_fail" ];
39 description = lib.mdDoc ''
40 Parameters that will be passed to the kernel kexec-ed on crash.
41 '';
42 };
43 };
44 };
45 };
46
47###### implementation
48
49 config = mkIf crashdump.enable {
50 boot = {
51 postBootCommands = ''
52 echo "loading crashdump kernel...";
53 ${pkgs.kexec-tools}/sbin/kexec -p /run/current-system/kernel \
54 --initrd=/run/current-system/initrd \
55 --reset-vga --console-vga \
56 --command-line="init=$(readlink -f /run/current-system/init) irqpoll maxcpus=1 reset_devices ${kernelParams}"
57 '';
58 kernelParams = [
59 "crashkernel=${crashdump.reservedMemory}"
60 "nmi_watchdog=panic"
61 "softlockup_panic=1"
62 ];
63 kernelPatches = [ {
64 name = "crashdump-config";
65 patch = null;
66 extraConfig = ''
67 CRASH_DUMP y
68 DEBUG_INFO y
69 PROC_VMCORE y
70 LOCKUP_DETECTOR y
71 HARDLOCKUP_DETECTOR y
72 '';
73 } ];
74 };
75 };
76}