当前位置: 首页 > 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.cnnetsun.cn/news/113934.html

相关文章:

  • Xiaomi 商城页面布局(部分)
  • FPGA以太网升级程序:便捷qspi Flash升级,具备校验功能,适用于Xilinx 7系列...
  • 运料小车装卸料控制:西门子1200PLC与TP700触摸屏联机仿真博途16
  • S32K311启动过程中,向量表重定向
  • 从蓝图到产线:高效产品信息传递的桥梁建设
  • 时间复杂度
  • 网站建设公司怎么选?2025年网站设计制作公司推荐指南
  • 今天咱们来聊一个挺有意思的优化算法改进——基于透镜成像反向策略的海洋捕食者算法。这个改进版本在原始MPA基础上搞了点新花样,咱们直接上干货看代码实现
  • Gitee:本土化DevOps平台如何重塑中国开发者生态
  • vCenter Server 8.0U3h 新增功能简介
  • Cisco NX-OS 10.6(2)F 发布 - 数据中心网络操作系统
  • Ubuntu24.04无操作卡死,无法唤醒问题以及内核版本切换记录
  • 全场景覆盖・全流程智控:分布式解决方案让多功能厅 “不止于多”
  • 【轨物方案】聚焦锯床设备智能化升级,打造工业互联网新范式
  • 【轨物交流】轨物科技亮相2025高校科技成果交易会
  • cesium加载geotiff的 四种方法
  • 【毕业设计】基于python的运维管理平台的设计与实现
  • 苹果 iOS 开发真正复杂的不是写代码这方面,是证书、构建、上架
  • FSMC-TFTLCD显示实验(5):显示一个字符串的函数传递过程追踪~
  • 基于Android的课程考勤及作业提交系统
  • 飞易通蓝牙与Wi-Fi模块:医疗产品无线连接的全能助手
  • 你的音效素材库该升级了!这个网站的分类细到超出你想象
  • Agent的“话痨”病有救了!微软黑科技教你压缩对话历史,让AI告别失忆,这篇教程太顶了!
  • ARMv7 linux中断路由以及处理
  • 【详解】基于Kubernetes部署Kafka集群
  • AIoT:从万物互联到万物智联的进化之路
  • ERROR in ./node_modules/vue-router/dist/vue-router.mjs 被报错折磨半天?真相竟是……
  • Spring Boot 自动配置的底层实现原理
  • AI如何帮你快速掌握Wireshark端口过滤技巧
  • 手把手教你复现CVE-2023-51767漏洞