Merge #361424: refactor lib.packagesFromDirectoryRecursive (v2)
[NixPkgs.git] / nixos / modules / services / hardware / rasdaemon.nix
blob53a0780e4e341a2abcc8695c57461964e796514b
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
9   cfg = config.hardware.rasdaemon;
13   options.hardware.rasdaemon = {
15     enable = lib.mkEnableOption "RAS logging daemon";
17     record = lib.mkOption {
18       type = lib.types.bool;
19       default = true;
20       description = "record events via sqlite3, required for ras-mc-ctl";
21     };
23     mainboard = lib.mkOption {
24       type = lib.types.lines;
25       default = "";
26       description = "Custom mainboard description, see {manpage}`ras-mc-ctl(8)` for more details.";
27       example = ''
28         vendor = ASRock
29         model = B450M Pro4
31         # it should default to such values from
32         # /sys/class/dmi/id/board_[vendor|name]
33         # alternatively one can supply a script
34         # that returns the same format as above
36         script = <path to script>
37       '';
38     };
40     # TODO, accept `rasdaemon.labels = " ";` or `rasdaemon.labels = { dell = " "; asrock = " "; };'
42     labels = lib.mkOption {
43       type = lib.types.lines;
44       default = "";
45       description = "Additional memory module label descriptions to be placed in /etc/ras/dimm_labels.d/labels";
46       example = ''
47         # vendor and model may be shown by 'ras-mc-ctl --mainboard'
48         vendor: ASRock
49           product: To Be Filled By O.E.M.
50           model: B450M Pro4
51             # these labels are names for the motherboard slots
52             # the numbers may be shown by `ras-mc-ctl --error-count`
53             # they are mc:csrow:channel
54             DDR4_A1: 0.2.0;  DDR4_B1: 0.2.1;
55             DDR4_A2: 0.3.0;  DDR4_B2: 0.3.1;
56       '';
57     };
59     config = lib.mkOption {
60       type = lib.types.lines;
61       default = "";
62       description = ''
63         rasdaemon configuration, currently only used for CE PFA
64         for details, read rasdaemon.outPath/etc/sysconfig/rasdaemon's comments
65       '';
66       example = ''
67         # defaults from included config
68         PAGE_CE_REFRESH_CYCLE="24h"
69         PAGE_CE_THRESHOLD="50"
70         PAGE_CE_ACTION="soft"
71       '';
72     };
74     extraModules = lib.mkOption {
75       type = lib.types.listOf lib.types.str;
76       default = [ ];
77       description = "extra kernel modules to load";
78       example = [ "i7core_edac" ];
79     };
81     testing = lib.mkEnableOption "error injection infrastructure";
82   };
84   config = lib.mkIf cfg.enable {
86     environment.etc = {
87       "ras/mainboard" = {
88         enable = cfg.mainboard != "";
89         text = cfg.mainboard;
90       };
91       # TODO, handle multiple cfg.labels.brand = " ";
92       "ras/dimm_labels.d/labels" = {
93         enable = cfg.labels != "";
94         text = cfg.labels;
95       };
96       "sysconfig/rasdaemon" = {
97         enable = cfg.config != "";
98         text = cfg.config;
99       };
100     };
101     environment.systemPackages =
102       [ pkgs.rasdaemon ]
103       ++ lib.optionals (cfg.testing) (
104         with pkgs.error-inject;
105         [
106           edac-inject
107           mce-inject
108           aer-inject
109         ]
110       );
112     boot.initrd.kernelModules =
113       cfg.extraModules
114       ++ lib.optionals (cfg.testing) [
115         # edac_core and amd64_edac should get loaded automatically
116         # i7core_edac may not be, and may not be required, but should load successfully
117         "edac_core"
118         "amd64_edac"
119         "i7core_edac"
120         "mce-inject"
121         "aer-inject"
122       ];
124     boot.kernelPatches = lib.optionals (cfg.testing) [
125       {
126         name = "rasdaemon-tests";
127         patch = null;
128         extraConfig = ''
129           EDAC_DEBUG y
130           X86_MCE_INJECT y
132           PCIEPORTBUS y
133           PCIEAER y
134           PCIEAER_INJECT y
135         '';
136       }
137     ];
139     # i tried to set up a group for this
140     # but rasdaemon needs higher permissions?
141     # `rasdaemon: Can't locate a mounted debugfs`
143     # most of this taken from src/misc/
144     systemd.services = {
145       rasdaemon = {
146         description = "the RAS logging daemon";
147         documentation = [ "man:rasdaemon(1)" ];
148         wantedBy = [ "multi-user.target" ];
150         serviceConfig = {
151           StateDirectory = lib.optionalString (cfg.record) "rasdaemon";
153           ExecStart =
154             "${pkgs.rasdaemon}/bin/rasdaemon --foreground" + lib.optionalString (cfg.record) " --record";
155           ExecStop = "${pkgs.rasdaemon}/bin/rasdaemon --disable";
156           Restart = "on-abort";
158           # src/misc/rasdaemon.service.in shows this:
159           # ExecStartPost = ${pkgs.rasdaemon}/bin/rasdaemon --enable
160           # but that results in unpredictable existence of the database
161           # and everything seems to be enabled without this...
162         };
163       };
164       ras-mc-ctl = lib.mkIf (cfg.labels != "") {
165         description = "register DIMM labels on startup";
166         documentation = [ "man:ras-mc-ctl(8)" ];
167         wantedBy = [ "multi-user.target" ];
168         serviceConfig = {
169           Type = "oneshot";
170           ExecStart = "${pkgs.rasdaemon}/bin/ras-mc-ctl --register-labels";
171           RemainAfterExit = true;
172         };
173       };
174     };
175   };
177   meta.maintainers = [ lib.maintainers.evils ];