news 2026/10/1 11:37:34

tlb user_pcid

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
tlb user_pcid

user_pcid是 x86 架构中用于将逻辑 ASID 转换为用户态 PCID(uPCID)的辅助函数。它与kern_pcid配对使用,专门服务于 KPTI(页表隔离)场景下的用户态页表切换。

核心作用:在 kPCID 基础上设置切换位

static inline u16 user_pcid(u16 asid) { u16 ret = kern_pcid(asid); // 先得到内核态 PCID (1~6) #ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION ret |= 1 << X86_CR3_PTI_PCID_USER_BIT; // 设置 bit 11,得到用户态 PCID #endif return ret; }

代码逻辑解析

1. 基础转换

u16 ret = kern_pcid(asid);

先调用kern_pcid完成逻辑 ASID → kPCID 的转换。kern_pcid的核心操作是asid + 1,将逻辑 ASID(0~5)映射到 kPCID(1~6)。PCID 0 被保留给swapper_pg_dir等特殊用途。

2. KPTI 下的用户态标识

#ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION ret |= 1 << X86_CR3_PTI_PCID_USER_BIT; #endif

如果内核启用了 KPTI(页表隔离),则将结果与1 << X86_CR3_PTI_PCID_USER_BIT进行或运算。X86_CR3_PTI_PCID_USER_BIT通常是bit 11,1 << 11 = 2048。这样,uPCID 的范围就是2049~2054。

为什么需要区分 kPCID 和 uPCID?

在 KPTI 机制下,每个进程实际上有两套页表:

  • 内核页表:包含完整的内核和用户空间映射。

  • 用户页表:只包含极少的必要内核映射和完整的用户空间映射。

当 CPU 从用户态陷入内核时,需要从用户页表切换到内核页表;返回用户态时再切回。如果两套页表使用同一个 PCID,那么每次切换都会导致 TLB 中该 PCID 的条目被混淆——内核态的 TLB 条目和用户态的 TLB 条目无法区分。

通过给用户页表分配一个独立的 PCID(设置 bit 11 的 uPCID),内核页表和用户页表就拥有了不同的 PCID 标签。CR3 切换时,CPU 只会命中与当前 PCID 匹配的 TLB 条目,从而避免了 KPTI 切换时刷新整个 TLB,显著降低了 KPTI 的性能开销。

三个标识符的完整映射

名称范围计算公式用途
ASID0~5逻辑标识内核内部索引
kPCID1~6asid + 1写入 CR3,内核态页表
uPCID2049~2054kPCID | (1 << 11)写入 CR3,用户态页表(KPTI)

这三个标识符共同构成了 Linux PCID 管理的核心:用极小的 ASID 空间(6 个槽位)配合位标志,在有限的 12 位 PCID 中,为每个 CPU 缓存最近使用的少量地址空间,同时与 KPTI 的页表切换需求完美协同。

kern_pcid的调用者

kern_pcid和user_pcid是纯计算函数,它们本身不调用其他函数,而是被上层函数在构建 CR3 值和执行 TLB 刷新时调用。

它最核心的用途是构建内核态 CR3 值。在build_cr3和build_cr3_noflush中,kern_pcid(asid)被用来将逻辑 ASID 转换为硬件 PCID 位:

static inline unsigned long build_cr3(pgd_t *pgd, u16 asid, unsigned long lam) { return __sme_pa(pgd) | kern_pcid(asid) | lam; }

build_cr3本身又被load_new_mm_cr3和__get_current_cr3_fast调用,用于在进程切换时加载 CR3 。

此外,在 TLB 刷新的底层实现中,kern_pcid也被用来指定要刷新哪个 PCID 的条目,例如invlpgb_flush_single_pcid_nosync(kern_pcid(asid))。

user_pcid的调用者

user_pcid主要用于KPTI 场景下的 TLB 刷新。当内核需要使某个用户地址空间的 TLB 条目失效时,必须同时刷新对应的内核 PCID 和用户 PCID:

invlpgb_flush_user_nr_nosync(kern_pcid(asid), addr, nr, pmd); if (static_cpu_has(X86_FEATURE_PTI)) invlpgb_flush_user_nr_nosync(user_pcid(asid), addr, nr, pmd);

这段代码来自 AMD 广播 TLB 失效(INVLPGB)的补丁,它在刷新用户地址的 TLB 时,先刷新内核 PCID,如果启用了 KPTI,再刷新用户 PCID 。

在invalidate_user_asid中的间接使用

invalidate_user_asid函数不直接调用user_pcid,但它通过kern_pcid来标记用户 ASID 需要刷新:

static inline void invalidate_user_asid(u16 asid) { __set_bit(kern_pcid(asid), (unsigned long *)this_cpu_ptr(&cpu_tlbstate.user_pcid_flush_mask)); }

这里用kern_pcid(asid)作为位索引,在user_pcid_flush_mask位图中标记“这个 ASID 的用户 PCID 需要在下一次切换时刷新” 。这个位图的存在正是因为用户 PCID 和内核 PCID 需要分别管理——内核空间的 TLB 失效只影响kern_pcid,用户空间的失效则需要额外标记user_pcid。

总结

kern_pcid和user_pcid处于 PCID 管理的最底层,它们不调用任何函数,只做简单的位运算。它们的调用者分为两类:构建 CR3 值(如build_cr3)和执行 TLB 刷新(如 INVLPGB 路径和invalidate_user_asid)。这种分层设计确保了 PCID 的转换逻辑集中在一处,避免在各处重复计算。

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

表格结构检测数据集与YOLOv8实战:从训练到单元格还原

简介&#xff1a;表格结构检测数据集2.zip 面向文档数字化、表格数据提取与文档布局分析方向的算法开发者与研究人员&#xff0c;提供可直接用于目标检测训练的标注数据&#xff0c;解决发票、报表、合同等文档中表格行列结构自动解析的问题。资源包共2000个文件&#xff0c;以…

作者头像 李华
网站建设 2026/10/1 11:35:57

会员成长与积分体系全解析:从等级计算到积分商城落地实践

简介&#xff1a;芒果TV会员成长及积分体系的完整拆解文档&#xff0c;聚焦会员等级、成长值与积分三大模块&#xff0c;适合产品经理、会员运营人员及互联网商业分析研究者阅读。文档详细说明了成长值的三类获取来源、到期未续费时的扣减规则&#xff0c;以及代金券、观影券、…

作者头像 李华
网站建设 2026/10/1 11:35:10

数据库基础与运维实战:从连接到同步的核心问题全解析

很多人一听“数据库——1”这个标题&#xff0c;第一反应是“又要从SQL语法讲起了”。其实真不是。我在这行干了十多年&#xff0c;从MySQL、Oracle一路用到达梦、人大金仓、GBase&#xff0c;再到SQLite这种单文件小库&#xff0c;项目里几乎都碰过。这个系列想做的&#xff0…

作者头像 李华
网站建设 2026/10/1 11:35:08

Windows下MySQL 5.5安装配置全攻略:从下载到故障排查一次搞定

实验课的第一课通常都是这个画风&#xff1a;老师在群里丢一句“回去把MySQL装好&#xff0c;下一节实验要用”&#xff0c;然后就没有然后了。你打开搜索引擎&#xff0c;结果一半是MySQL 8.0的教程&#xff0c;一半是十年前模糊不清的截图&#xff0c;跟着做到“服务启动失败…

作者头像 李华
网站建设 2026/10/1 11:34:21

世界4大顶级黑客,排第一的他从不黑中国,最后一位是中国的骄傲

世界4大顶级黑客&#xff0c;排第一的他从不黑中国&#xff0c;最后一位是中国的骄傲&#xff0c;大家对于黑客应该都是知道一点的&#xff0c;也都是特别的羡慕这种人的&#xff0c;全世界最顶级的黑客之一就是凯米&#xff0c;米特尼克了&#xff0c;他是第一个被美国的调查局…

作者头像 李华
网站建设 2026/10/1 11:34:06

Flutter for OpenHarmony跨端适配实战:衣橱管家帮助模块开发记录

这套衣橱管家App从立项算起&#xff0c;断断续续写了两个月。业务逻辑本身不算复杂——衣物分类、穿搭推荐、换季收纳提醒&#xff0c;都是很常规的增删改查加上一点规则判断。真正让我花心思的是跨端适配&#xff0c;尤其是把Flutter代码搬到OpenHarmony上之后&#xff0c;一堆…

作者头像 李华