ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

tlb flush_tlb_one_user

2026/10/4 21:04:31 拓冰建站 浏览量
tlb flush_tlb_one_user flush_tlb_one_user是 x86 架构中用于使用户空间映射中单个页面的 TLB 条目失效的顶层函数。它的核心特点是通常只刷新当前 CPU 的用户态 TLB而非广播到所有 CPU。核心作用单页用户 TLB 失效这个函数的职责非常具体针对当前进程用户地址空间中的一个特定虚拟地址使其在 TLB 中的缓存条目失效。它主要被flush_tlb_one_kernel调用-5也用于 UV 平台等场景。实现逻辑与 PTI 的特殊处理根据内核源码其实现如下void flush_tlb_one_user(unsigned long addr) { count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE); __flush_tlb_one_user(addr); if (!static_cpu_has(X86_FEATURE_PTI)) return; /* * If PTI is on, then the kernel is mapped with non-global PTEs, * and __flush_tlb_one_user() will flush the given address for * the current kernel address space and for its usermode counterpart, * but it does not flush it for other address spaces. */ this_cpu_write(cpu_tlbstate.invalidate_other, true); }关键点PTI 关闭时内核映射使用全局 PTE_PAGE_GLOBAL。INVLPG指令会刷新所有地址空间中的全局映射因此只刷新当前 CPU 就足够了因为全局映射在所有 CPU 上是一致的。PTI 开启时内核映射使用非全局 PTE。此时__flush_tlb_one_user(addr)只刷新当前地址空间中的条目。为了确保其他进程的页表也能看到这个变更函数会设置cpu_tlbstate.invalidate_other true标记“其他地址空间需要刷新”。这个标记会在下一次上下文切换时触发相应的清理操作。与flush_tlb_one_kernel的关系flush_tlb_one_user被flush_tlb_one_kernel调用。后者的逻辑是内核映射的刷新先通过flush_tlb_one_user(addr)完成当前地址空间的刷新如果 PTI 开启还需要额外标记“其他地址空间需要刷新”因为此时内核映射使用非全局 PTEINVLPG只影响当前地址空间。命名演进这个函数曾名为__flush_tlb_one或__flush_tlb_single。2018 年Dave Hansen 提交补丁将其重命名为flush_tlb_one_user和flush_tlb_one_kernel目的是让语义更清晰flush_tlb_single和flush_tlb_one听起来几乎一样但它们实际含义是“刷新用户翻译”和“刷新内核翻译”。重命名后函数名明确表达了刷新目标。2020 年Thomas Gleixner 进一步将__flush_tlb_one_user()移出内联头文件改为EXPORT_SYMBOL_GPL的独立函数以避免将敏感的cpu_tlbstate直接暴露给内核模块。与 KFENCE 的交互在 KFENCE内核内存错误检测器的 x86 实现中flush_tlb_one_kernel被用于保护/取消保护页面。LKML 讨论指出这种“只刷新本地 CPU”的做法在 KFENCE 场景下是可接受的近似行为——因为 KFENCE 的检测不要求确定性偶尔错过一个 bug 是可以容忍的。