当前位置: 首页 > news >正文

Linux 内存管理:TLB ASID

文章目录

  • 1. 前言
  • 2. TLB ASID 的硬件支持
    • 2.1 概念
    • 2.2 TLB 查找
  • 3. Linux 下 TLB ASID 管理
  • 4. 参考资料

1. 前言

限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。

2. TLB ASID 的硬件支持

2.1 概念

  • 什么是TLB
    TLBTranslation Lookaside Buffers的缩写,MMU 将虚拟地址(VA)翻译为物理地址(PA)时,要经过页表遍历(page table walk)过程,每访问一级页表就要一次内存访问,相对来说,这个延迟还是相对较大的。为了提高性能,硬件上引入了 TLB cache 缓存,首次访问一个 VA 后,将 MMU 转换的 PA 以对应的 VA 为 tag 缓存到 TLB 缓存,下次再访问同一 VA,就可以通过以 VA 为 tag 从 TLB 搜索提取对应的 TLB entry 了,不用再经历漫长的page table walk过程。当然,TLB 的容量有限,只能缓存有限个数 VA 翻译的 PA 地址,这就需要做一定的管理,在 TLB 耗尽时,通过某种算法,用新的 PA 将一些旧的缓存替换掉。

  • 什么是 TLB ASID?
    ASIDAddress Space Identifier的缩写,标识属于特定进程的TLB entries。那为什么需要它?前面说过,TLB 容量有限,在系统中属于珍贵资源;另外,在系统进程的切换过程中,会进行页表切换,而每个进程的页表不一样,那意味着,当前进程的 TLB 缓存的地址翻译内容,对新进程将失效,所以页表切换需要进行整个 TLB cache 的 flush,这会带来不小的性能损失。于是硬件上引入了nG(not Global)标志位 和ASID,来对该问题进行优化:nG=0标识 TLB entries 属于 ASID 标识的进程,nG=1标识 TLB entries 属于全局的内核空间地址(所有进程共享内核空间的页表映射)。这样,在切换进程的页表时候,只需要为新进程分配一个 ASID 来标识自己的 TLB entries,在 ASID 或 TLB cache entries 消耗完之前,都不需要刷 TLB cache 了。

2.2 TLB 查找

nG标志位同时位于最后一级页表的表项TLB entries中,然后首次内存访问某个地址时,记录到 TLB entries 中。而当前进程的ASID,会在进程页表切换时设置到TTBRx寄存器中,同时也会在首次访问某个VA地址时,记录到TLB entries中。当然,TLB entries 也记录访问VA地址的VA tag。这样,在后续访问某一VA地址时,首先比较 VA 地址 TLB entries VA tag,如果不匹配,则表示 TLB miss,要继续进行page table walk来翻译PA;如果相同,则继续查看 TLB entry 的nG位,如果为nG=0,则意味着是内核空间地址的 TLB entry,所有进程共享,即命中了 TLB,返回 TLB entry 保存的PA即可;如果nG=1,则表示是某进程特定的 TLB entry,通过 ASID 标识,则继续比较 TLB entry 的 ASID 和 TTBRx 寄存器存储的当前进程的 ASID,如果值相同,则标识命中,否则标识 TLB miss,否则要继续进行page table walk来翻译PA

3. Linux 下 TLB ASID 管理

ARMv7架构 +Linux 4.14.x内核简略的分析下TLB ASID的管理细节,来看代码:

typedefstruct{#ifdefCONFIG_CPU_HAS_ASIDatomic64_tid;/* ASID: generation | HW ASID */#else...#endif...}mm_context_t;
voidcheck_and_switch_context(structmm_struct*mm,structtask_struct*tsk){unsignedlongflags;unsignedintcpu=smp_processor_id();u64 asid;...asid=atomic64_read(&mm->context.id);/* 读取新进程的 ASID *//* * a. !((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS * 新进程 asid 属于/分配自 当前 generation * b. atomic64_xchg(&per_cpu(active_asids, cpu), asid) * a.成立的条件下, 顺便设定 当前 CPU 激活的 (进程的) asid, * 然后就可以进入页表的切换过程了. */if(!((asid^atomic64_read(&asid_generation))>>ASID_BITS)&&atomic64_xchg(&per_cpu(active_asids,cpu),asid))gotoswitch_mm_fastpath;/* ASID 无需更新,直接进入页表切换过程 */raw_spin_lock_irqsave(&cpu_asid_lock,flags);/* Check that our ASID belongs to the current generation. */asid=atomic64_read(&mm->context.id);/* 新进程 asid 不 属于/分配自 当前 generation, 要重新从当前 generation 为新进程分配 asid */if((asid^atomic64_read(&asid_generation))>>ASID_BITS){asid=new_context(mm,cpu);/* ASID 管理操作 */atomic64_set(&mm->context.id,asid);/* 为 进程 分配的 ASID 记录到 进程的 mm_struct */}/* 当前 generation ASID 耗尽,需要刷掉所有的 TLB cache */if(cpumask_test_and_clear_cpu(cpu,&tlb_flush_pending)){local_flush_bp_all();local_flush_tlb_all();}atomic64_set(&per_cpu(active_asids,cpu),asid);/* 当前 CPU 激活的 (进程的) asid */cpumask_set_cpu(cpu,mm_cpumask(mm));raw_spin_unlock_irqrestore(&cpu_asid_lock,flags);}staticu64new_context(structmm_struct*mm,unsignedintcpu){staticu32 cur_idx=1;u64 asid=atomic64_read(&mm->context.id);u64 generation=atomic64_read(&asid_generation);/* * 在创建新的进程的时候会分配一个新的 mm, 其(mm->context.id)初始化为 0. * 如果 asid 不等于 0, 那么说明这个 mm 之前就已经分配过 software asid * (generation + hw asid)了. */if(asid!=0){u64 newasid=generation|(asid&~ASID_MASK);/* * If our current ASID was active during a rollover, we * can continue to use it and this was just a false alarm. */if(check_update_reserved_asid(asid,newasid))returnnewasid;/* * We had a valid ASID in a previous life, so try to re-use * it if possible., *//* 如果新 generation 中旧的 asid 还未被分配出去, 重用它 */asid&=~ASID_MASK;if(!__test_and_set_bit(asid,asid_map))returnnewasid;/* 返回更新了 generation 的 asid */}/* * 如果 asid 等于 0, 说明我们的确是需要分配一个新的 HW asid, * 这时候首先要找一个空闲的 HW asid, 如果能够找到, 那么直接返 * 回 software asid (当前 generation + 新分配的 hw asid); 否则, * 表示 asid 消耗完了,生成新的 generation 并重新进行分配??? */asid=find_next_zero_bit(asid_map,NUM_USER_ASIDS,cur_idx);if(asid==NUM_USER_ASIDS){/* ASID 消耗完了,需重新分配 */generation=atomic64_add_return(ASID_FIRST_VERSION,&asid_generation);/* 递增 ASID generation */flush_context(cpu);asid=find_next_zero_bit(asid_map,NUM_USER_ASIDS,1);}__set_bit(asid,asid_map);/* 更新 ASID 分配位图: 标记 asid 已经被分配 */cur_idx=asid;cpumask_clear(mm_cpumask(mm));returnasid|generation;/* 返回新分配的 asid */}staticvoidflush_context(unsignedintcpu){inti;u64 asid;/* Update the list of reserved ASIDs and the ASID bitmap. */bitmap_clear(asid_map,0,NUM_USER_ASIDS);for_each_possible_cpu(i){asid=atomic64_xchg(&per_cpu(active_asids,i),0);/* * If this CPU has already been through a * rollover, but hasn't run another task in * the meantime, we must preserve its reserved * ASID, as this is the only trace we have of * the process it is still running. */if(asid==0)asid=per_cpu(reserved_asids,i);__set_bit(asid&~ASID_MASK,asid_map);per_cpu(reserved_asids,i)=asid;}/* Queue a TLB invalidate and flush the I-cache if necessary. */cpumask_setall(&tlb_flush_pending);/* 当前 generation 的 asid 耗尽, 更新 generation, 标记要刷 TLB */if(icache_is_vivt_asid_tagged())__flush_icache_all();}

4. 参考资料

[1] DDI0406C_d_armv7ar_arm.pdf
[2] TLB原理

http://www.jsqmd.com/news/106357/

相关文章:

  • 【计算机毕设】基于深度学习的人体摔倒识别方法与实现
  • 42、Linux编程:软件开发工具探索与实践
  • 告别 LLM 输出的不确定性:深度解析 TypeChat 如何重塑 AI 工程化开发
  • 机器人操作空间速度计算python几种实现函数
  • 透过格子玻尔兹曼LBM实现三相驱替:油、水、二氧化碳三组分动态模拟与研究
  • 通用 AI · Universal AI 2
  • 微信朋友圈集赞神器靠谱吗?微信点赞群5000人微信投票是真的吗? - 速递信息
  • 格子玻尔兹曼方法(LBM)的MRT作用力模型
  • 为何选择具备制造业基因的厂商,是ERP与OA系统集成成功的关键
  • 43、Linux 编程:GNU 许可证与入门级 Shell 脚本编写
  • LLC谐振变换器的控制策略多种多样,今天咱们就来聊聊几种常见的闭环仿真方法,顺便用Matlab/Simulink来搞点代码,看看这些控制策略在实际中是怎么玩的
  • 多孩家庭首选 30-40 万新能源7座车型推荐 - 速递信息
  • API赋能:消金电销无缝联的革新实践
  • scheme中的序列操作
  • 力扣 “两数之和” 最优解:哈希表 O (n) 时间复杂度实现详解
  • 30-40 万新能源汽车 兼顾续航与智能的热门之选 - 速递信息
  • Skipping xxx as repository xxxx doesn‘t support architecture ‘i386‘
  • 基于WEB的高校计算机数据库课程知识图谱系统的设计与实现
  • TLS网络安全协议巩固知识基础题(2)
  • 网站建设公司怎么选?2025年网站设计制作公司推荐指南
  • 告别重复编码!10+顶级开发工具,引爆程序员效率革命
  • 聚焦家庭需求:20 万左右新能源 SUV 空间与安全优选车型
  • 基于SpringBoot + Vue的高校科研项目申报审批管理系统
  • 2026年河北省职业院校技能大赛中职组“网络建设与运维”竞赛样题
  • 基于SpringBoot + Vue的个性化学习系统
  • C语言5——常见关键字 define定义常量 表达式求值
  • 数学刷题总结
  • FlutterOpenHarmony底部导航栏组件开发
  • 2026年河北省职业院校技能大赛“信息技术应用创新”赛项(高职组)竞赛样题
  • FlutterOpenHarmony动画效果实现指南