at 25.11-pre 3.3 kB view raw
1{ 2 lib, 3 config, 4 options, 5 ... 6}: 7let 8 inherit (builtins) hasAttr; 9 inherit (lib) mkIf; 10 cfg = config.hardware.cpu.x86.msr; 11 opt = options.hardware.cpu.x86.msr; 12 defaultGroup = "msr"; 13 isDefaultGroup = cfg.group == defaultGroup; 14 set = "to set for devices of the `msr` kernel subsystem."; 15 16 # Generates `foo=bar` parameters to pass to the kernel. 17 # If `module = baz` is passed, generates `baz.foo=bar`. 18 # Adds double quotes on demand to handle `foo="bar baz"`. 19 kernelParam = 20 { 21 module ? null, 22 }: 23 name: value: 24 assert lib.asserts.assertMsg ( 25 !lib.strings.hasInfix "=" name 26 ) "kernel parameter cannot have '=' in name"; 27 let 28 key = (if module == null then "" else module + ".") + name; 29 valueString = lib.generators.mkValueStringDefault { } value; 30 quotedValueString = 31 if lib.strings.hasInfix " " valueString then 32 lib.strings.escape [ "\"" ] valueString 33 else 34 valueString; 35 in 36 "${key}=${quotedValueString}"; 37 msrKernelParam = kernelParam { module = "msr"; }; 38in 39{ 40 options.hardware.cpu.x86.msr = 41 with lib.options; 42 with lib.types; 43 { 44 enable = mkEnableOption "the `msr` (Model-Specific Registers) kernel module and configure `udev` rules for its devices (usually `/dev/cpu/*/msr`)"; 45 owner = mkOption { 46 type = str; 47 default = "root"; 48 example = "nobody"; 49 description = "Owner ${set}"; 50 }; 51 group = mkOption { 52 type = str; 53 default = defaultGroup; 54 example = "nobody"; 55 description = "Group ${set}"; 56 }; 57 mode = mkOption { 58 type = str; 59 default = "0640"; 60 example = "0660"; 61 description = "Mode ${set}"; 62 }; 63 settings = mkOption { 64 type = submodule { 65 freeformType = attrsOf (oneOf [ 66 bool 67 int 68 str 69 ]); 70 options.allow-writes = mkOption { 71 type = nullOr (enum [ 72 "on" 73 "off" 74 ]); 75 default = null; 76 description = "Whether to allow writes to MSRs (`\"on\"`) or not (`\"off\"`)."; 77 }; 78 }; 79 default = { }; 80 description = "Parameters for the `msr` kernel module."; 81 }; 82 }; 83 84 config = mkIf cfg.enable { 85 assertions = [ 86 { 87 assertion = hasAttr cfg.owner config.users.users; 88 message = "Owner '${cfg.owner}' set in `${opt.owner}` is not configured via `${options.users.users}.\"${cfg.owner}\"`."; 89 } 90 { 91 assertion = isDefaultGroup || (hasAttr cfg.group config.users.groups); 92 message = "Group '${cfg.group}' set in `${opt.group}` is not configured via `${options.users.groups}.\"${cfg.group}\"`."; 93 } 94 ]; 95 96 boot = { 97 kernelModules = [ "msr" ]; 98 kernelParams = lib.attrsets.mapAttrsToList msrKernelParam ( 99 lib.attrsets.filterAttrs (_: value: value != null) cfg.settings 100 ); 101 }; 102 103 users.groups.${cfg.group} = mkIf isDefaultGroup { }; 104 105 services.udev.extraRules = '' 106 SUBSYSTEM=="msr", OWNER="${cfg.owner}", GROUP="${cfg.group}", MODE="${cfg.mode}" 107 ''; 108 }; 109 110 meta = with lib; { 111 maintainers = with maintainers; [ lorenzleutgeb ]; 112 }; 113}