DISTRO: Fedora 41 KDE
GOAL: Im trying to automatically set some cpu parameters (per-CPU max frequency, governors, energy policy, etc.) during my boot process. I wrote a script to do this (it lives at /usr/local/bin/cpu-tune.sh)...I just need this to get run automatically.
WHY: My i9-7940x will happily draw 300 W all day if it has sufficient work to do. These tweaks allow me to selectively slow down the hottest cores so they run cooler. I lose maybe 1% max performance, in in exchange and my hottest CPU core temps drop by 10 C. (and i no longer fail any of the mprime tests)
CUSTOM BOOT SEQUENCE: My system bootup is unlike most Fedora systems. I use Unified Kernel Images (UKIs) to boot directly from the UEFI (no grub/systemd-boot). These images are signed with my personal signing key, since i use secure boot with all keys other than my own removed. The UKI then asks for my password, unlocks a LUKS partition, imports the root ZFS pool from the device-mapper block device (I use ZFS on root) and mounts the various ZFS datasets that make up my root filesystem.
WHAT IVE TRIED: a bunch of stuff.
first I tried a simple systemd service that was more-or-less:
[Unit] Description=Force CPU tuning udev re-trigger After=systemd-udevd.service systemd-udev-trigger.service [Service] Type=oneshot RemainAfterExit=true ExecStart=/usr/bin/bash /usr/local/bin/cpu-tune.sh [Install] WantedBy=multi-user.target This didnt work, even if I manually started the service with systemctl.
NOTE: running /usr/bin/bash /usr/local/bin/tune-cpu.sh manually works...but it doesnt in the systemd service.
so i tried adding some extra capabilities
User=root # shared keyring KeyringMode=shared # Required privileges CapabilityBoundingSet=CAP_SYS_ADMIN CAP_SYS_RAWIO CAP_DAC_OVERRIDE AmbientCapabilities=CAP_SYS_ADMIN CAP_SYS_RAWIO CAP_DAC_OVERRIDE # Disable systemd protections that block /sys writes ProtectSystem=no ProtectKernelTunables=no ProtectKernelModules=no ProtectControlGroups=no and...no change. still doesnt work. so i figured id try udev instead. added a custom rule
ACTION=="add|change", SUBSYSTEM=="cpu", KERNEL=="cpu[0-9]*", RUN+="/usr/bin/bash /usr/local/bin/cpu-tune.sh %k" and made cpu-tune.sh:
/usr/local/bin/cpu-tune.sh is: #!/usr/bin/bash # cpu-tune.sh - invoked by udev with %k (e.g. cpu0) # Keep this tiny and fast: udev wants short-running helpers. nn="${1##*[^0-9]}" # small helper to write safely (retry a few times) safe_write() { local file="$1" local value="$2" local i=0 while :; do if [ -w "${file}" ] || [ ! -e "${file}" ] && [ -w "$(dirname "$file")" ]; then printf '%s' "$value" > "$file" && return 0 fi i=$((i+1)) if [ $i -ge 5 ]; then printf '%s: failed writing %s -> %s\n' "$(date -Iseconds)" "$file" "$value" >> /var/log/cpu-tune.log return 1 fi sleep 0.05 done } case "$nn" in 3|5|17|19) safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/energy_performance_preference" "balance_performance" safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/scaling_governor" "powersave" safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/scaling_max_freq" "3900000" safe_write "/sys/devices/system/cpu/cpu${nn}/power/energy_perf_bias" "15" ;; 4|8|9|11|18|22|23|25) safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/energy_performance_preference" "balance_performance" safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/scaling_governor" "powersave" safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/scaling_max_freq" "4000000" safe_write "/sys/devices/system/cpu/cpu${nn}/power/energy_perf_bias" "15" ;; 1|15|13|27) safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/energy_performance_preference" "balance_performance" safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/scaling_governor" "powersave" safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/scaling_max_freq" "4100000" safe_write "/sys/devices/system/cpu/cpu${nn}/power/energy_perf_bias" "15" ;; *) safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/energy_performance_preference" "performance" safe_write "/sys/devices/system/cpu/cpu${nn}/cpufreq/scaling_governor" "performance" safe_write "/sys/devices/system/cpu/cpu${nn}/power/energy_perf_bias" "0" ;; esac # also try enabling hwp dynamic boost once per invocation (harmless if not present) safe_write "/sys/devices/system/cpu/intel_pstate/hwp_dynamic_boost" "1" || true This one i can trigger with udevadm trigger --subsystem-match=cpu. But does it trigger on boot? no, of course not. So i figure ill have systemd run the udevadm command for me. i change the systemd service above so that
ExecStart=/bin/udevadm trigger --subsystem-match=cpu And it works! well, if i manually start the service at least. But does that service run during boot? no, no it doesnt.
so, finally, i recreate my UKI so that the udev rules and the xcpu-tune.sh script are present. And.....still doesnt work.
At this point im sorta out of ideas....anyone know what im doing wrong?