【ARM】Cache深度解读

Cache的基本概念和使用场景

不同的Master硬件共享数据时---invalid cache


外设和DDR之间没有cache,所以外设直接把数据写入DDR中,但是cpu和DDR之间有cache,cpu会首先访问cache,如果命中直接从cache中拿数据,但是此时的cache并不是最新的数据,cache没有刷新,就拿不到DDR中的数据。此时的解决办法就是在cpu读取数据之前,让cache中的缓存无效,这样就会直接从DDR中读取数据。

不同的Master硬件共享数据时---flush cache

同样还有下面情况,需要刷新cache

不同的缓存策略的系统共享数据时---flush cache

不同的缓存策略的系统共享数据时---invalid cache

操作系统中软件维护cache一致性的API

void __flush_icache_range(unsigned long start, unsigned long end);

int invalidate_icache_range(unsigned long start, unsigned long end);

void __flush_dcache_area(void *addr, size_t len);

void __inval_dcache_area(void *addr, size_t len);

void __clean_dcache_area_poc(void *addr, size_t len);

void __clean_dcache_area_pop(void *addr, size_t len);

void __clean_dcache_area_pou(void *addr, size_t len);

long __flush_cache_user_range(unsigned long start, unsigned long end);

void sync_icache_aliases(void *kaddr, unsigned long len);

void flush_icache_range(unsigned long start, unsigned long end)

void __flush_icache_all(void)

modified的数据地址,在执行invalidate的时候,会先自动执行clean。即

DC IVAC等效于DC CIVAC

cache指令

为什么要用cache?

ARM 架构刚开始开发时,处理器的时钟速度和内存的访问速度大致相似。今天的处理器内核要复杂得多,并且时钟频率可以快几个数量级。然而,外部总线和存储设备的频率并没有达到同样的程度。可以实现可以与内核以相同速度运行的小片上 SRAM 块,但与标准 DRAM 块相比,这种 RAM 非常昂贵,标准DRAM 块的容量可能高出数千倍。在许多基于 ARM 处理器的系统中,访问外部存储器需要数十甚至数百个内核周期。缓存是位于核心和主内存之间的小而快速的内存块。它在主内存中保存项目的副本。对高速缓冲存储器的访问比对主存储器的访问快得多。每当内核读取或写入特定地址时,它首先会在缓存中查找。如果它在高速缓存中找到地址,它就使用高速缓存中的数据,而不是执行对主存储器的访问。通过减少缓慢的外部存储器访问时间的影响,这显着提高了系统的潜在性能。通过避免驱动外部信号的需要,它还降低了系统的功耗。

怎么去刷cache呢? (软件维护cache的一致性)

ARM提供了操作cache的指令, 软件维护操作cache的指令有三类:

• Invalidation:其实就是修改valid bit,让cache无效。

• Cleaning: 这其实就是我们所说的flush cache,这里就是清除dirty标志,这里会将cache数据回写到内存

• Zero:将cache中的数据清0.

那么一般什么时候需要软件维护cache一致性呢?

(1)、当有其它的Master改变的external memory,如DMA操作

(2)、MMU的enable或disable的整个区间的内存访问,

(3)、当不同缓存策略的系统使用同一块内存通信时,如REE enable了mmu,TEE disable了mmu.

cache一致性指令介绍

总结

按照指令,分为:

• IC : 操作instruction cache,指令cache

• DC : 操作data cache,数据cache

point:刷cache刷到哪个位置

U:一般L1刷到L2

C:从L2往后刷完

IS:刷哪些范围中的cache

按照操作,分为以下三类:

• Invalidation:其实就是修改valid bit,让cache无效。

• Cleaning: 清除cache中的data和TAG,这其实就是我们所说的flush cache,这里会将cache数据回写到内存,并清除dirty标志

• Zero:将cache中的数据清0.

可以以指定只刷L1或L2或L3 cache

Cache的架构

big.LITTLE 和 dynamIQ架构的cache

• 在big.LITTLE 架构中,大核小核在不同的cluster中,做为两个不同的ACE或CHI Master,连接到缓存一致性总线上(CCI或CMN)。大核cluster和小核cluster的缓存一致性,也需要通过一致性总线来解决。

• 到了DynamIQ 架构中,大核和小核都是一个DSU cluster中,一个DSU cluster最多可以支持8个core。如果你的系统是8个core,那么一个DSU就够了,那么系统中也就只有一个ACE或CHI Master,大核和小核之间的一致性,都在DSU cluster内

完成了

dynamIQ架构的cache

Cache是多级相连的

cache是多级的,在一个系统中你可能会看到L1、L2、L3, 当然越靠近core就越小,也是越昂贵。一般来说,对于big.LITTLE架构中,在L1是core中,L1又分为L1 data cache和 L1 Instruction cache, L2 cache在cluster中,L3则在BUS总线上。

cache的种类(VIVT,PIPT,VIPT)

在一个core中一个架构中一个SOC中,你所使用的cache是哪种类型的,都是固定的,是软件改不了的。

在ARM架构中,一般L1 cache都是VIPT的,其余的都是PIPT的。

L1、L2 和 L3 缓存:有什么区别?

三级高速缓存之间的主要区别在于大小、速度以及它们所在的位置。

• L1 缓存的存储容量较低,但通常是计算机中最快的内存,比 RAM 快 100 倍。每个处理器核心都有自

己的 L1 缓存,通常约为 64KB。

• L2 缓存可能比 L1 大几倍,但速度仅为 RAM 的 25 倍左右。与 L1 一样,每个处理器核心都有自己的

L2 缓存。每个通常为 256-512KB,有时高达 1MB。

• L3 缓存具有最大的存储容量,通常为 32MB 或更多,但速度可能仅为系统内存的两倍。L3 缓存通常嵌

入在 CPU 中,但与内核分开。

cache的组织形式(index, way, set)

cache的术语概念

• index : 用白话理解,其实就是在一块cache中,一行一行的编号(事实是没有编号/地址的)

• Set :用index查询到的cache line可能是多个,这些index值一样的cacheline称之为一个set

• way:用白话来说,将cache分成了多个块(多路),每一块是一个way

• cache TAG :查询到了一行cache后,cachelne由 TAG + DATA组成

• cache Data :查询到了一行cache后,cachelne由 TAG + DATA组成

• cache Line 和 entry 是一个概念

cache的分配策略(alocation,write-through, write-back)

读分配(read allocation)

当CPU读数据时,发生cache缺失,这种情况下都会分配一个cache line缓存从主存读取的数据。默认情况下,cache都支持读分配。

写分配(write allocation)

当CPU写数据发生cache缺失时,才会考虑写分配策略。当我们不支持写分配的情况下,写指令只会更新主存数据,然后就结束了。当支持写

分配的时候,我们首先从主存中加载数据到cache line中(相当于先做个读分配动作),然后会更新cache line中的数据。

写直通(write through)

当CPU执行store指令并在cache命中时,我们更新cache中的数据并且更新主存中的数据。cache和主存的数据始终保持一致。

写回(write back)

当CPU执行store指令并在cache命中时,我们只更新cache中的数据。并且每个cache line中会有一个bit位记录数据是否被修改过,称之为dirty

bit(翻翻前面的图片,cache line旁边有一个D就是dirty bit)。我们会将dirty bit置位。主存中的数据只会在cache line被替换或者显示的clean

操作时更新。因此,主存中的数据可能是未修改的数据,而修改的数据躺在cache中。cache和主存的数据可能不一致。

cache hit/miss hint的概念

命中(Hit):

当处理器需要访问内存中的数据或指令时,首先会在缓存中查找该数据或指令。

如果缓存中已经包含了所需的数据或指令,则称为"命中"(hit),处理器可以直接从缓存中获取数据,无

需访问主存。

命中通常导致较快的访问速度,因为缓存具有更快的访问时间和更短的延迟。

未命中(Miss):

如果处理器在缓存中未找到所需的数据或指令,则称为"未命中"(miss)。

在发生未命中时,处理器需要从主存中获取所需的数据或指令,然后将其加载到缓存中,以便日后的访问。

未命中通常导致较长的访问延迟,因为需要从相对较慢的主存中加载数据。

命中和未命中的概念可以用来评估缓存系统的性能和效率。高命中率通常表示缓存系统能够有效地提高访

问速度,因为大部分数据都能在缓存中找到。而较高的未命中率可能表明缓存容量不足、替换策略不佳或

者访问模式不合理,需要进行性能优化。

cache的查询原理

cache的层级

cache缓存形式

cache的查询过程

先使用index去查询cache,然后再比较TAG,比较tag的时候还会检查valid标志位

歧义

歧义(ambiguity)也称Homonyms(同名异物)是指一个VA对应不同的PA。例如两个不同的进程,虚拟内

存的地址互相独立,两个不同进程中的相同虚拟内存地址会指向不同的物理内存地址。

歧义主要是因为virtual tag引起的。因为两个不同进程的相同virtual tag可能对应两个不同的physical tag。那么当进程发生切换时,新来的进程B在使用VIVT访问Cache时,很有可能把上一个进程的virtual tag给hit了!!但实际上对应的是不同的physical tag!!这种情况可以使用flush解决:即当发生进程切换时,将Cache flush(clean+invalid)掉,然后再切换到新进程。

同一地址数据(虚拟地址)缓存到了不同的cache中

重名/别名

重名(aliasing),也称Synonyms(同物异名):重名即指多个不同的VA共享同一个PA。

不同地址数据(虚拟地址)缓存到了相同的cache中

解决重名问题:

1、如引入一个新功能:page color

2、物理TAG从BIT12开始

怎样去维护多核多系统缓存的一致性

有三种机制可以保持一致性:

  1. 禁用缓存是最简单的机制,但可能会显着降低 CPU 性能。为了获得最高性能,处理器通过管道以高频率运行,并从提供极
    低延迟的缓存中运行。缓存多次访问的数据可显着提高性能并降低 DRAM 访问和功耗。将数据标记为"非缓存"可能会影响
    性能和功耗。
  2. 软件管理的一致性是数据共享问题的传统解决方案。在这里,软件(通常是设备驱动程序)必须清除或刷新缓存中的脏数
    据,并使旧数据无效,以便与系统中的其他处理器或主设备共享。这需要处理器周期、总线带宽和功率。
  3. 硬件管理的一致性提供了一种简化软件的替代方案。使用此解决方案,任何标记为"共享"的缓存数据将始终自动更新。该
    共享域中的所有处理器和总线主控器看到的值完全相同。

Cluster中的缓存一致性

同一个cluster中多core之间的缓存一致性由DSU(big.LITTLE叫SCU)来维护,遵循MESI协议。

多Master之间的缓存一致性

Master分为以下几类:

• ACE Master : 如 big.LITTLE cluster 或 DSU

cluster

• CHI Master : 如 big.LITTLE cluster 或 DSU

cluster

• ACE-lite Master: 如 GPU cluster

• I/O Device Master : 如 DMA

以下是多Master之间的缓存一致性的结论:

• 首先,CHI/ACE总线都是支持MESI协议数据传输的

• Master与I/O Device Master之间没有一致性,因为I/O Device没有链接到CCI/CMN缓存互联总线上。

• 多个ACE/CHI Master之间的缓存一致性,是否遵循MESI,要具体情况具体分析,简而言之就是:

(1) 如果两个Master都支持带MESI状态位,支持带有MESI信号的读写,那么这两个Master缓存一致性是遵从MESI协议的

(2) 如果有一个Master不支持带MESI状态位,那么这个Master就无法支持带有MESI信号的读写,那么这两个Master缓存一致性是不遵从MESI协议的

(3) Master的MESI状态位,是在该Master的cache的TAG中。

• ACE/CHI Master和ACE-lite Master之间的缓存一致性,是不遵从MESI协议的。这主要是因为ACE/CHI Master无法snoop ACE-lite Master的内存,而ACE-lite Master却可以snoop ACE/CHI Master的内存,总得来说,这不是一个完整的MESI协议。

两个DSU cluster的L3 cache中的TAG中,是有MESI比特位的,这两个DSU通过ACE/CHI 接口发起的读写是带有MESI信号的,所以他们是支持MESI协议的。

dynamIQ架构同一个core中的L1和L2 cache

dynamIQ架构core中的L1和L2 cache不存在缓存一致性的问题,但有分配和替换策略。

下DynamIQ架构中的cache中新增的几个概念:

• (1) Strictly inclusive: 所有存在L1 cache中的数据,必然也存在L2 cache中

• (2) Weakly inclusive: 当miss的时候,数据会被同时缓存到L1和L2,但在之后,L2中的数据可能会被替换

• (3) Fully exclusive: 当miss的时候,数据只会缓存到L1

其实inclusive/exclusive属性描述的正是是 L1和L2之间的替换策略,这部分是硬件定死的,软件不可更改的。

• L1 I-cache和L2之间是 weakly inclusive的

• L1 D-cache和L2之间是 strictly inclusive的

也就是说:

• 当发生D-cache发生miss时,数据缓存到L1 D-cache的时候,也会被缓存到L2 Cache中,当L2 Cache被替换时,L1 D-cache也会跟着被替换

• 当发生I-cache发生miss时,数据缓存到L1 I-cache的时候,也会被缓存到L2 Cache中,当L2 Cache被替换时,L1 I- cache不会被替换。

所以总结一下就是 : L1 和 L2之间的cache的替换策略,针对I-cache和D-cache可以是不同的策略,每一个core都有每一个core的做法,这部

分是硬件决定的,请查阅你使用core的TRM手册。

Mesi协议的范围

Mesi协议状态切换

Events:

• RH = Read Hit

• RMS = Read miss, shared

• RME = Read miss, exclusive

• WH = Write hit

• WM = Write miss

• SHR = Snoop hit on read

• SHI = Snoop hit on invalidate

• LRU = LRU replacement

• Bus Transactions:

• Push = Write cache line back to memory

• Invalidate = Broadcast invalidate

• Read = Read cache line from memory

cache的安全访问

cache中的安全比特;

首先看到core,core中有一个SCR寄存器,寄存器中有一个NS比特位可以表示当前core所处的是安全还是非安全,NS=1非安全,NS=0安全。寄存器的值只能EL3修改,因此只有双系统切换时(安全状态和非安全状态切换时,会经过ATF)才能修改。

core最后要访问memory,中间隔了一个TZC,TZC可以配置memory的权限,是Secure memory还是Non-Secure memory,还有一个的作用就是过滤,如果是非安全的cpu要访问Secure memory会被挡住,无法访问;如果是安全的cpu,TZC都会放行。

看第二步,如果是secure的cpu那么MMU必然就是Secure Transaction Regime,然后就要看entry中的NS比特位,如果NS为1就代表发起Non-Secure Access;如果NS为0,就代表发起Secure Access。;如果是Non-secure的cpu那么使用的MMU就是Non Secure Transaction Regime,下面也永远是Non-Secure Access,不用看NS比特位。

再回看第一步,如果cpu在访问内存时,已经在TLB中命中,就不会经过MMU的翻译,直接进行标号位1的路径,此时TLB的entry中有两个NSbit位,后面的NS就对应了第二步中entry的NS位,二者一致,就决定了接下来访问的安全状态。前面的NS代表了是Secure Transaction Regime还是Non Secure Transaction Regime。

页表entry中的NS比特位在软件中是可以修改的。

一个非安全侧的entry中NS=1,如果给它修改位0,那么可以访问安全的memory可以吗?答案是不可以的,因为是Non Secure Transaction Regime,它就不会看NS比特位,自然还是进行Non Secure Access。

如果在安全侧是secure Transaction Regime,那么访问的内存可以修改NS比特位吗?答案是可以的。

相关推荐
陈王卜11 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、12 分钟前
Spring Boot 注解
java·spring boot
java亮小白199717 分钟前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF23 分钟前
java Queue 详解
java·队列
武子康44 分钟前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
苏-言1 小时前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
界面开发小八哥1 小时前
更高效的Java 23开发,IntelliJ IDEA助力全面升级
java·开发语言·ide·intellij-idea·开发工具
草莓base1 小时前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
Allen Bright1 小时前
maven概述
java·maven