Почему статус p-состояния MSR на ryzen не меняется?

Я пытаюсь обнаружить текущее p-состояние моего процессора. Я заметил, что статус p-состояния MSR (C001_0063) всегда возвращает 2 на мою ryzen систему 1700x, даже если ядро ​​явно не в этом состоянии. Я думаю, что он работал с начальным bios (v0403), с которым приходила моя материнская плата, но которая больше не доступна для загрузки 1.

Мой процессор разогнан 2 до 3,8 ГГц. Я использовал cpufreq-set для исправления скорости и cpufreq-info для проверки:

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).

Ниже приведена небольшая тестовая программа, которая показывает значение регистра для ядра # 0 вместе с эффективной скоростью относительно состояния P0. Требуется привилегии root. Для меня он постоянно печатает pstate: 2, speed: 99% под загрузкой.

#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);
    }
}

Аналогичный подход используется для работы с моим FX-8350. Что я делаю не так? Результаты тестов также приветствуются.

Информация о системе:

  • Cpu: ryzen 1700x, P0 и P1 - 3,8 ГГц 3 P2 - 2,2 ГГц
  • Материнская плата: Asus Prime X370-A, bios 3401
  • Операционная система: debian 7.1, kernel 4.9.0

Обновление: я изменил код, чтобы распечатать запрошенный pstate, и этот регистр меняется, как ожидалось. Фактическая скорость процессора также меняется, что подтверждается различными критериями.


1 По какой-то неясной причине функция резервного копирования bios отключена, поэтому я не смог сделать копию перед обновлением.

2 Я запускаю тест по умолчанию, когда получаю шанс.

3 Не знаю, почему он дублируется.

Ответ 1

Это может быть не связано, однако я слышал, что некоторые люди успешно заменили свои Ryzen 7s на AMD из-за состояний p, вызывающих проблемы со стабильностью системы в Unix или Unix-подобных системах. Хотя из комментариев по данному вопросу, особенно из форума ASrock, указывается на проблему с драйверами/прошивками, я читал в другом месте, что AMD может взять на себя некоторую ответственность за ранние партии чипов. Тем не менее из того, что я знаю о состояниях P и C, некоторые состояния запрашиваются операционной системой или средой вертуализации хоста. Так что патч можно сделать изнутри?