I am trying to detect the current p-state of my cpu. I have noticed that the p-state status MSR (C001_0063) always returns 2 on my ryzen 1700x system, even if the core is clearly not in that state. I think it used to work with the initial bios (v0403) that my motherboard came with, but that's not available for download anymore1.
My cpu is overclocked2 to 3.8GHz. I used cpufreq-set
to fix the speed and cpufreq-info
to verify:
analyzing CPU 0:
driver: acpi-cpufreq
CPUs which run at the same hardware frequency: 0
CPUs which need to have their frequency coordinated by software: 0
maximum transition latency: 4294.55 ms.
hardware limits: 2.20 GHz - 3.80 GHz
available frequency steps: 3.80 GHz, 2.20 GHz
available cpufreq governors: ondemand, conservative, performance, schedutil
current policy: frequency should be within 3.80 GHz and 3.80 GHz.
The governor "performance" may decide which speed to use
within this range.
current CPU frequency is 3.80 GHz (asserted by call to hardware).
Following is a little test program that shows the value of the register for core #0, along with the effective speed relative to P0 state. Needs root privileges. For me, it constantly prints pstate: 2, speed: 99%
under load.
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char** argv)
{
uint64_t aperf_old = 0;
uint64_t mperf_old = 0;
int fd;
fd = open("/dev/cpu/0/msr", O_RDONLY);
uint64_t pstate_limits;
pread(fd, &pstate_limits, sizeof(pstate_limits), 0xC0010061);
printf("pstate ranges: %d to %d\n", (int)(pstate_limits & 0x07), (int)((pstate_limits >> 4) & 0x07));
for(;;)
{
uint64_t pstate;
uint64_t pstate_req;
uint64_t aperf;
uint64_t mperf;
pread(fd, &pstate_req, sizeof(pstate_req), 0xC0010062);
pread(fd, &pstate, sizeof(pstate), 0xC0010063);
pread(fd, &aperf, sizeof(aperf), 0x000000E8);
pread(fd, &mperf, sizeof(mperf), 0x000000E7);
printf("pstate: %d, requested: %d", (int)(pstate & 0x07), (int)(pstate_req & 0x07));
if (mperf_old != 0 && mperf_old != mperf)
{
printf(", speed: %d%%", (int)(100 * (aperf - aperf_old) / (mperf - mperf_old)));
}
putchar('\n');
mperf_old = mperf;
aperf_old = aperf;
sleep(1);
}
}
A similar approach used to work on my FX-8350. What am I doing wrong? Test results also welcome.
System information:
Update: I have changed the code to print the requested pstate and that register is changing as expected. The actual cpu speed is changing too, as confirmed by various benchmarks.
1 For some obscure reason, the bios backup function is disabled, so I couldn't make a copy before updating.
2 I will run a test at defaults when I get a chance.
3 No idea why it's duplicated.
It may not be related, however I have heard that some people have successfully had their Ryzen 7s replaced by AMD, due to p states causing system stability issues in Unix or Unix like systems. Although from commentary on the matter, especially from ASrock forum points towards a driver/firmware issue, I have read elsewhere that AMD may be taking some responsibility with early batches of chips. That said from what I know of P and C states, some states are requested by the operating system, or host vertulisation environment. So a patch could be done from within?
User contributions licensed under CC BY-SA 3.0