Вопрос о регистре MSR 0xCE для определения частоты RDTSC

Тема в разделе "WASM.NT.KERNEL", создана пользователем zky02, 26 апр 2024.

  1. zky02

    zky02 New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2024
    Сообщения:
    20
    Здравствуйте! У меня возник вопрос касательно использования модельно-специфичного регистра (MSR) с индексом 0xCE для получения частоты процессора, которую я хотел бы использовать для корректировки результатов, получаемых с помощью инструкции RDTSC. Я использую следующий код для чтения частоты:

    Код (Text):
    1. long long freq = ((0xFF & (__readmsr(0xCE) >> 8)) * 100000000LL);

    В этом коде я считываю значение из MSR, сдвигаю его на 8 бит вправо, применяю маску 0xFF для извлечения определенного байта и умножаю результат на 100000000, чтобы преобразовать его в герцы. Могу ли я использовать эту частоту для точного измерения времени с помощью RDTSC? Интересует ваше мнение о корректности такого подхода и возможные ограничения на использование этой частоты.
     
  2. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    В современных цп частота - параметр не постоянный, и плавает она в широком диапазоне.
    Например среди общего пула ядер есть: Р-мощные + E-слабые, и работают они на разных частотах. Когда Р-ядро загружено, множитель его частоты увеличивается, а при простое/сне падает в дефолт. Как результат, потребляемые ватты расходуются более эффективно (см.CPU-Z).

    А MSR.0xCE - это просто invariant счётчик, который не имеет отношения к текущей частоте процессора, а стучит с постоянным шагом даже когда cpu уходит в сон. Если вы пишете профайлер, имхо лучше считать через QueryPerformanceCounter(), и делить его показания на QueryPerformanceFrequency(). QPC сидит на аппаратном таймере HPET с постоянной частотой ~14 МГц (если он недоступен, то ACPI 3.579 МГц), что позволит чекать время вплоть до наносек.
     
    Mikl___ нравится это.
  3. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    00.jpg
    Во вложении asm/rc/ico/cur/exe-файлы
     

    Вложения:

    • tut_15.zip
      Размер файла:
      11,3 КБ
      Просмотров:
      107
    k3rnl и Marylin нравится это.
  4. k3rnl

    k3rnl Member

    Публикаций:
    0
    Регистрация:
    28 янв 2021
    Сообщения:
    53
    syscall явно работает как-то не так :grin:
    1.png
     
    Mikl___ нравится это.
  5. zky02

    zky02 New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2024
    Сообщения:
    20
    Вот ещё два метода для считывания частоты процессора
    Код (C++):
    1. void getcpufreqeuncyhz() {
    2.    HAL_PROCESSOR_SPEED_INFORMATION ProcessorSpeedInfo; // Информация о скорости процессора
    3.    NTSTATUS status; // Статус
    4.    ULONG Size; // Размер
    5.    status = HalQuerySystemInformation(HalProcessorSpeedInformation,
    6.      sizeof(ProcessorSpeedInfo),
    7.      &ProcessorSpeedInfo,
    8.      &Size);
    9.    if (NT_SUCCESS(status)) {
    10.        DbgPrint("Скорость CPU: %llu Гц\n",
    11.       (ULONG64)ProcessorSpeedInfo.ProcessorSpeed * 1000000ull);
    12.      }
    13. }
    14. static inline uint64_t GetFreq(void) {
    15.    // Кэшируем ответ, чтобы многократные вызовы не приводили к замедлению
    16.    static uint64_t tsc_freq = 0;
    17.    volatile uint64_t* hypervisor_shared_page = NULL; // Общая страница гипервизора
    18.    unsigned int size = 0; // Размер
    19.    // SystemHypervisorSharedPageInformation == 0xc5
    20.    int result = ZwQuerySystemInformation(SystemHypervisorSharedPageInformation,
    21. (void*)&hypervisor_shared_page, sizeof(hypervisor_shared_page), (PULONG)&size);
    22.    // успех
    23.    if (size == sizeof(hypervisor_shared_page) && result >= 0) {
    24.      // по документации ReferenceTime = ((VirtualTsc * TscScale) >> 64)
    25.      // устанавливаем ReferenceTime = 10000000 = 1 секунда при 10 МГц, решаем для VirtualTsc
    26.      tsc_freq = (10000000ull << 32) / (hypervisor_shared_page[1] >> 32);
    27.      DbgPrint("Скорость CPU: %llu Гц\n", tsc_freq);
    28.      return 0; // Используем 0 вместо NULL для возвращения числового значения
    29.    }
    30. }
     
    Mikl___ нравится это.
  6. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    zky02,
    не могли бы Вы еще и работоспособный экзешник прицепить? :dash1:
     
  7. alex_dz

    alex_dz Active Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    449
  8. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    Mikl___, это вроде в ядре Hal, для процессоров с поддержкой VT-x, и только на системах Win10+
     
    Mikl___ нравится это.
  9. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    alex_dz, k3rnl,
    Код (ASM):
    1. PROCESSOR_POWER_INFORMATION STRUC
    2.       Number ULONG ?;номер процессора <-- наверное ошибка здесь
    3.       MaxMhz ULONG ? ;Максимальная указанная тактовая частота системного процессора
    4. ;в мегагерцах.
    5.       CurrentMhz ULONG ? ;Тактовая частота процессора в мегагерцах.
    6. ;Это число является максимальной указанной тактовой частотой процессора,
    7. ;умноженной на текущее регулирование процессора
    8.       MhzLimit ULONG ?;Ограничение на тактовой частоте процессора в мегагерцах.
    9. ;Это число является максимальной указанной тактовой частотой процессора,
    10. ;умноженной на текущий предел регулирования температуры процессора.
    11.       MaxIdleState ULONG ?;Максимальное состояние простоя этого процессора
    12.       CurrentIdleState ULONG ?;Текущее состояние простоя этого процессора
    13. PROCESSOR_POWER_INFORMATION ENDS
    14. SYSTEM_INFO STRUC
    15.     UNION
    16. dwOemId DWORD ?
    17. STRUC  
    18. wProcessorArchitecture WORD ?
    19. wReserved WORD ?
    20. ENDS          
    21.     ENDS
    22. dwPageSize DWORD ?
    23. ; DWORD ?
    24. lpMinimumApplicationAddress LPVOID ?
    25. lpMaximumApplicationAddress LPVOID ?
    26. dwActiveProcessorMask DWORD_PTR ?
    27. dwNumberOfProcessors DWORD ?
    28. dwProcessorType DWORD ?
    29. dwAllocationGranularity DWORD ?
    30. wProcessorLevel WORD ?
    31. wProcessorRevision WORD ?
    32. SYSTEM_INFO ENDS
    33.  
    34. local si_:SYSTEM_INFO
    35.  
    36.        lea ecx,si_
    37.        invoke GetSystemInfo
    38.        mov eax,si_+SYSTEM_INFO.dwNumberOfProcessors
    39.        imul eax,(sizeof PROCESSOR_POWER_INFORMATION)
    40.        sub esp,eax
    41.        mov r9d,esp;ppi
    42.        sub esp,30h
    43.        mov [rsp+20h],rax;(sizeof PROCESSOR_POWER_INFORMATION)*4
    44.        xor edx,edx
    45.        xor r8d,r8d
    46.        push rax
    47.        mov r10d,ProcessorInformation;rcx
    48.        mov eax,5Ch;<-- возможно ошибка здесь ?
    49.        syscall
    50.        add esp,38h
    51.        mov eax,[rsp+PROCESSOR_POWER_INFORMATION.MaxMhz]
    52.        xor edx,edx
    53.        mov ecx,50
    54.        div ecx
    55.        mov Freq,rax
    56.  
     
    Marylin и k3rnl нравится это.
  10. zky02

    zky02 New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2024
    Сообщения:
    20
    Здесь методы частоты TSC в ядре требуют отключения DSE для загрузки драйвера.

    [​IMG]

    [​IMG]

    bcdedit /set {globalsettings} advancedoptions true
    bcdedit /set {default} bootmenupolicy legacy

    Отключить принудительную проверку подписи драйверов
     

    Вложения:

  11. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    zky02, какой процессор у вас?
     
  12. zky02

    zky02 New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2024
    Сообщения:
    20
    i7 10700kf
     
    Marylin нравится это.
  13. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    да.. номера сисколов жёстко привязаны к системе, поэтому подход сомнительный.
    а ты на какой системе проводил тесты, что eax=5ch возвращает у тебя гуд?
    например у меня на Win7 эта функция NtQuerySystemInformation() = 33h,
    а на Win10 уже = 15Bh (можно проверить в IDA), плюс ещё чекается какое-то поле в peb.

    33h.png 15bh.png
     
  14. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    Marylin,
    а у меня i3-3210 и Win10 Pro версия 21H1
     
  15. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    ошибочка вышла..
    это оказывается не QuerySysInfo(), а NtPowerInformation()
    но и этом случае на моей бесятке eax=5fh

    Код (ASM):
    1. ;//------ Win-7 --------------
    2. 0: kd> uf NtPowerInformation
    3. 00000000`76f8c120   4c8bd1          mov     r10, rcx
    4. 00000000`76f8c123   b85c000000      mov     eax, 5Ch
    5. 00000000`76f8c128   0f05            syscall
    6. 00000000`76f8c12a   c3              ret
    7.  
    8. ;//------ Win-10 -------------
    9. .text:000000018009D2B0              mov     r10, rcx   ; NtPowerInformation
    10. .text:000000018009D2B3              mov     eax, 5Fh
    11. .text:000000018009D2B8              test    byte ptr ds:7FFE0308h, 1
    12. .text:000000018009D2C0              jnz     short loc_18009D2C5
    13. .text:000000018009D2C2              syscall
    14. .text:000000018009D2C4              retn
    15.