news 2026/10/2 17:53:00

tlb invlpgb_kernel_range_flush

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
tlb invlpgb_kernel_range_flush

invlpgb_kernel_range_flush是 AMD 广播 TLB 失效(INVLPGB)补丁集中,用于刷新内核地址空间一段范围 TLB 条目的专用函数。它通过硬件广播指令替代传统的 IPI 风暴,显著降低了内核 TLB 刷新的开销。

核心作用:内核范围的硬件广播刷新

当内核需要修改自己的页表映射(如vmalloc区域的建立或拆除)时,需要使所有 CPU 上对应的 TLB 条目失效。传统方式是通过on_each_cpu向所有 CPU 发送 IPI,让每个 CPU 执行flush_tlb_one_kernel。

invlpgb_kernel_range_flush利用 AMD EPYC 3 及更新 CPU 上的INVLPGB 指令,从当前 CPU 直接向全系统广播失效请求,无需发送任何 IPI。

核心实现逻辑

根据补丁,其典型实现如下:

static void invlpgb_kernel_range_flush(struct flush_tlb_info *info) { unsigned long addr, nr; for (addr = info->start; addr < info->end; addr += nr << PAGE_SHIFT) { nr = (info->end - addr) >> PAGE_SHIFT; /* * INVLPGB has a limit on the size of ranges it can * flush. Break up large flushes. */ nr = clamp_val(nr, 1, invlpgb_count_max); invlpgb_flush_addr_nosync(addr, nr); } __tlbsync(); }

关键步骤:

  1. 循环切分范围:INVLPGB 单次操作能刷新的页面数量有硬件上限(存储在invlpgb_count_max中,通过 CPUID 读取)。因此函数需要将大范围切分成多个不超过上限的批次。

  2. clamp_val限幅:确保每次刷新的页数nr在[1, invlpgb_count_max]之间。invlpgb_count_max在早期启动阶段会被初始化为1,以防止在硬件值尚未读取时发生无限循环 。

  3. invlpgb_flush_addr_nosync:调用底层 INVLPGB 封装,指定地址和页数。nosync后缀表示不等待完成——INVLPGB 是异步指令,刷新请求发出后立即返回 。

  4. __tlbsync():在循环结束后调用TLBSYNC 指令,等待本 CPU 发出的所有 INVLPGB 请求真正完成。这是必须的同步点——在 TLB 刷新实际生效之前,内核不能释放相关的物理页 。

调用关系

flush_tlb_kernel_range(start, end) └── kernel_tlb_flush_range(info) └── invlpgb_kernel_range_flush(info) // ← 你问的函数 ├── invlpgb_flush_addr_nosync() // 多次,异步 └── __tlbsync() // 最后,同步等待

flush_tlb_kernel_range是上层入口。如果 CPU 支持X86_FEATURE_INVLPGB,就直接走invlpgb_kernel_range_flush;否则回退到传统的on_each_cpu(do_kernel_range_flush, ...)。

设计要点

  • ASID 有效位必须设置:INVLPGB 的 ASID 有效位(INVLPGB_FLAG_ASID)需要始终置位。在宿主机上,硬件会使用 EDX[15:0] 中指定的 ASID 值(应为 0);在客户机中,硬件会自动替换为客户机的实际 ASID。如果不设置这个位,可能会意外刷新客户机的 TLB 条目 。

  • cant_migrate()的必要性:__tlbsync()内部调用了cant_migrate(),因为TLBSYNC 只等待本 CPU 发出的 INVLPGB 完成。如果任务在 INVLPGB 发出后、TLBSYNC 执行前被迁移到其他 CPU,TLBSYNC 就无法等待到之前的刷新请求,导致同步失效 。

  • 与broadcast_tlb_flush的区别:broadcast_tlb_flush用于用户地址空间的刷新(基于全局 ASID),而invlpgb_kernel_range_flush用于内核地址空间的刷新。内核映射是全局的,不属于任何特定 ASID,因此 INVLPGB 使用INVLPGB_FLAG_VA | INVLPGB_FLAG_INCLUDE_GLOBAL模式来刷新所有地址空间中的内核映射 。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 17:50:04

国产32位MCU替代STM32F103:GPS定位板卡从选型到NMEA解析全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 17:47:44

VQGAN原理与PyTorch实战:从图像离散化到文本生成高清图像

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 17:47:09

Google翻译API HTTPS调用实战:密钥、证书、配额与连接管理全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 17:46:28

OCC入门指南:Open CASCADE三维建模开发实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 17:46:20

SoC存储体系详解:从寄存器到UFS的类型差异与工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华