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 失效函数 (/arch/x86/mm/tlb.c) 和与体系结构相关的函数 (/arch/x86/include/asm/tlbflush.h)。这是因为不同的架构提供了截然不同的 TLB 管理机制。要查看 Linux 内核何时执行 TLB 失效的一些示例,请参阅tlb_flush_reason枚举(评论是我的):
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,
};
Run Code Online (Sandbox Code Playgroud)
还有其他情况内核会刷新 TLB。很难列出一个完整的清单,而且我认为没有人做过这样的清单。
Linux 内核实现了惰性 TLB 刷新技术。基本思想是,当进程的分页结构被修改时,内核会尝试将 TLB 击落延迟到该进程中的线程即将被安排在使用模式下执行的时间点。
Linux 内核当前使用以下四种方法之一在需要时刷新与当前逻辑核心关联的 TLB:
当前不使用其他类型的 INVPCID。
相关:术语 tlb shotdown 和 tlb flush 是指同一件事吗。
除了软件启动的 TLB 条目失效外,英特尔手册第 3 卷第 4.10.2.2 节针对 P6 微体系结构和大多数后来的微体系结构:
处理器不需要实现任何 TLB。实施 TLB 的处理器可能随时使任何 TLB 条目无效。软件不应依赖于 TLB 的存在或 TLB 条目的保留。
据我所知,AMD 手册中没有这样的声明。但也没有给出关于 TLB 整体保留的保证,因此我们可以对 AMD 处理器得出相同的结论。
x86 TLB不在内核之间共享,在硬件级别之间不同步.
操作系统指示处理器刷新其TLB.
指示"当前"处理器相当于调用一个函数,指示另一个处理器相当于进行IPI.
术语"TLB关闭"明确地指代这种(甚至比正常情况下)昂贵的情况,其中为了保持系统一致性,OS必须告知其他处理器使其TLB无效以便达到特定处理器的相同映射.
我认为只有在新映射影响某些共享内存时才需要这样做,否则每个处理器都在执行一个进程的不同实例,每个实例都有一个映射.
在上下文切换期间,刷新TLB以删除旧映射,这必须独立于调度程序运行的最后一个处理器完成.
由于处理器正在刷新自己的TLB,因此这不是TLB关闭.
处理器之间必须始终保持一致的共享区域可以是:内核页面,内存映射IO,共享内存映射文件.
的指令的执行invlpg,invpcid,此举cr0,cr3(包括HW任务切换过程中)或cr4与一个VMX过渡,所有无效TLB.
有关确切的粒度和语义,请参阅" 英特尔手册3"的第4.10.4节.