☰
tlb __get_current_cr3_fast
2026/10/4 21:00:21 网站建设 项目流程

__get_current_cr3_fast是一个快速获取当前 CR3 值的辅助函数。它的核心目的是在不执行缓慢的read_cr3()指令的情况下,通过软件状态(cpu_tlbstate)直接“拼装”出当前的 CR3 值。

核心用途与限制

这个函数主要服务于KVM(内核虚拟机)这类会“偷偷”修改 CR3、之后又需要恢复它的代码。

它的使用有非常严格的限制:

  • 必须在原子上下文(in_atomic())中调用,且不能处于 NMI(不可屏蔽中断)中。

  • 在CONFIG_DEBUG_VM下,它会用VM_BUG_ON断言拼装出的值与真实read_cr3()一致,用于调试。

实现逻辑与演进

基础实现(较新版本):

unsigned long __get_current_cr3_fast(void) { unsigned long cr3 = __pa(this_cpu_read(cpu_tlbstate.loaded_mm)->pgd); VM_WARN_ON(in_nmi() || !in_atomic()); VM_BUG_ON(cr3 != read_cr3()); return cr3; }

它直接读取当前 CPU 已加载的mm的pgd物理地址,而不包含 PCID 信息。

更完整的实现(2020 年及以后):

unsigned long __get_current_cr3_fast(void) { unsigned long cr3 = build_cr3(this_cpu_read(cpu_tlbstate.loaded_mm)->pgd, this_cpu_read(cpu_tlbstate.loaded_mm_asid), tlbstate_lam_cr3_mask()); VM_WARN_ON(in_nmi() || preemptible()); VM_BUG_ON(cr3 != __read_cr3()); return cr3; }

这里通过build_cr3()将页表基址、ASID(进程上下文标识符)和 LAM(线性地址掩码)完整地拼装出来,以匹配硬件 CR3 的真实值。

演进原因:2020 年,Thomas Gleixner 将__get_current_cr3_fast从内联头文件移到了arch/x86/mm/tlb.c中,并改为EXPORT_SYMBOL_GPL。这是为了避免将敏感的cpu_tlbstate直接暴露给内核模块,让模块通过这个受控的接口来获取 CR3。

与 ASI(地址空间隔离)的交互

在支持ASI(Address Space Isolation)的补丁集中,该函数需要感知当前是否处于隔离会话中。如果 ASI 处于活动状态,它不能直接读取cpu_tlbstate(因为 ASI 页表可能未映射该结构),而是从 ASI 会话缓存中获取 CR3 值。

这个函数是 KVM 等底层代码在无法使用慢速read_cr3时,获取当前 CR3 值的“快捷通道”。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询