diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 396e91204079..2846afea8fbc 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -281,6 +281,7 @@ ./services/hardware/upower.nix ./services/hardware/usbmuxd.nix ./services/hardware/thermald.nix + ./services/hardware/undervolt.nix ./services/logging/SystemdJournal2Gelf.nix ./services/logging/awstats.nix ./services/logging/fluentd.nix diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix new file mode 100644 index 000000000000..e5ef0601de3c --- /dev/null +++ b/nixos/modules/services/hardware/undervolt.nix @@ -0,0 +1,134 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.undervolt; +in { + options.services.undervolt = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to undervolt intel cpus. + ''; + }; + + verbose = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable verbose logging. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.undervolt; + defaultText = "pkgs.undervolt"; + description = '' + undervolt derivation to use. + ''; + }; + + coreOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset the CPU cores by. Accepts a floating point number. + ''; + }; + + gpuOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset the GPU by. Accepts a floating point number. + ''; + }; + + uncoreOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset uncore by. Accepts a floating point number. + ''; + }; + + analogioOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset analogio by. Accepts a floating point number. + ''; + }; + + temp = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target. Accepts a floating point number. + ''; + }; + + tempAc = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target on AC power. Accepts a floating point number. + ''; + }; + + tempBat = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target on battery power. Accepts a floating point number. + ''; + }; + }; + + config = mkIf cfg.enable { + boot.kernelModules = [ "msr" ]; + + environment.systemPackages = [ cfg.package ]; + + systemd.services.undervolt = { + path = [ pkgs.undervolt ]; + + description = "Intel Undervolting Service"; + serviceConfig = { + Type = "oneshot"; + Restart = "no"; + + # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs: + # + # Core or Cache offsets have no effect. It is not possible to set different offsets for + # CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to + # both CPU and Cache. A warning message will be displayed if you attempt to set different offsets. + ExecStart = '' + ${pkgs.undervolt}/bin/undervolt \ + ${optionalString cfg.verbose "--verbose"} \ + ${optionalString (cfg.coreOffset != null) "--core ${cfg.coreOffset}"} \ + ${optionalString (cfg.coreOffset != null) "--cache ${cfg.coreOffset}"} \ + ${optionalString (cfg.gpuOffset != null) "--gpu ${cfg.gpuOffset}"} \ + ${optionalString (cfg.uncoreOffset != null) "--uncore ${cfg.uncoreOffset}"} \ + ${optionalString (cfg.analogioOffset != null) "--analogio ${cfg.analogioOffset}"} \ + ${optionalString (cfg.temp != null) "--temp ${cfg.temp}"} \ + ${optionalString (cfg.tempAc != null) "--temp-ac ${cfg.tempAc}"} \ + ${optionalString (cfg.tempBat != null) "--temp-bat ${cfg.tempBat}"} + ''; + }; + }; + + systemd.timers.undervolt = { + description = "Undervolt timer to ensure voltage settings are always applied"; + partOf = [ "undervolt.service" ]; + wantedBy = [ "multi-user.target" ]; + timerConfig = { + OnBootSec = "2min"; + OnUnitActiveSec = "30"; + }; + }; + }; +} diff --git a/pkgs/os-specific/linux/undervolt/default.nix b/pkgs/os-specific/linux/undervolt/default.nix new file mode 100644 index 000000000000..e9c033acd990 --- /dev/null +++ b/pkgs/os-specific/linux/undervolt/default.nix @@ -0,0 +1,27 @@ +{ stdenv, fetchFromGitHub, python3Packages }: + +python3Packages.buildPythonApplication rec { + version = "0.2.8"; + pname = "undervolt"; + + src = fetchFromGitHub { + owner = "georgewhewell"; + repo = "undervolt"; + rev = "${version}"; + sha256 = "0crkqc5zq0gpyg031hfwdxymfc2gc1h8b6m0axzlh7gvnxlf5hra"; + }; + + meta = with stdenv.lib; { + homepage = https://github.com/georgewhewell/undervolt/; + description = "A program for undervolting Intel CPUs on Linux"; + + longDescription = '' + Undervolt is a program for undervolting Intel CPUs under Linux. It works in a similar + manner to the Windows program ThrottleStop (i.e, MSR 0x150). You can apply a fixed + voltage offset to one of 5 voltage planes, and override your systems temperature + target (CPU will throttle when this temperature is reached). + ''; + license = licenses.gpl2; + platforms = [ "x86_64-linux" ]; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 1c804b47afec..5b4a090efc8a 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -22195,4 +22195,6 @@ with pkgs; powershell = callPackage ../shells/powershell { }; doing = callPackage ../applications/misc/doing { }; + + undervolt = callPackage ../os-specific/linux/undervolt { }; }