首页 > 解决方案 > 如何从 EFI 棒更改 msr 0x199?

问题描述

我有一个没有电池的macbookpro11,3。取出电池后,固件会将 CPU 调至半速。在 Windows 中,我可以使用 Throttlestop 覆盖它以关闭 BD PROCHOT 并将乘数设置为 25。我想从 EFI 执行此操作,以便引导和更新以正常速度运行。

基于更新 0x3a 寄存器的rEFInd的源代码,我编写了这个程序,但是当 BD PROCHOT 在启动到 Windows 后被正确禁用时,乘数不是。

#include "../include/tiano_includes.h"
static VOID DisablePROCHOT(VOID)
{
    UINT32 msr = 0x1FC;
    UINT32 low_bits = 0, high_bits = 0;

    __asm__ volatile ("rdmsr" : "=a" (low_bits), "=d" (high_bits) : "c" (msr));

    // lowest bit is BD PROCHOT 
    low_bits &= ~(1 << 0);

    __asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits));
} // VOID DisablePROCHOT()

static VOID SetMultiplier25(VOID)
{
    UINT32 msr = 0x199;
    UINT32 low_bits = 0, high_bits = 0;

    __asm__ volatile ("rdmsr" : "=a" (low_bits), "=d" (high_bits) : "c" (msr));

    // second lowest byte is multiplier
    // 25 is .... xxxxxxxx 00011001 xxxxxxxx 
    low_bits |= 1 << 8;
    low_bits &= ~(1 << 9);
    low_bits &= ~(1 << 10);
    low_bits |= 1 << 11;
    low_bits |= 1 << 12;
    low_bits &= ~(1 << 13);
    low_bits &= ~(1 << 14);
    low_bits &= ~(1 << 15);

    __asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits));
} // VOID SetMultiplier25()

EFI_STATUS
EFIAPI
efi_main (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  DisablePROCHOT();
  SetMultiplier25();

  return EFI_SUCCESS;
}

从 EFI 读取带有 rdmsr 的寄存器似乎显示两者都设置正确,但是当启动到 Windows 时,当 0x1FC 的位 0 正确设置为关闭时,存储在 0x199 中的乘数与默认值 12 相比没有变化,而我预计它是 25。

默认值

这些是标准启动到 Windows 后的值(来自 RWEverything)

标准引导

调用程序后的结果

在调用 Windows 引导加载程序bootmgfw.efi之前从 EFI shell 调用程序

0x1FC 已更新,0x199 未更新。

调用程序后开机

在 Windows 中使用 RWEverything 更新 0x199 会正确更改乘数,因此我相当确定它是正确的寄存器。

由于这是我的第一个 EFI(或 C)程序,我可能忽略了一些琐碎的事情。

标签: cuefimsrrefind

解决方案


每次通过循环时,您都必须创建一个循环并更改处理器亲和性。然后每次通过循环为每个线程(CPU1、CPU2、CPU3、CPU4)执行一次 wrmsr。在 Windows 中,您使用此功能。

https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-setthreadaffinitymask

启动后,Windows 会立即更改 MSR 0x199 中的值,因此在启动后查看 MSR 0x199 中的值并不能证明任何事情。

为了简化事情,您可以在 SetMultiplier 中执行此操作,

低位 = 0x1900


推荐阅读