• 深入理解地址翻译 CSAPP


    地址翻译, 用自己的话说一遍, 然后自己在draw.io画图理解.

    术语

    页表就是一个 页表条目(Page Table Entry  PTE)的数组,每一项(每个PTE)是[有效位,物理地址]. 我们是用VPN来标识每个PTE,但记住这些VPN并不是页表的一部分,不会储存在内存中

    虚拟地址为n位,p位为offset(inner), 其他的为第几页,就是outter-inner的结构,outter的page number第几页,inner是页里面的第几行page offset (和一个循环的维度分成tile后的outter-inner概念类似,分块后有多少块,每块有多少行)

    物理地址类似的

    因为虚拟地址和物理地址每一页的大小相同都是p位,因此地址翻译的时候只需要翻译第几页的对应关系就可以,页的第几行是一模一样的。这个映射关系就是图左边的箭头,在右边用一个字典来存储这个映射关系,这个字典叫做页表page table,其中除了虚拟页号和物理页号的映射关系,还有一个信息是有效位,表示这个虚拟地址是否已经cached在主存中。

     综上所述,这个地址翻译的工作就是由MMU做的。

    页命中的情况是这样的,CPU执行挑转指令时,ret call jump 等指令,会生成虚拟地址VA,MMU接到VA后,根据VA地址中的虚拟页号,在页表中查找,如果有效位为1,就是页命中,则MMU输出翻译后的物理地址,就是页表中那一行获取物理页号,拼接上虚拟地址的page offset,就是物理地址了,然后去内存获取数据,传给CPU。

    页命中完全是由硬件来处理的,缺页的情况需要硬件和操作系统内核协作完成。MMU查表发现有效位为0, 触发异常,传给发缺页异常处理程序,这个异常处理程序给出物理内存中的牺牲页,如果这个页已被修改,则换出到磁盘,然后缺页处理程序调入新的页面,并更新表的中物理页号,有效位改为1。

     目前这套机制的问题是,如果VA空间很大,那么MMU要查找的页表就很长,每次MMU都需要从内存取这个页表的数据,代价大概是100cycle,如果可以把页表放到缓存中,那么开销就降为5cycle左右。因此在MMU内部做了一个关于PTE的缓存,叫做TLB (Translation Lookaside Buffer)翻译后备缓冲器。那么这个TLB肯定是比较小的,于是把虚拟地址的Page Number分成 2^t 个set,索引第几个set就是 TLBI (TLB index)- outter, 剩下的是inner TLBT (tag) 

    术语

    4KB的页面(4KB=2^12 page size)页面大小为4KB

    32bit addr space (VA)

    4-byte PTE 

    求一共需要多大的page table?

    2^32*2^-12 * 4Byte = 4MB

    总是需要一个4MB的页表驻留在内存中。

    对64-bit的系统来说,指针和地址都是 64 位的,但是虚拟地址空间则是 48 位的,超过 48 位的 bit 要么全是 0 要么全是 1,这是 intel 制定的规则,高位全为 1 的地址为内核保留(地址指向内核中的代码或者数据),高位全为 0 的地址为用户代码保留。 

    假如地址空间是48bit, page size还是4KB,8-byte PTE, 则需要2^48*2^-12*8= 2^39 Byte =512GB来放页表。

    解决方案是multi-level page table,多级页表表示,是一种压缩页表的方法。

     一级页面的每一项PTE映射总虚拟地址中4MB的片chunk, 每个页表块 为 4MB的片 chunk (1024 * 4Byte PTE) 

    二级页表的每一个PTE负责映射一个4KB的虚拟内存页面,一级和二级页表都是4KB,刚好和一个页面大小是一样的。都是由2^10个条目,每个条目4Byte,总共是2^32 bit地址空间

    如何压缩的思想:

    - 如果一级页表中的某一项为空,相应的二级页表就不存在

    - 只放一级页表在主存中,二级页表根据需要调度

    具体例子

    1. MMU把虚拟地址翻译成物理地址,TLB是虚拟地址寻址的,找到相应的物理地址(页面大小为4KB由12位的VPO,这个和物理地址的PPO是相同的)

    2. 物理地址在传送到L1高速缓存(高速缓存是物理寻址的,L1高速缓存8组相连,由64个组,大小为64字节的缓存块,每个物理地址由6个缓存偏移位 和6个缓存索引位,这12位刚刚好和VPO, PPO也是12位。

    因此地址翻译的时候,把VPN发给MMU处理,把VPO发给高速L1缓存处理。当MMU得到PPN,就可以匹配是否命中高速缓存了

    L1,L2,L3 cache是物理寻址的,下图的块大小为4字节,intel的块大小是64字节

    L1,L2是8路组相连,L3是16路组相连

    页大小可以在启动时被配置,linux使用的是4KB的页

     

     1. MMU首先根据VPN查找 TLB, TLBI=3, TLBT=3, 找到相应的物理地址 PPN=0x0D

    2.  PPN+PPO合成物理地址

    3. 物理地址发送给cache,提取CI=5, CT=0xD, C0=0, 在表中找到值为36

    4. cache将36中的字节通过MMU返回给CPU,并将其存到一个寄存器中

    参考:https://greenhathg.github.io/2022/05/18/CMU213-CSAPP-Virtual-Memory-Systems/18-Virtual-Memory-SystemsSimple memory system exampleAddress Translation Example #1 PPN实际不存在页表中 MMU做的第一件事是检查TLB,将VA中的VPN的TLBI(0x3)和TLBT(0x03)提取出来。所以会去查set3找到tag为3的line,找到对应的line并且valid为1,TLB将PPN(0D)返https://greenhathg.github.io/2022/05/18/CMU213-CSAPP-Virtual-Memory-Systems/

  • 相关阅读:
    数据结构与算法这么重要还不会?字节内部笔记来帮你轻松拿下!
    Redis6.0 新功能
    Python、设计原则和设计模式-对象行为类设计模式(一)
    【小笔记】当一个算法性能不满意,可能是这几方面的原因
    java毕业设计超市后台系统Mybatis+系统+数据库+调试部署
    【FPGA教程案例35】通信案例5——基于FPGA的16QAM调制信号产生,通过matlab测试其星座图
    用ARM进行汇编语言编程(5) 使用链接寄存器进行分支并返回和从堆栈内存中保存和检索数据
    Luogu P3379 【模板】最近公共祖先(LCA),树链剖分求LCA模板
    Vue.js 组件通信——父组件向子组件通过props传值
    面试官问Spring 启动流程,把这篇文章甩给他!
  • 原文地址:https://blog.csdn.net/Chunying27/article/details/128075495