Cache - 虚拟地址 or 物理地址


  • Cache使用地址判断是否命中,地址使用的是物理地址还是虚拟地址呢?

1. VIVT(Virtually Indexed Virtually Tagged)

  • 虚拟高速缓存:以虚拟地址作为查找对象。
  • 首先虚拟地址给cache,如果命中,则返回数据给cpu,如果未命中,则将虚拟地址通过MMU转化为物理地址,根据物理地址从主存中读取数据。
  • 优点
    • 不需要在查找cache过程将虚拟地址翻译成物理地址,节省了MMU转换的时间,提高访问cache的访问速度。
  • 缺点
    • 引入软件使用上的问题,歧义(ambiguity)和别名(alias)。

2. 歧义

  • 歧义是指数据在cache中有相同的tag和index。
  • 发生情况:不同进程,相同的虚拟地址映射不同的物理地址。
    • 可能出现A进程地址a映射的数据为b,而B进程地址a映射的数据为c,当A进程运行时,访问地址a会将数据b加载到cache上,而进程B运行时,访问地址a时命中了并将数据b返回给CPU,但是实际上B进程应该把数据c给CPU。
  • 解决方法:切换进程,flush cache,主要有两种。
    • 使主存储器有效:首先将主存置为有效,将cacheline上已经修改的数据写回主存上,避免修改的数据丢失。
    • 使高速缓存无效:首先将cacheline都置为无效,保证切换时不会有进程误命中上一进程的数据。
  • 所以对于VIVT来说,每次进程切换时,都可能出现大量的cache缺失,且只要切换进程就需要flush cache,导致性能的缺失。

3. 别名

  • 发生情况:不同虚拟地址映射到相同物理地址。
    • 可能出现物理地址A对应的虚拟地址为B和C,index值B<C,那么当程序想要修改物理地址A对应的数据时,采用写回策略,对B进行修改,且修改的值没有同步到主存中,当程序想要访问虚拟地址C时,命中,但是取出的数据是未修改的。
  • 解决方法
    • (1)采用nocache映射,不通过cache映射,CPU直接去主存读写数据。既适用于不同进程共享数据也适用于相同进程共享数据。
    • (2)不同进程共享数据,可以选择在进程切换时,flush cache,(主要因为存在一个向主存写数据的过程)。
    • (3)同一进程共享数据,保证虚拟地址cache大小对齐,保证每次虚拟地址都会找到同一个cacheline,下面有更详细的描述。

4. PIPT(Physically Indexed Physically Tagged)

  • 物理高速缓存:为了解决VIVT歧义和别名的问题,tag和index都取自物理地址,对于物理地址来说tag和index都是唯一的。
  • 实现过程
    • CPU发出的虚拟地址首先经过MMU转化为物理地址,给到cache控制器观察是否命中。如果未命中,将去主存中根据物理地址取出数据。
  • 缺点
    • 硬件设计较VIVT要复杂很多,需要等待MMU转换之后才可以查cache。
    • 为了加快MMU转换速度,硬件上也会加一块TLB,虚拟地址和物理地址转换可以这篇博客
    • 很多CPU都使用PIPT高速缓存。

5. VIPT(Virtually Indexed Physically Tagged)

  • 物理标记的虚拟高速缓存
  • 使用虚拟index查找cacheline,与此同时,将虚拟地址给MMU转换为物理地址。MMU转换完之后cache也查找结束了,此时比对物理tag是否相同,以判断是否命中cache。
  • 不会存在歧义
    • 关键在于 VIPT的tag使用的是物理地址的PFN,是唯一的。
  • 不会存在别名(特定情况下)
    • 对于大部分系统来说,虚拟地址和物理地址之间的映射最小是以页为单位,在这篇博客中有介绍,页addr[11:0]内的内容无论是物理地址还是虚拟地址都是相同的。
    • 所以对于直接映射高速缓存,如果cache的大小小于等于4KB,那么意味着虚拟地址和物理地址的index是一样的,此时VIPT和PIPT是相同的。
    • 对于多路组相连高速缓存,每一组大小小于等于4KB,使用虚拟地址(此时等于物理地址)来做index寻址,并选择物理地址的tag来选择命中哪路的cache line。
  • 别名问题
    • 若cache的大小大于4KB,还是会出现别名问题。
    • 目的:避免相同物理地址的数据被加载到不同cacheline中。
      • 解决方法:相同物理地址数据对应的虚拟地址满足cache大小对齐。
      • 举例:cache大小8KB = 2^13,cache line大小为256B = 2^8,那么虚拟地址应该是下表几种情况,这样才会都找到第4行cacheline,不会出现别名的情况。
      • Linux实现中,采用该方法解决的别名问题。
address
0_00100_0000_0000
1_00100_0000_0000
10_00100_0000_0000
...
  • 对于L1 Cache的ICache,如果使用VIPT,虽然存在别名问题,但是考虑其为只读,所以即使多个虚拟地址对应一个物理地址也没有关系。

6. 不存在的PIVT高速缓存

  • 没有任何优点,首先需要通过MMU转换,消耗时间。还存在歧义和别名的问题。

7. 总结

  • VIVT几乎没有人使用,软件维护成本过高。
  • 对于多路组相连高速缓存的一路大小小于等于4KB,采用VIPT。
  • 对于一路大于4KB的,一般采用PIPT,VIPT也可以,但是还是需要特殊处理一下别名问题。
posted @ 2023-06-10 10:17  可达达鸭  阅读(541)  评论(0编辑  收藏  举报