at 24.11-pre 3.0 kB view raw
1{ lib 2, config 3, options 4, ... 5}: 6let 7 inherit (builtins) hasAttr; 8 inherit (lib) mkIf; 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"; }; 28in 29{ 30 options.hardware.cpu.x86.msr = with lib.options; with lib.types; { 31 enable = mkEnableOption "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 = "Owner ${set}"; 37 }; 38 group = mkOption { 39 type = str; 40 default = defaultGroup; 41 example = "nobody"; 42 description = "Group ${set}"; 43 }; 44 mode = mkOption { 45 type = str; 46 default = "0640"; 47 example = "0660"; 48 description = "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}