Linux 是不是将 x86 CPU 的 PCID 功能用于 TLB?如果不是,为啥?

Posted

技术标签:

【中文标题】Linux 是不是将 x86 CPU 的 PCID 功能用于 TLB?如果不是,为啥?【英文标题】:Does Linux use x86 CPU's PCID feature for TLB? If not, why?Linux 是否将 x86 CPU 的 PCID 功能用于 TLB?如果不是,为什么? 【发布时间】:2013-12-07 22:47:38 【问题描述】:

我写了一个内核模块来检查 CR4.PCIDE,它没有设置。为什么 Linux 不使用这样的特性来减少由于 TLB 失效和缓存污染导致的性能下降?

【问题讨论】:

forum.osdev.org/viewtopic.php?f=1&t=29935 2017 年的注意事项:自 4.14 以来,Linux 确实使用它,但方式有点不寻常。 See details here,段落1.8. Faster TBL flushing with PCID 刚找到'1.10.上面 Hi-Angel 答案中带有 PCID 的更长寿的 TLB 条目,但它非常有用。 【参考方案1】:

更新:由于 2017 年底和 2018 年初的Meltdown and Spectre attacks,这在 4.15 时间范围内发生了变化。有关详细信息,请参阅 the other answer。

注意:我不是 Linux 开发人员

对于英特尔的“进程上下文标识符”,有 4096 个 ID 的限制。这意味着当有超过 4096 个进程时,您需要管理它们(例如,可能会做一个“最近最少使用”的事情,以便如果需要执行当前没有 ID 的进程,那么 ID 取自一些其他过程并重复使用)。

涉及到的另一件事是多 CPU 系统上的“TLB 击落”。这些可能有点贵,所以人们会采取一些技巧来避免它们。例如,如果一个进程只有一个线程,那么它只能在一个 CPU 上运行,并且您知道没有必要向其他 CPU 发送 IPI(中断它们并要求它们执行“TLB 击落”)。一旦开始使用 PCID,您就无法确定其他 CPU 是否仍然没有 TLB 条目,并且无法使用这些技巧来避免“TLB 击落”。这也意味着(理论上,对于实施不当的 PCID 支持)您从 PCID 获得的性能可能低于由于不可避免的 TLB 击落和 ID 管理开销而损失的性能,从而导致净损失。

我要说的主要是添加对 PCID 的支持有点复杂(这不像您可以在 CR4 中设置一个标志而忘记它)。您必须进行一些研究(实验、原型、基准测试)以确定最有效的实施方式。对于大型/复杂/旧内核(如 Linux),它会更加复杂,因为您必须小心不要意外破坏其他东西。另一件事是这个功能相对较新(如果我没记错的话,它只存在了几年)并且不被很多 CPU 支持(例如任何更旧的 CPU,以及来自 AMD 的任何东西)。

基本上,我认为它归结为“时间与收益”(或者,没有足够的时间在有限数量的 CPU 上进行小的性能改进)。

【讨论】:

16个ID限制从何而来?抱歉,我没听懂。 我记错了(不是 16 个 ID)——我查了一下,实际上有 4096 个 ID(因为它是 CR3 中的 12 位字段)。我更改/更正了我的答案。 你应该总结第一句话:no :-) 请注意,我认为没有证据表明 PCID 补丁与 Spectre 或 Meltdown 攻击必然相关。很自然,最终 PCID 将用于更有效的上下文切换,并且补丁的出现比 Spectre 和 Meltdown 的大推动要早得多。此外,将应用 Meltdown 修复 (KPTI) 的内核明显大于支持 PCID 的内核。【参考方案2】:

是的!最新版本的 Linux 内核支持 PCID。 在提出此问题时,此支持不存在,但已在 2017 年底添加,从 4.14 kernel 开始。可以关注一些原版补丁讨论in this LKML chain。

该更改实际上并没有为每个进程关联一个唯一的 PCID,因为数量有限,或者尝试将它们分配给经常使用的基础,而是为每个 CPU 使用一个 PCID 缓存,以便给定的多个正在运行的进程CPU 很可能能够使用 PCID 机制来避免 TLB 刷新开销。

这在最近变得更加重要,因为在哪里找到了a series of vulnerabilities,它允许非特权用户代码读取内核内存,KPTI patches 是针对其部署的。这些补丁可能会对性能产生重大影响,因为用户级 TLB 条目可能在任何内核调用时失效。使用 PCID 支持,影响会降低,因为用户级 TLB 条目被保留。


在发布的内核中不提供 PCID 支持时,可以在下面找到此答案的旧版本:

还没有,但似乎正在酝酿中。请参阅 LKML 上以 around here 开头的线程。特别是,针对跨核心 TLB 击落问题提出了一些解决方案,其中包括:

如果在收到针对非当前 PCID 的 TLB 击落时,我们只需 刷新该 PCID 的所有条目并从 mm 中移除 CPU cpu_vm_mask_var,我们永远不会收到超过一个击落 IPI 一个非当前的mm,但我们仍然会得到TLB长寿的好处 在处理例如。任务轮流运行的管道工作负载 同一个 CPU。

您还可以从该线程中收集到地址空间标识符长期以来一直用于其他 Linux 体系结构。

【讨论】:

以上是关于Linux 是不是将 x86 CPU 的 PCID 功能用于 TLB?如果不是,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

x86 CPU架构

Android目前支持那些CPU的移植?

在 Linux 上调用哪个函数来唤醒 cpu

循序渐进学习Linux--第二天更新

AMD 授权,中国开始生产自主设计 x86 CPU;JDK 11 将引入低延迟 GC

Linux operation 23Win 10 64位(X86 架构CPU)安装ARM架构的虚拟机(银河麒麟高级服务器操作系统 V10)