How to permanently limit CPU P-cores max frequency?

My CPU is a mobile Intel Core i9-13980HX (13th gen. Raptor Lake) which has the following capabilities when it comes to max frequencies

Frequency:	2.2 GHz
Turbo Clock:	up to 5.6 GHz
P-Core Boost 3.0:	5.5 GHz
E-Core Frequency:	1600 MHz up to 4 GHz

The driver in use is of course intel_pstate

According to Intel XTU application and laptop’s manufacturer (MSI) when Turbo Boost is enabled:

  • 2 out of 8 P-cores (CPU 2 and CPU 3/CPU 4-5 and CPU 6-7 when hyper-threading is enabled) are capable of reaching up to 5,6Ghz
  • the rest 6 out of 8 P-cores can go up to 5,4Ghz
  • 16 E-cores can go up to 4,0Ghz

The problem is I’m getting some stability issues when P-cores 2 and 3 are reaching max 5,6Ghz, so the idea is to limit max possible frequency of all P-cores to 5,4Ghz. I can do that temporarily with a command

sudo cpupower frequency-set -u 5400000

Unfortunately there are two limitations to this approach:

  1. it’s only temporary and it’s being reset after every reboot and also (!) after some time when i.e. playing a game.
  2. it has to be done manually with the command mentioned above

What I’ve tried to do is modyfing cpupower config file /etc/default/cpupower

# Limit frequency range
# Valid suffixes: Hz, kHz (default), MHz, GHz, THz
min_freq="0.80GHz"
max_freq="5.4GHz"

and running cpupower.service

● cpupower.service - Apply cpupower configuration
     Loaded: loaded (/usr/lib/systemd/system/cpupower.service; enabled; preset: disabled)
     Active: active (exited) since Sun 2025-03-09 09:19:31 CET; 39s ago
 Invocation: 3c19902ea7f94bb5a7b78be1e1f85969
    Process: 2542 ExecStart=/usr/lib/systemd/scripts/cpupower (code=exited, status=0/SUCCESS)
   Main PID: 2542 (code=exited, status=0/SUCCESS)
   Mem peak: 2M
        CPU: 14ms

mar 09 09:19:31 CachyOS systemd[1]: Starting Apply cpupower configuration...
mar 09 09:19:31 CachyOS systemd[1]: Finished Apply cpupower configuration.

The problem this doesn’t work as expected - cpupower.service does not set the proper max frequencies automatically after every reboot, although it does so when I restart it manually after login in, and the values are still being reset after some time. What could be the possible reason for that behaviour?

you want to lower frequency values

I’m not sure what do you mean and that you did read my post with understanding. Leaving this unresolved is unacceptable to me because of instability issues as I wrote before. Simple command solves that instability, so it works perfectly and the only problem is how to set this permanently. The cpupower frequency-set command works on my system and there aren’t any problems with different cores as cpupower cannot set any values beyond hardware limitations. Look

see this
https://wiki.archlinux.org/title/CPU_frequency_scaling

see with `cat /sys/devices/system/cpu/cpu*/cpufreq/*’

I have read this wiki entry already on many occasions and didn’t find a solution to my problem.

0
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
0
performance powersave
802183
intel_pstate
powersave
5400000
800000
<unsupported>
1
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
1
performance powersave
802977
intel_pstate
powersave
5400000
800000
<unsupported>
2
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
2
performance powersave
800000
intel_pstate
powersave
5400000
800000
<unsupported>
3
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
3
performance powersave
800000
intel_pstate
powersave
5400000
800000
<unsupported>
4
2200000
5600000
800000
0
default performance balance_performance balance_power power 
balance_performance
4
performance powersave
1100012
intel_pstate
powersave
5400000
800000
<unsupported>
5
2200000
5600000
800000
0
default performance balance_performance balance_power power 
balance_performance
5
performance powersave
800000
intel_pstate
powersave
5400000
800000
<unsupported>
6
2200000
5600000
800000
0
default performance balance_performance balance_power power 
balance_performance
6
performance powersave
799306
intel_pstate
powersave
5400000
800000
<unsupported>
7
2200000
5600000
800000
0
default performance balance_performance balance_power power 
balance_performance
7
performance powersave
800286
intel_pstate
powersave
5400000
800000
<unsupported>
8
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
8
performance powersave
846091
intel_pstate
powersave
5400000
800000
<unsupported>
9
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
9
performance powersave
800000
intel_pstate
powersave
5400000
800000
<unsupported>
10
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
10
performance powersave
1154999
intel_pstate
powersave
5400000
800000
<unsupported>
11
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
11
performance powersave
847768
intel_pstate
powersave
5400000
800000
<unsupported>
12
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
12
performance powersave
1339807
intel_pstate
powersave
5400000
800000
<unsupported>
13
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
13
performance powersave
800000
intel_pstate
powersave
5400000
800000
<unsupported>
14
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
14
performance powersave
1251653
intel_pstate
powersave
5400000
800000
<unsupported>
15
2200000
5400000
800000
0
default performance balance_performance balance_power power 
balance_performance
15
performance powersave
862587
intel_pstate
powersave
5400000
800000
<unsupported>
16
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
16
performance powersave
1000064
intel_pstate
powersave
4000000
800000
<unsupported>
17
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
17
performance powersave
999122
intel_pstate
powersave
4000000
800000
<unsupported>
18
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
18
performance powersave
799914
intel_pstate
powersave
4000000
800000
<unsupported>
19
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
19
performance powersave
800041
intel_pstate
powersave
4000000
800000
<unsupported>
20
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
20
performance powersave
800000
intel_pstate
powersave
4000000
800000
<unsupported>
21
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
21
performance powersave
799923
intel_pstate
powersave
4000000
800000
<unsupported>
22
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
22
performance powersave
800974
intel_pstate
powersave
4000000
800000
<unsupported>
23
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
23
performance powersave
800000
intel_pstate
powersave
4000000
800000
<unsupported>
24
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
24
performance powersave
800000
intel_pstate
powersave
4000000
800000
<unsupported>
25
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
25
performance powersave
800000
intel_pstate
powersave
4000000
800000
<unsupported>
26
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
26
performance powersave
800000
intel_pstate
powersave
4000000
800000
<unsupported>
27
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
27
performance powersave
800058
intel_pstate
powersave
4000000
800000
<unsupported>
28
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
28
performance powersave
801047
intel_pstate
powersave
4000000
800000
<unsupported>
29
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
29
performance powersave
919432
intel_pstate
powersave
4000000
800000
<unsupported>
30
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
30
performance powersave
798986
intel_pstate
powersave
4000000
800000
<unsupported>
31
1600000
4000000
800000
0
default performance balance_performance balance_power power 
balance_performance
31
performance powersave
800000
intel_pstate
powersave
4000000
800000
<unsupported>

maybe this : [SOLVED] Setting max frequency for a single core of a multi-core CPU / System Administration / Arch Linux Forums

https://www.kernel.org/doc/html/latest/admin-guide/pm/intel_pstate.html#coordination-of-p-state-limits

Thanks for those links, but my question would be not how to set the desired frequencies (I know that already), but rather is there some kind of process (like profile power-profiles-daemon?) which overrides my manual setting after a while? Maybe during system boot cpupower.service should be run in a proper order?

Does anyone have any suggestions? I’ve noticed that the “reset” to max frequency settings usually happens after starting a game - could the “game-performance” script be messing something up?

So far the only possible solution I’ve found regarding this topic is to set maximum performance percentage using intel_pstate driver with a command

echo "95" | sudo tee /sys/devices/system/cpu/intel_pstate/max_perf_pct

The number “95” means “95% of max performance” which down-clocks CPU cores a little bit, and it stays so until reboot. Unfortunately for making this permanent one has to create a script which will run and do this on startup. I didn’t find any other working solution.

Try making a systemd service that runs the appropriate command for setting your desired cpu frequency at each boot/reboot.

Use the following as pattern:

[Unit]
Description=Set the CPU frequency at boot

[Service]
Type=oneshot
ExecStart=/my/command/line

[Install]
WantedBy=multi-user.target

Create a file name.service with the name you want and put it in

/etc/systemd/system/

Then enable and start the service:

sudo systemctl enable --now name.service

This does not seem to work.

systemctl status procesor.service
○ procesor.service - Set the CPU frequency at boot
     Loaded: loaded (/etc/systemd/system/procesor.service; enabled; preset: disabled)
     Active: inactive (dead) since Sat 2025-04-12 20:00:57 CEST; 1min 13s ago
 Invocation: 818abe17d19549a0bafd4bf9422d5062
    Process: 2560 ExecStart=echo 95 | sudo tee /sys/devices/system/cpu/intel_pstate/max_perf_pct (code=exited, status=0/SUCCESS)
   Main PID: 2560 (code=exited, status=0/SUCCESS)
   Mem peak: 2M
        CPU: 6ms

kwi 12 20:00:57 CachyOS systemd[1]: Starting Set the CPU frequency at boot...
kwi 12 20:00:57 CachyOS echo[2560]: 95 | sudo tee /sys/devices/system/cpu/intel_pstate/max_perf_pct
kwi 12 20:00:57 CachyOS systemd[1]: procesor.service: Deactivated successfully.
kwi 12 20:00:57 CachyOS systemd[1]: Finished Set the CPU frequency at boot.

~
❯ cat /sys/devices/system/cpu/intel_pstate/max_perf_pct
100

Hi. Honestly, KDE’s Powerdevil and Power Profiles Daemon work pretty disgustingly and constantly reset settings after a reboot. For example, the system fails to remember the battery charge limit set in the settings.

Here are the bugs related to Powerdevil and Power Profiles Daemon. It’s unclear when they’ll be fixed:

I once wrote a script to limit battery charge levels for myself (I can share it if you need it). It can be adapted to your task, which I’ve done.
Just run it, and it will automatically create and enable the necessary service to run at system startup:

# Set cpu freq threshold
sudo tee /usr/local/bin/set-cpufreq-threshold.sh <<'EOF'
#!/bin/bash
echo 95 | tee /sys/devices/system/cpu/intel_pstate/max_perf_pct
EOF

# Grant execution permissions
sudo chmod +x /usr/local/bin/set-cpufreq-threshold.sh

# Create a systemd service
sudo tee /etc/systemd/system/set-cpufreq-threshold.service <<'EOF'
[Unit]
Description=Set CPU frequency threshold
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/set-cpufreq-threshold.sh
Restart=on-failure
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

# Enable and start the service
sudo systemctl enable --now set-cpufreq-threshold.service

You can also add the following values ​​to the [Service] section if you have problems with execution:

User=root
Group=root

But they should not occur, it works for me without it

–###–

Some additional thoughts:
Since the script is located in /usr/local/bin/, you could theoretically run it just before launching a game.
I haven’t tested this, but you could add something like this to Steam:
set-cpufreq-threshold.sh %command%

Create a simple script at /usr/local/bin.

sudo nano /usr/local/bin/cpu-freq-limit

Put this in and save the file.

#! /bin/bash
echo 95 > /sys/devices/system/cpu/intel_pstate/max_perf_pct

Make it executable.

sudo chmod +x /usr/local/bin/cpu-freq-limit

Now make the systemd service.

sudo nano /etc/systemd/system/cpu-freq-limit.service

[Unit]
Description=Set the CPU frequency at boot

[Service]
Type=oneshot
ExecStart=/usr/local/bin/cpu-freq-limit

[Install]
WantedBy=multi-user.target

Enable the system first and reboot.

sudo systemctl enable cpu-freq-limit.service

Or if you want to check it right away:

sudo systemctl start cpu-freq-limit.service

Choose the names you like for the script and the service.

I’ve tested it on my system and it works for me. I hope it works for you too.

That worked for me. Thanks.

1 Like

By the way ..

systemctl shouldnt require sudo in most cases.

And enable/start a unit can be combined into a single command;

systemctl enable cpu-freq-limit --now