【问题标题】:Why each logical CPU has it's own CR3 register in case of multithreading?在多线程的情况下,为什么每个逻辑 CPU 都有自己的 CR3 寄存器?
【发布时间】:2018-04-17 09:18:47
【问题描述】:

当我们的 CPU 支持某种形式的多线程时,每个逻辑 CPU 都有自己的一组寄存器(至少),包括一个 CR3 寄存器。

由于我们在执行不同线程时处理同一进程的虚拟地址空间,并且从未发生上下文切换(切换同一进程的线程时 TLB 缓存都不会失效),为什么我们需要一个 CR3 寄存器来指向逻辑CPU中的页表和页目录?

这个值不总是和物理CPU的CR3里的值一样吗?

【问题讨论】:

  • 处理器不只是执行来自一个进程的代码。操作系统调度线程。
  • @HansPassant 那么他们之间的TLB是如何共享的呢?为什么它没有失效?
  • 不共享,每个核心都有自己的TLB。
  • 那么当来自不同进程的两个线程同时运行时,内存转换是如何发生的呢?
  • 它们只有在不同内核上运行时才能真正同时运行。每个核心都有自己的 CR3 和自己的 TLB,没什么特别的。

标签: multithreading x86 cpu


【解决方案1】:

由于我们在执行不同线程时正在处理同一进程的虚拟地址空间

这并不是 HT 的全部能力。我认为您将“硬件线程”(执行上下文/逻辑核心)与“软件线程”混淆了。

两个逻辑核心在一个物理核心上运行,一个物理 iTLB / dTLB / L2TLB。 逻辑核心非常独立,不必从同一进程运行线程。

这是SMT 设计(如 Intel 的 HT)中的理想属性:如果操作系统必须小心避免将具有不同页表的线程调度到同一物理内核的不同逻辑内核上,则需要内核之间更多的同步。


不同进程的两个线程(具有单独的 CR3 页表)可以共享一个 TLB,因为条目使用 PCID(进程上下文 ID)进行标记。 IIRC,硬件虚拟化也使用类似(或相同?)标记,以避免在 VM 退出或在来宾之间切换时需要 TLB 刷新。

操作系统可以设置一个 PCID(CR3 的低 12 位)以避免在上下文切换时需要刷新 TLB,并且作为奖励,可以让 2 个进程同时使用 TLB。 Does Linux use x86 CPU's PCID feature for TLB? If not, why?(据此,Linux 一般不使用 PCID,但我认为它用于 HT。)

嗯,我不确定我的细节是否完全正确,但在物理上存在某种类型的 TLB 条目标记,即使两个逻辑核心具有不同的 CR3 也可以将它们分开。


根据an Intel forum thread,SnB 系列 CPU 静态划分 iTLB(因此每个逻辑核心获得一半的条目)。这会自动解决任何共享问题。

dTLB 和 L2TLB 是竞争性共享的,因此它们确实需要标记。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-09
    • 2015-05-03
    • 2017-04-01
    • 2020-09-04
    • 2013-08-23
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    相关资源
    最近更新 更多