【问题标题】:Who performs the TLB shootdown?谁执行 TLB 击落?
【发布时间】:2018-10-19 18:29:42
【问题描述】:

我读过这个SO question 描述什么是 TLB 击落。我试图了解这是由内核还是处理器或两者执行的操作?

我的问题是:-

  1. 上下文切换时是否会发生 TLB 击落?我认为不会,因为需要能够在多处理器 CPU 上同时执行多个进程。这个假设正确吗?
  2. TLB 击落的具体时间是什么时候?
  3. 谁执行实际的 TLB 击落?是内核(如果是,我在哪里可以找到执行刷新的代码?)还是 CPU(如果是,是什么触发动作)还是两者兼有(内核执行导致中断的指令,这依次导致 CPU 执行 TLB 击落)

【问题讨论】:

    标签: linux x86 kernel tlb


    【解决方案1】:

    x86 TLB 不跨内核共享,并且在硬件级别彼此之间不同步。
    是操作系统指示处理器刷新其 TLB。
    指示“当前”处理器相当于调用一个函数,指示另一个处理器相当于发出IPI

    术语“TLB 击落”明确指这种(甚至比正常情况更严重)昂贵的情况,即为了保持系统一致性,操作系统必须告诉其他处理器使其 TLB 无效,以达到特定处理器的相同映射.

    我认为只有在新映射影响某些共享内存时才需要这样做,否则每个处理器正在执行进程的不同实例,每个实例都有其映射。

    在上下文切换期间,TLB 被刷新以删除旧映射,这必须独立于运行计划程序的最后一个处理器来完成。
    由于处理器正在刷新自己的 TLB,因此这不是 TLB 击落。

    处理器之间必须始终保持一致的共享区域可以是:内核页面、内存映射 IO、共享内存映射文件。

    指令invlpginvpcid的执行、移动到cr0cr3(包括在硬件任务切换期间)或cr4和VMX转换,都使TLB无效。
    有关确切的粒度和语义,请参阅Intel Manual 3 的第 4.10.4 节。

    【讨论】:

      【解决方案2】:

      TLB 击落的确切时间是什么时候?

      当操作系统或管理程序请求它时发生。

      在 ISA 级别,某些操作可以执行 TLB 击落(参见 Intel 手册 V3 4.10.4 和 AMD 手册 V2 5.5.2),从而使一个或多个本地或远程 TLB 缓存中的一个或多个 TLB 条目无效(那些同一 CPU 的其他逻辑内核和所有其他类型的具有 TLB 并共享相同物理内存地址空间的处理器)。

      还要注意,任何分页结构条目都可以被缓存,即使它还没有被任何退休指令访问。这可能是由于推测执行或 MMU 预取而发生的。因此,一般来说,任何条目都可以随时被缓存或失效。当然,也有特定的保证,以便 MMU 缓存可以被管理并与内存中的分页结构保持一致。

      谁执行实际的 TLB 击落?是内核吗(如果是,在哪里 我可以找到执行刷新的代码吗?)还是 CPU(如果 那么,是什么触发了动作)还是两者兼而有之(内核执行 导致中断的指令,进而导致 CPU 执行 TLB 击落)

      正如我之前所说,CPU 本身可以随时使任何条目无效。此外,当前权限级别(CPL)=0的软件可以执行任何与TLB管理相关的操作。

      Linux内核中TLB失效简介

      Linux 内核定义了依赖于体系结构的 TLB 无效函数 (/arch/x86/mm/tlb.c) 和依赖于体系结构的函数 (/arch/x86/include/asm/tlbflush.h)。这是因为不同的架构为管理 TLB 提供了截然不同的机制。要查看 Linux 内核何时执行 TLB 失效的一些示例,请参阅tlb_flush_reason 枚举(cmets 是我的):

      enum tlb_flush_reason {
      
          // The memory descriptor structure mm of the current process is about to change.
          // This occurs when switching between threads of different processes.
          // Note that when mm changes, the ASID changes as well (CR3[11:0]).
          // I'd rather not discuss when context switches occur because it's a whole different topic.
          // TLB shootdown only occurs for the current logical core.
          // The kernel sometimes can optimize away TLB flushes on a process-context switch.
          TLB_FLUSH_ON_TASK_SWITCH,
      
          // Another logical core has sent a request to the current logical core
          // to perform a TLB shootdown on its TLB caches.
          // This occurs due to a KVM hypercall. See TLB_REMOTE_SEND_IPI.
          TLB_REMOTE_SHOOTDOWN,
      
          // Occurs when one or more pages have been recently unmapped.
          // Affects only the local TLBs.
          TLB_LOCAL_SHOOTDOWN,
      
          // This occurs when making changes to the paging structures.
          // Affects only the local TLBs.
          TLB_LOCAL_MM_SHOOTDOWN,
      
          // Occurs when the current logical core uses a KVM hypercall to request
          // from other logical cores to perform TLB shootdowns on their respective TLBs.
          TLB_REMOTE_SEND_IPI,
      
          // This equals to the number of reasons. Currently not used.
          NR_TLB_FLUSH_REASONS,
      };
      

      在其他情况下内核会刷新 TLB。很难列出完整的清单,而且我认为没有人列出过这样的清单。

      Linux 内核实现了惰性 TLB 刷新技术。其基本思想是,当修改进程的分页结构时,内核会尝试将 TLB 击落延迟到该进程中的线程即将被安排在使用模式下执行的时间点。

      Linux 内核当前使用以下四种方法之一在需要时刷新与当前逻辑内核关联的 TLB:

      • 将 CR3 的当前值写入 CR3。虽然这不会更改 CR3 中的值,但它会指示逻辑核心刷新所有与 CR3 中具有相同 PCID 的非全局 TLB 条目。
      • 禁用 CR4.PGE,然后将 CR4 的当前值写入 CR4,然后重新启用 CR4.PGE。这具有刷新所有 PCID 和全局条目的所有 TLB 条目的效果。如果支持 INVPCID,则不使用此方法。
      • 使用 INVPCID 指令类型 0 使给定 PCID 和虚拟地址的 TLB 条目无效。
      • 使用 INVPCID 指令类型 2 使所有 TLB 条目(包括全局变量和所有 PCID)无效。

      目前没有使用其他类型的INVPCID。

      相关:Do the terms tlb shootdown and tlb flush refer to the same thing.


      除了软件启动的 TLB 条目失效之外,英特尔手册第 3 卷第 4.10.2.2 节针对 P6 微架构和大多数更新的微架构:

      处理器不需要实现任何 TLB。确实实现的处理器 TLB 可以随时使任何 TLB 条目无效。软件不应该 依赖于 TLB 的存在或 TLB 条目的保留。

      据我所知,AMD 手册中没有这样的声明。但也没有提供关于 TLB 整体保留的保证,因此我们可以对 AMD 处理器得出相同的结论。

      【讨论】:

      • :/arch/x86/mm/tlb.c 和 /arch/x86/include/asm/tlbflush.h 都是 x86 特定的。我不知道您为什么将 /arch/x86/mm/tlb.c 作为“架构独立”代码的示例。
      • 小问题:我不会说“[TLB 击落] 随时可能发生,即使操作系统或管理程序没有请求它。”我会称其为 TLB 无效或未命中,或者可能是 TLB 填充,它获得的值不同于 (a) 其他 TLB 中相同虚拟地址的 TLB 条目或 (b) 在其他时间在当前 TLB 中的转换。 // TLB 击落是一个 SW 构造或算法,仅在硬件手册中提及以说明 SW 是如何做到的。至少在您添加 TLB 击落指令之前(例如 ARMv8.4-A TLBI 跨一致性域广播。
      • P6 添加了“SW 不应依赖 TLB 的存在或 TLB 条目的保留”,因为像 P5 这样的早期处理器确实保证了保留,以及最小的 TLB 容量/关联性(没有推测性的 TLB 未命中)。这允许 SW 在没有共同虚拟地址的虚拟地址空间之间进行切换(因为保留允许您短暂使用陈旧的 TLB 条目),而由于 P6 SW 这样做是鼓励至少一页,映射执行 CR3 更改的代码,标识映射在新旧虚拟地址空间中。 // 让我有点难过。
      猜你喜欢
      • 2011-04-14
      • 1970-01-01
      • 1970-01-01
      • 2017-12-29
      • 2020-07-04
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 2011-11-22
      相关资源
      最近更新 更多