关注了就能看到更多这么棒的文章哦~
Kernel support for processor undervolting
November 2, 2020
This article was contributed by Marta Rybczyńska
DeepL assisted translation
https://lwn.net/Articles/835594/
对处理器进行超频(将其运行在规定的最高频率之上以提高性能),这是很多读者都熟悉的操作。然而,有时需要反其道而行之,通过降低电压来降低处理器的工作功耗,以避免过热。最近,Jason Donenfeld 提交了一个简单的 patch,删除了内核在用户空间访问相关的特殊处理器寄存器时给出的 warning,允许在 x86 处理器上进行这种 "降压"动作。这个 patch 引起了很长的讨论,可能会引发一个新的内核接口,让用户来安全控制他们的处理器电压。
Voltage, frequency, and undervolting
现代处理器可以采用任意的频率和电压组合来运行,这是通过一个名为 dynamic frequency scaling(动态频率调整)的过程来动态调整的。不同的频率和电压组合自然会改变每秒可执行的指令数,也会有不同的功耗。我们也可以设置让 CPU 运行在它通常的工作频率范围之外,不过这样做时处理器可能会出现各种故障,比如某些指令偶尔出现错误,或者完全崩溃掉。
对于一些用户来说必须要能降低工作电压。因为他们的芯片(特别是最近的英特尔笔记本芯片),在高负荷运行时可能会过热。编译内核时就会出现这种情况。解决方案之一就是降低处理器的电压,使其在较低的电压下运行来降低功耗(从而降低发热)。由于频率没有降低,那么系统的性能仍然可以保持住。幸运的是,对于这些用户来说,有像 intel-undervolt 这样的工具,可以帮助他们实现这个目的。然而仍然有两个困难:该使用什么值,并没有文档记载,而且在不同的处理器上都有区别;并且每次工具改变这个设置时,内核都会打印一个很吓人的 warning。
在英特尔芯片系统中,电压设置是由 Model Specific Registers(MSRs)来控制的,它不仅仅可以用来改变电压,还是处理器特有的许多设置的接口。在 Linux 上,可以使用/dev/cpu/CPUID/msr 这个特殊文件来从用户空间访问 MSRs。然而,系统有可能通过 msr.allow_writes 这个启动选项来禁止 msr 的写操作,或者内核运行在 lockdown 模式下也是一样。在内核中对 MSR 的访问需要特殊的处理器指令,这是由 msr 的平台特有驱动程序来处理。当试图写入一个没有被明确列为安全的 MSR 寄存器时,此驱动会给出一个 warning。不过,如果允许写入操作的话,这个写 MSR 寄存器的动作仍然可以成功完成写入。
Donenfeld 的 patch 是在安全 MSR 寄存器列表中添加一项,从而消除这个 warning。这一项在 patch 中名为 MSR_IA32_OC_MAILBOX,它就可以用来改变处理器电压。这是 intel-undervolt 和其他类似工具在使用的寄存器。有兴趣的读者可以参考这份文档(https://github.com/mihic/linux-intel-undervolt ),了解这些寄存器是如何配置的。显然,这项工作是来自于少部分文档以及大量的反向工程,不断试错得到的。
Undervolting as an essential feature
Donenfeld 的补丁引发了许多讨论,主要是关于为什么需要从用户空间直接访问 MSR。Borislav Petkov 建议,最好通过 sysfs 提供对特定寄存器的访问并且控制好,取消直接写入寄存器的能力。他后来又进一步建议,在默认情况下,应该完全禁止用户空间对 MSRs 的访问。这引起了一些用户的反对,他们认为这种功能是必备功能。Donenfeld 解释说,他的系统需要降低电压才能保持持续工作,还有很多其他用户也有同样的情况。
嗯,这不是很好。这肯定会让许多人感到不安,他们依靠降低电压等相关的功能,才能使他们的笔记本电脑确保可以远程使用,特别是在近期的 14 纳米英特尔 CPU 的疯狂热设计的情况执行【……】,至少我的笔记本电脑会受到影响。
另一个例子来自 Sultan Alsawaf,他描述了他使用一些笔记本处理器的经验。在执行编译内核等任务时,这些处理器都有必要降低降低电压来执行,这样可以减少 22-30%的功耗,提高性能。他说:"我想指出,在英特尔最近的 14 纳米部件上,降低电压并不是为了压榨 SoC 的每一滴性能,而是真的必须得要降低"。Petkov 承认这种用法,并表示应该提供更好的支持。"在我看来,这种降压功能应该是内核的一部分,并且应该是自动进行的"。不过 Donenfeld 指出,自动实现可能会很难,因为正确的数值针对每个特定芯片都不一样,就是所谓的“silicon lottery”。
如果这个功能要在内核里支持的话,还需要回答一些其他问题。Donenfeld 问,应该在什么地方做这种操作?是放在内核还是用户空间?随后,Petkov 做出了强烈的回应,支持在内核中建立 "一个合适的接口"。他还提到了 tree 内的 x86_energy_perf_policy 工具,它使用的是另一个 MSR。他说一旦有真正的内核接口来实现该功能的话,这个 MSR 也可以从允许列表中删除。Donenfeld 同意这个目标,但他说在实践中可能很难实现,因为 MSRs 并不是都有公开的文档,而且含义也各有不同。
英特尔电源相关驱动的维护者 Srinivas Pandruvada 回应说,超频(可能也包含降压)并不是架构中提供的接口。也没有公开的文档说明要传递给这个特定 MSR 的命令值。他承诺会在公司内部寻找这些文档。他说,一个合适的 sysfs 接口必须要对传递进来的值进行检查,以防止用户的系统被破坏。
Toward a solution
这时,许多 x86 相关子系统的维护者 Andy Lutomirski 评论说,MSR 访问和 undervolting 是两个不同的话题。根据他的说法,只有在去掉访问限制的情况下,才应该允许 MSR 访问(并发出 warning),但是,降压功能应该由内核支持。不过他也指出了跟 lockdown 相关的一个潜在问题,这个功能可能会破坏系统的稳定,也许会让攻击者获得更高特权。他建议为这个功能单独设置一个 lockdown bit。Matthew Garrett 告诉大家有一种 Plundervolt 攻击(https://www.plundervolt.com/doc/plundervolt.pdf),它会采用降低电压的方式来破坏 Software Guard Extensions(SGX) enclaves(独立模块)。他还指出,如果有需要的话,sysfs 接口可以允许添加一个 SELinux 或 AppArmor 规则用来保护这个接口。
差不多这个时候,Pandruvada 带着 Intel 的答案回来了。原来正确的数值是来自于实验结果,英特尔的指南也警告了可能会有稳定性问题。他说,现在有内核代码使用了相关的 MSR(intel_turbo_max_3 driver),所以这个 MSR 寄存器的操作是公开的,但没有办法验证写入的命令是否安全。
关于将功能放在哪里的讨论持续了一段时间,直到 Dave Hansen 提议英特尔开发人员研究尽可能多型号的 MSR 的文档,并创建一个单独的驱动程序,也许最开始可以只针对一个型号的处理器。Petkov 同意了,讨论就此停止。
内核开发者们因此达成了一致意见,即降压功能对于一些用户来说是必不可少的,他们需要这个功能来使他们的 CPU 处于合理的散热条件下。提供这个功能的路线也已经制定出来了。一个障碍是可能缺乏官方文档,但看起来英特尔有意愿解决这个问题。这些工作还需要继续做,但我们可以期待很快会有新的接口出现。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~