Merge pull request #258994 from lorenzleutgeb/msr

nixos/hardware/cpu/x86/msr: init

authored by

Ryan Lahfa and committed by
GitHub
efccbbab ed02e10e

+99 -6
+2
nixos/doc/manual/release-notes/rl-2311.section.md
··· 493 493 - The `electron` packages now places its application files in `$out/libexec/electron` instead of `$out/lib/electron`. Packages using electron-builder will fail to build and need to be adjusted by changing `lib` to `libexec`. 494 494 495 495 - `teleport` has been upgraded from major version 12 to major version 14. Please see upstream [upgrade instructions](https://goteleport.com/docs/management/operations/upgrading/) and release notes for versions [13](https://goteleport.com/docs/changelog/#1300-050823) and [14](https://goteleport.com/docs/changelog/#1400-092023). Note that Teleport does not officially support upgrades across more than one major version at a time. If you're running Teleport server components, it is recommended to first upgrade to an intermediate 13.x version by setting `services.teleport.package = pkgs.teleport_13`. Afterwards, this option can be removed to upgrade to the default version (14). 496 + 497 + - The Linux kernel module `msr` (see [`msr(4)`](https://man7.org/linux/man-pages/man4/msr.4.html)), which provides an interface to read and write the model-specific registers (MSRs) of an x86 CPU, can now be configured via `hardware.cpu.x86.msr`.
+91
nixos/modules/hardware/cpu/x86-msr.nix
··· 1 + { lib 2 + , config 3 + , options 4 + , ... 5 + }: 6 + let 7 + inherit (builtins) hasAttr; 8 + inherit (lib) mkIf mdDoc; 9 + cfg = config.hardware.cpu.x86.msr; 10 + opt = options.hardware.cpu.x86.msr; 11 + defaultGroup = "msr"; 12 + isDefaultGroup = cfg.group == defaultGroup; 13 + set = "to set for devices of the `msr` kernel subsystem."; 14 + 15 + # Generates `foo=bar` parameters to pass to the kernel. 16 + # If `module = baz` is passed, generates `baz.foo=bar`. 17 + # Adds double quotes on demand to handle `foo="bar baz"`. 18 + kernelParam = { module ? null }: name: value: 19 + assert lib.asserts.assertMsg (!lib.strings.hasInfix "=" name) "kernel parameter cannot have '=' in name"; 20 + let 21 + key = (if module == null then "" else module + ".") + name; 22 + valueString = lib.generators.mkValueStringDefault {} value; 23 + quotedValueString = if lib.strings.hasInfix " " valueString 24 + then lib.strings.escape ["\""] valueString 25 + else valueString; 26 + in "${key}=${quotedValueString}"; 27 + msrKernelParam = kernelParam { module = "msr"; }; 28 + in 29 + { 30 + options.hardware.cpu.x86.msr = with lib.options; with lib.types; { 31 + enable = mkEnableOption (mdDoc "the `msr` (Model-Specific Registers) kernel module and configure `udev` rules for its devices (usually `/dev/cpu/*/msr`)"); 32 + owner = mkOption { 33 + type = str; 34 + default = "root"; 35 + example = "nobody"; 36 + description = mdDoc "Owner ${set}"; 37 + }; 38 + group = mkOption { 39 + type = str; 40 + default = defaultGroup; 41 + example = "nobody"; 42 + description = mdDoc "Group ${set}"; 43 + }; 44 + mode = mkOption { 45 + type = str; 46 + default = "0640"; 47 + example = "0660"; 48 + description = mdDoc "Mode ${set}"; 49 + }; 50 + settings = mkOption { 51 + type = submodule { 52 + freeformType = attrsOf (oneOf [ bool int str ]); 53 + options.allow-writes = mkOption { 54 + type = nullOr (enum ["on" "off"]); 55 + default = null; 56 + description = "Whether to allow writes to MSRs (`\"on\"`) or not (`\"off\"`)."; 57 + }; 58 + }; 59 + default = {}; 60 + description = "Parameters for the `msr` kernel module."; 61 + }; 62 + }; 63 + 64 + config = mkIf cfg.enable { 65 + assertions = [ 66 + { 67 + assertion = hasAttr cfg.owner config.users.users; 68 + message = "Owner '${cfg.owner}' set in `${opt.owner}` is not configured via `${options.users.users}.\"${cfg.owner}\"`."; 69 + } 70 + { 71 + assertion = isDefaultGroup || (hasAttr cfg.group config.users.groups); 72 + message = "Group '${cfg.group}' set in `${opt.group}` is not configured via `${options.users.groups}.\"${cfg.group}\"`."; 73 + } 74 + ]; 75 + 76 + boot = { 77 + kernelModules = [ "msr" ]; 78 + kernelParams = lib.attrsets.mapAttrsToList msrKernelParam (lib.attrsets.filterAttrs (_: value: value != null) cfg.settings); 79 + }; 80 + 81 + users.groups.${cfg.group} = mkIf isDefaultGroup { }; 82 + 83 + services.udev.extraRules = '' 84 + SUBSYSTEM=="msr", OWNER="${cfg.owner}", GROUP="${cfg.group}", MODE="${cfg.mode}" 85 + ''; 86 + }; 87 + 88 + meta = with lib; { 89 + maintainers = with maintainers; [ lorenzleutgeb ]; 90 + }; 91 + }
+1
nixos/modules/module-list.nix
··· 55 55 ./hardware/cpu/amd-sev.nix 56 56 ./hardware/cpu/intel-microcode.nix 57 57 ./hardware/cpu/intel-sgx.nix 58 + ./hardware/cpu/x86-msr.nix 58 59 ./hardware/decklink.nix 59 60 ./hardware/device-tree.nix 60 61 ./hardware/digitalbitbox.nix
+2 -3
nixos/modules/services/hardware/throttled.nix
··· 29 29 30 30 # Kernel 5.9 spams warnings whenever userspace writes to CPU MSRs. 31 31 # See https://github.com/erpalma/throttled/issues/215 32 - boot.kernelParams = 33 - optional (versionAtLeast config.boot.kernelPackages.kernel.version "5.9") 34 - "msr.allow_writes=on"; 32 + hardware.cpu.x86.msr.settings.allow-writes = 33 + mkIf (versionAtLeast config.boot.kernelPackages.kernel.version "5.9") "on"; 35 34 }; 36 35 }
+1 -1
nixos/modules/services/hardware/tlp.nix
··· 47 47 48 48 ###### implementation 49 49 config = mkIf cfg.enable { 50 - boot.kernelModules = [ "msr" ]; 50 + hardware.cpu.x86.msr.enable = true; 51 51 52 52 warnings = optional (cfg.extraConfig != "") '' 53 53 Using config.services.tlp.extraConfig is deprecated and will become unsupported in a future release. Use config.services.tlp.settings instead.
+1 -1
nixos/modules/services/hardware/undervolt.nix
··· 159 159 }; 160 160 161 161 config = mkIf cfg.enable { 162 - boot.kernelModules = [ "msr" ]; 162 + hardware.cpu.x86.msr.enable = true; 163 163 164 164 environment.systemPackages = [ cfg.package ]; 165 165
+1 -1
nixos/modules/services/misc/xmrig.nix
··· 52 52 }; 53 53 54 54 config = mkIf cfg.enable { 55 - boot.kernelModules = [ "msr" ]; 55 + hardware.cpu.x86.msr.enable = true; 56 56 57 57 systemd.services.xmrig = { 58 58 wantedBy = [ "multi-user.target" ];