tailscale: build derpprobe (#364918)
[NixPkgs.git] / nixos / modules / services / hardware / undervolt.nix
blob5a8ad9806ef1d2d01e0fa9f8976c656cf3d573a7
2   config,
3   pkgs,
4   lib,
5   ...
6 }:
7 let
8   cfg = config.services.undervolt;
10   mkPLimit =
11     limit: window:
12     if (limit == null && window == null) then
13       null
14     else
15       assert lib.asserts.assertMsg (
16         limit != null && window != null
17       ) "Both power limit and window must be set";
18       "${toString limit} ${toString window}";
19   cliArgs = lib.cli.toGNUCommandLine { } {
20     inherit (cfg)
21       verbose
22       temp
23       turbo
24       ;
25     # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs:
26     #
27     #     Core or Cache offsets have no effect. It is not possible to set different offsets for
28     #     CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to
29     #     both CPU and Cache. A warning message will be displayed if you attempt to set different offsets.
30     core = cfg.coreOffset;
31     cache = cfg.coreOffset;
32     gpu = cfg.gpuOffset;
33     uncore = cfg.uncoreOffset;
34     analogio = cfg.analogioOffset;
36     temp-bat = cfg.tempBat;
37     temp-ac = cfg.tempAc;
39     power-limit-long = mkPLimit cfg.p1.limit cfg.p1.window;
40     power-limit-short = mkPLimit cfg.p2.limit cfg.p2.window;
41   };
44   options.services.undervolt = {
45     enable = lib.mkEnableOption ''
46       Undervolting service for Intel CPUs.
48       Warning: This service is not endorsed by Intel and may permanently damage your hardware. Use at your own risk
49     '';
51     verbose = lib.mkOption {
52       type = lib.types.bool;
53       default = false;
54       description = ''
55         Whether to enable verbose logging.
56       '';
57     };
59     package = lib.mkPackageOption pkgs "undervolt" { };
61     coreOffset = lib.mkOption {
62       type = lib.types.nullOr lib.types.int;
63       default = null;
64       description = ''
65         The amount of voltage in mV to offset the CPU cores by.
66       '';
67     };
69     gpuOffset = lib.mkOption {
70       type = lib.types.nullOr lib.types.int;
71       default = null;
72       description = ''
73         The amount of voltage in mV to offset the GPU by.
74       '';
75     };
77     uncoreOffset = lib.mkOption {
78       type = lib.types.nullOr lib.types.int;
79       default = null;
80       description = ''
81         The amount of voltage in mV to offset uncore by.
82       '';
83     };
85     analogioOffset = lib.mkOption {
86       type = lib.types.nullOr lib.types.int;
87       default = null;
88       description = ''
89         The amount of voltage in mV to offset analogio by.
90       '';
91     };
93     temp = lib.mkOption {
94       type = lib.types.nullOr lib.types.int;
95       default = null;
96       description = ''
97         The temperature target in Celsius degrees.
98       '';
99     };
101     tempAc = lib.mkOption {
102       type = lib.types.nullOr lib.types.int;
103       default = null;
104       description = ''
105         The temperature target on AC power in Celsius degrees.
106       '';
107     };
109     tempBat = lib.mkOption {
110       type = lib.types.nullOr lib.types.int;
111       default = null;
112       description = ''
113         The temperature target on battery power in Celsius degrees.
114       '';
115     };
117     turbo = lib.mkOption {
118       type = lib.types.nullOr lib.types.int;
119       default = null;
120       description = ''
121         Changes the Intel Turbo feature status (1 is disabled and 0 is enabled).
122       '';
123     };
125     p1.limit = lib.mkOption {
126       type = with lib.types; nullOr int;
127       default = null;
128       description = ''
129         The P1 Power Limit in Watts.
130         Both limit and window must be set.
131       '';
132     };
133     p1.window = lib.mkOption {
134       type =
135         with lib.types;
136         nullOr (oneOf [
137           float
138           int
139         ]);
140       default = null;
141       description = ''
142         The P1 Time Window in seconds.
143         Both limit and window must be set.
144       '';
145     };
147     p2.limit = lib.mkOption {
148       type = with lib.types; nullOr int;
149       default = null;
150       description = ''
151         The P2 Power Limit in Watts.
152         Both limit and window must be set.
153       '';
154     };
155     p2.window = lib.mkOption {
156       type =
157         with lib.types;
158         nullOr (oneOf [
159           float
160           int
161         ]);
162       default = null;
163       description = ''
164         The P2 Time Window in seconds.
165         Both limit and window must be set.
166       '';
167     };
169     useTimer = lib.mkOption {
170       type = lib.types.bool;
171       default = false;
172       description = ''
173         Whether to set a timer that applies the undervolt settings every 30s.
174         This will cause spam in the journal but might be required for some
175         hardware under specific conditions.
176         Enable this if your undervolt settings don't hold.
177       '';
178     };
179   };
181   config = lib.mkIf cfg.enable {
182     hardware.cpu.x86.msr.enable = true;
184     environment.systemPackages = [ cfg.package ];
186     systemd.services.undervolt = {
187       description = "Intel Undervolting Service";
189       # Apply undervolt on boot, nixos generation switch and resume
190       wantedBy = [
191         "multi-user.target"
192         "post-resume.target"
193       ];
194       after = [ "post-resume.target" ]; # Not sure why but it won't work without this
196       serviceConfig = {
197         Type = "oneshot";
198         Restart = "no";
199         ExecStart = "${cfg.package}/bin/undervolt ${toString cliArgs}";
200       };
201     };
203     systemd.timers.undervolt = lib.mkIf cfg.useTimer {
204       description = "Undervolt timer to ensure voltage settings are always applied";
205       partOf = [ "undervolt.service" ];
206       wantedBy = [ "multi-user.target" ];
207       timerConfig = {
208         OnBootSec = "2min";
209         OnUnitActiveSec = "30";
210       };
211     };
212   };