- MSR modification may void your CPU's (or system board's) warranty. Proceed with care. I'm not responsible for any destruction caused by this article.
- MSR address (greatly) differs from CPU to CPU. Check your own CPU's MSR address using Intel's documentation.
- Only tested on Intel i7-8550U (Kaby Lake R).
- This article is translation of this article. If you can understand Korean, I recommend reading that article, not this.
On Windows, Intel XTU can be used for modifying turbo-boost parameter and TDP related settings. But on other OSes, there are no specific (user friendly) tools available. In this article, I will directly modify MSR (Model-Specific Registers) to achieve similar effect.
There are many CPU models. We call them by their friendly names - such as 'Core i7' - but this is not enough in this article. In fact, some CPUs are very different even if they are named after same friendly name. Some CPUs are named different, but they are actually same varient of other CPU. In Intel, they distinguish between CPU using CPU family and model. For example,
$ cat /proc/cpuinfo | less
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 142
model name : Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
stepping : 10
...
Note that /proc/cpuinfo returns CPU family and model by decimal.
In Linux, you will need msr-tools, and msr kernel module. You may want to insert kernel module automatically by adding appropriate configuration. (e.g., echo msr > /etc/modules-load.d/msr.conf
in Arch Linux)
You can read from MSR with rdmsr 0x(address)
and write to MSR with wrmsr 0x(address) 0x(value)
. When reading, you can specify bitmasks by -f 15:0
(from bit 0 to bit 15, in reverse).
My CPU has MSR_RAPL_POWER_UNIT
at address 606h
.
606H MSR_RAPL_POWER_UNIT (RO)
3:0 = Power unit (W) = 1/2^(decimal)W - def: 0.125W
12:8 = Energy unit (J) = 1/2^(decimal)J - def: 0.00006103515625J
19:16 = Time unit (sec) = 1/2^(decimal)sec - def: 0.0009765625sec
These units are needed to modify existing values.
Now the fun part begins, MSR_PKG_POWER_LIMIT
has package power limit variables.
610H MSR_PKG_POWER_LIMIT (RW)
14:0 = Pkg power limit = Powerunit * decimal
15:15 = Pkg power enabled (bool)
16:16 = Pkg clamping limit (bool)
23:17 = Pkg power limit time window = 2^(21:17 bit) * (1.0 + (23:22 bit)/4.0 ) * Timeunit
46:32 = Pkg power limit 2 = Powerunit * decimal
47:47 = Pkg power 2 enabled (bool)
48:48 = Pkg clamping limit 2 (bool)
55:49 = Pkg power limit time window = 2^(53:49 bit) * (1.0 + (55:54 bit)/4.0 ) * Timeunit
63:63 = MSR lock (bool)
If bit 63 is 0, those values can be changed by writing to 0x610 register. You may change package power limit to higher TDP, and prolong limit time window to increase your processor's performance (if you are not throttled by thermal throttling).
If MSR_PLATFORM_INFO[28]
is 1, you can also change turbo boost limit variable.
CEH MSR_PLATFORM_INFO
15:8 = Maximum non-turbo (RO) bool
28 = Programmable ratio limit for turbo (RO) bool
29 = Programmable TDP limit for turbo (RO) bool
30 = Programmable TJ offset (RO) bool
1ADH MSR_TURBO_RATIO_LIMIT (RO if MSR_PLATFORM_INFO[28]=0, else RW)
7:0 = Ratio 1C
15:8 = Ratio 2C
23:16 = Ratio 3C
31:24 = Ratio 4C
Using above information, I could change MSR on my processor - i7-8550U.
Since this processor is limited to 37 boost ratio when all 4 cores are being used, I changed limitation to 40. Also, I changed 23W limit to 25W with longer (1073741824 seconds) boost duration.
From
610H
42819800dd80b8h
00000000 01000010 10000001 10011000
00000000 11011101 10000000 10111000
14:0 = Pkg power limit = 10111000b (184d, b8h) = 23
15:15 = Pkg power enabled (bool) = 1b
16:16 = Pkg clamping limit (bool) = 1b
23:17 = Pkg power limit time window = 11b(3d) 01110b(14d) = 2^14*(1+3/4)*(1/2)^10=28
46:32 = Pkg power limit 2 = 110011000b (408d, 198h) = 51
47:47 = Pkg power 2 enabled (bool) = 1b
48:48 = Pkg clamping limit 2 (bool) = 0b
55:49 = Pkg power limit time window = 01b(1d) 00001b(1d) = 2^1*(1+1/4)*(1/2)^10=0.00244140625
63:63 = MSR lock (bool) = 0b
1ADH
25252828h
7:0 = Ratio 1C = 40
15:8 = Ratio 2C = 40
23:16 = Ratio 3C = 37
31:24 = Ratio 4C = 37
To
610H
42819800FC80C8h
00000000 01000010 10000001 10011000
00000000 11111100 10000000 11001000
14:0 = Pkg power limit = 11001000b (200d, c8h) = 25
15:15 = Pkg power enabled (bool) = 1b
16:16 = Pkg clamping limit (bool) = 0b
23:17 = Pkg power limit time window = 11b(3d) 11110b(30d) = 2^30*(1+3/4)*(1/2)^10=1073741824
46:32 = Pkg power limit 2 = 110011000b (408d, 198h) = 51
47:47 = Pkg power 2 enabled (bool) = 1b
48:48 = Pkg clamping limit 2 (bool) = 0b
55:49 = Pkg power limit time window = 01b(1d) 00001b(1d) = 2^1*(1+1/4)*(1/2)^10=0.00244140625
63:63 = MSR lock (bool) = 0b
1ADH
28282828h
7:0 = Ratio 1C = 40
15:8 = Ratio 2C = 40
23:16 = Ratio 3C = 40
31:24 = Ratio 4C = 40
turbostat reported updated TDP limit and duration, and changed turbo boost ratio. I could not test real life performance difference, since my processor is heavily throttled by thermal throttling even at 15W TDP.
EDIT 2
I think it was resetting because of thermal throttling, Full Turbo made the CPU reach 98°C in an instant. So I did limit the turbo frequency as well. To limit to 3.0 GHz, I run
wrmsr 0x01AD 0x1e1e1e1e
. I get 80°C to 85°C on sustained 4-cores 100% load at 3.0 GHz without a cooling pad, which I think is pretty good, I might lower the max Turbo frequency further to 2.7 GHz if I plan on letting it run for several hours.So, for an "Long Term Performance" setup with my i7-8550U, this is what I had to do (run as root):
On a 4-cores/8-threads benchmark, I get 27% to 60% performance increase depending on the specifics of the computation. Not too bad!
EDIT
Turns out it still crashes using those settings, but only on AC, not on the battery... Any help would be greatly appreciated.
I can temporarily make everything work on AC by doing:
But the MSR value get changed back to
0x42016000dc8040
after a while, sometimes0x43816000dd8024
. I really don't know what's happening really.Original post follows
I have a laptop with a i7-8550U with 44W TDP that throtlles quite a lot on linux by defaults. Running some openmp code with 8 threads, it downclocks to 1.8 to 2 GHz in a matter of seconds eventhough the temperature is around 56°C. Note that I've put some thermal pads between the CPU heatsink and the chassis of the laptop to better dissipate heat. On windows the throttling is much less of a problem.Using your gist as a guideline I've managed to drastically increase the performance on linux, by about 25%. Now the clock decreases slowly and stabilizes at 2.6 to 2.7 GHz with a temperature around 68°C. This is much more similar to what I get on Windows.I simply increased the #1 window. When I tried to disable the clamping like you did, my computer crashed (probably reaching limit the temperature 100°C). For reference I did this (original 0x610 value is 0x42016000dc8160):It's still unclear to me what the devmem2 command is used for. And why 00DD should be kept regardless of the MSR stuff, I figured that out through trial and errors. Any explanation would be welcome.And, in case anyone wants to mess with MSR in python, I'm sharing a few convenient functions I coded for that project:e.g.
get_power_limits(0x42816000dd8160,0xa0e03)
yields