From 8073aa4e473ba5d748e9946c90497eb3d9464777 Mon Sep 17 00:00:00 2001 From: Antoine Viallon Date: Wed, 12 Oct 2022 19:22:13 +0200 Subject: [PATCH] [Power] Init power related config. Also add cpuVendor setting. --- default.nix | 1 + general.nix | 7 +++ power.nix | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 power.nix diff --git a/default.nix b/default.nix index cade0b9..8107d80 100644 --- a/default.nix +++ b/default.nix @@ -13,6 +13,7 @@ ./hardening.nix ./hardware.nix ./laptop.nix + ./power.nix ./overlays.nix ./optimizations.nix ./non-persistence.nix diff --git a/general.nix b/general.nix index 3700765..4cbfd4c 100644 --- a/general.nix +++ b/general.nix @@ -51,6 +51,13 @@ in description = "Number of physical threads of the machine"; type = with types; nullOr ints.positive; }; + + cpuVendor = mkOption { + default = null; + example = "amd"; + description = "Vendor of you CPU. Either AMD or Intel"; + type = types.str; + }; cpuArch = mkOption { default = "x86-64"; diff --git a/power.nix b/power.nix new file mode 100644 index 0000000..6744198 --- /dev/null +++ b/power.nix @@ -0,0 +1,169 @@ +{ config, pkgs, lib, myLib, ... }: +with lib; +let + generalCfg = config.aviallon.general; + cfg = config.aviallon.power; + undervoltType = with types; nullOr (addCheck int (x: (x < 0 && x > -200))); +in { + options.aviallon.power = { + enable = mkOption { + default = true; + example = false; + type = types.bool; + description = "Wether to enable power related tuning"; + }; + /*policy = mkOption { + default = "performance"; + example = "efficiency"; + description = "What to optimize towards"; + type = types.either [ "performance" "efficiency" ]; + };*/ + powerLimit = { + enable = mkEnableOption "power limiting"; + ac = { + cpu = mkOption { + default = null; + type = types.nullOr types.int; + description = "Power limit when on AC. Set to null for unlimited."; + example = 35; + }; + cpuBoost = mkOption { + default = null; + type = types.nullOr types.int; + description = "Boost power limit when on AC. Set to null for unlimited."; + example = 65; + }; + }; + battery = { + cpu = mkOption { + default = null; + type = types.nullOr types.int; + description = "Power limit when on battery. Set to null for unlimited."; + example = 15; + }; + cpuBoost = mkOption { + default = null; + type = types.nullOr types.int; + description = "Boost power limit when on battery. Set to null for unlimited."; + example = 35; + }; + }; + }; + temperature = { + enable = mkEnableOption "Temperature limitting"; + ac = { + cpu = mkOption { + default = null; + type = types.nullOr types.int; + description = "Temperature limit when on AC."; + example = 100; + }; + }; + battery = { + cpu = mkOption { + default = null; + type = types.nullOr types.int; + description = "Temperature limit when on battery."; + example = 60; + }; + }; + }; + undervolt.cpu = { + enable = mkEnableOption "CPU undervolting. Unstability may be caused when using this option."; + coreOffset = mkOption { + default = null; + example = -25; + description = "CPU core offset in mV"; + type = undervoltType; + }; + cacheOffset = mkOption { + default = cfg.undervolt.cpu.coreOffset; + example = -25; + description = "Cache offset in mV"; + type = undervoltType; + }; + iGPUOffset = mkOption { + default = null; + example = -15; + description = "iGPU offset in mV"; + type = undervoltType; + }; + }; + undervolt.gpu = { + enable = mkEnableOption "GPU undervolting."; + }; + }; + config = mkIf cfg.enable { + systemd.targets.ac-power = { + description = "Target is active when AC is plugged-in."; + wantedBy = [ "multi-user.target" ]; + conflicts = [ "battery-power.target" ]; + unitConfig = { + ConditionACPower = true; + }; + }; + + systemd.targets.battery-power = { + description = "Target is active when power is drawn from a battery."; + wantedBy = [ "multi-user.target" ]; + conflicts = [ "ac-power.target" ]; + }; + + services.udev.extraRules = '' + KERNEL=="AC*", SUBSYSTEM=="power_supply", ATTR{online}=="0", RUN+="${pkgs.systemd}/bin/systemctl stop ac-power.target" + KERNEL=="AC*", SUBSYSTEM=="power_supply", ATTR{online}=="1", RUN+="${pkgs.systemd}/bin/systemctl start ac-power.target" + + KERNEL=="BAT*", SUBSYSTEM=="power_supply", ATTR{status}=="Discharging", RUN+="${pkgs.systemd}/bin/systemctl start battery-power.target" + KERNEL=="BAT*", SUBSYSTEM=="power_supply", ATTR{status}=="Charging", RUN+="${pkgs.systemd}/bin/systemctl stop battery-power.target" + ''; + + systemd.services.undervolt-intel = { + script = "" + + "${pkgs.undervolt}/bin/undervolt" + + (optionalString (! isNull cfg.undervolt.cpu.coreOffset ) " --core ${toString cfg.undervolt.cpu.coreOffset}") + + (optionalString (! isNull cfg.undervolt.cpu.cacheOffset ) " --cache ${toString cfg.undervolt.cpu.cacheOffset}") + + (optionalString (! isNull cfg.undervolt.cpu.iGPUOffset ) " --gpu ${toString cfg.undervolt.cpu.iGPUOffset}") + ; + serviceConfig = { + RemainAfterExit = true; + }; + wantedBy = [ "multi-user.target" ]; + description = "Undervolt Intel CPUs with supported firmware."; + enable = cfg.undervolt.cpu.enable && (generalCfg.cpuVendor == "intel"); + }; + + systemd.services.intel-powerlimit-ac = { + script = "${pkgs.undervolt}/bin/undervolt" + + optionalString (! isNull cfg.powerLimit.ac.cpu ) " --power-limit-long ${toString cfg.powerLimit.ac.cpu} 28" + + optionalString (! isNull cfg.powerLimit.ac.cpuBoost ) " --power-limit-short ${toString cfg.powerLimit.ac.cpuBoost} 0.1" + + optionalString (! isNull cfg.temperature.ac.cpu ) " --temp ${toString cfg.temperature.ac.cpu}" + ; + unitConfig = { + ConditionACPower = true; + }; + serviceConfig = { + RemainAfterExit = true; + }; + wantedBy = [ "multi-user.target" "ac-power.target" ]; + description = "Set power limit of Intel CPUs with supported firmware. AC mode."; + partOf = [ "ac-power.target" ]; + enable = (cfg.powerLimit.enable || cfg.temperature.enable) && (generalCfg.cpuVendor == "intel"); + }; + + systemd.services.intel-powerlimit-battery = { + script = "${pkgs.undervolt}/bin/undervolt" + + optionalString (! isNull cfg.powerLimit.battery.cpu ) " --power-limit-long ${toString cfg.powerLimit.battery.cpu} 28" + + optionalString (! isNull cfg.powerLimit.battery.cpuBoost ) " --power-limit-short ${toString cfg.powerLimit.battery.cpuBoost} 0.1" + + optionalString (! isNull cfg.temperature.battery.cpu ) " --temp ${toString cfg.temperature.battery.cpu}" + ; + serviceConfig = { + RemainAfterExit = true; + }; + wantedBy = [ "multi-user.target" "battery-power.target" ]; + description = "Set power limit of Intel CPUs with supported firmware. Battery mode."; + partOf = [ "battery-power.target" ]; + enable = (cfg.powerLimit.enable || cfg.temperature.enable) && (generalCfg.cpuVendor == "intel"); + }; + + }; +}