本文主要从应用的角度介绍ARMV8的编程模型和存储模型
从应用的角度看到的ARM处理器元素:
可见的元素(寄存器/指令) |
说明 |
可见的寄存器 |
R0-R30、SP、 PC、 V0-V31、 FPCR、 FPSR |
可见的PSTATE位 |
NZCV DAIF |
可见的系统寄存器 |
Cache ID registers Debug registers Performance Monitors registers Thread ID registers Timer registers |
性能监控支持 |
可通过高一级的异常级别修改PMUSERENR_EL0寄存器来使能EL0的性能监控功能 |
异常处理 |
通过SVC指令引发系统调用异常(异常处理是由高于EL0的异常级别执行的) |
等待中断与等待事件 |
WFI和WFE指令 |
Yield指令 |
为提高整体性能,某个线程让给其它线程,用于多线程执行下的性能优化 |
Cache管理 |
很少的cache管理指令供EL0使用,通过高异常级别设置SCTLR_EL1,来使能cache管理指令 |
Debug事件 |
应用级软件对大部分Debug事件不可见,仅有的包括: BKPT指令:引起BKPT指令事件发生; DBG指令:给debug系统提供暗示?? HLT指令:引发进入debug状态 |
表 AARCH64下从应用的角度可以看到的寄存器或指令集
主要用于大块内存的读写、只读操作;
禁止随机读写操作,如大部分的IO寄存器
内存系统的实现非常依赖各个处理器的具体实现,ARMV8体系结构定义了与内存系统交互的应用级接口,包括带有多级caches的存储层级系统
Cache是一种高速的存储块。包含很多的存储项,每个存储项包含主存的地址(称为tag)和数据信息。利用时间局部性和空间局部性提高了内存的访问速度;
Cache line: 将cache分成一些固定大小的存储空间, 这些存储空间叫做Cache Line.
Cache hit:cache命中,访问的数据存在于cache中;
Cache miss:cache失效,访问的数据不在cache中;
PoU是一个存储层级的点,data cache, instruction cache和translation table walks看到的都是相同的copy. 那么这个点就是该PE的Point of Unification。
假设一个4核cpu,每个core都有自己的L1 instruction cache和L1 Data cache,所有的core共享L2 cache。在这样的一个系统中,PoU就是L2 cache,只有在该点上,特定PE的instruction cache、data cache和translation table walk硬件单元访问memory的时候看到的是同一个copy
可以认为是Point of System,它和PoU的概念类似,只不过PoC是以系统中所有的agent(bus master,又叫做observer,包括CPU、DMA engine等)为视角
这些agents在进行memory access的时候看到的是同一个copy的那个“点”。例如上一段文章中的4核cpu例子,如果系统中还有一个DMA controller和main memory(DRAM)通过bus连接起来,在这样的一个系统中,PoC就是main memory这个level,因为DMA controller不通过cache访问memory,因此看到同一个copy的位置只能是main memory了。
用来描述多处理器系统中的存储层级属性.
Cacheablity:定义了是否某段内存被指定给了一个cache;
Shareablity:定义了某段内存位置在整个系统中是共享的. 指当前内存页表项的数据是否可以同步到其它CPU上,多核CPU调用带有该属性页表项的数据,一旦某个CPU修改了数据,那么系统将自动更新到其它CPU的数据拷贝,实现内存数据一致性
体系结构定义了一组cache维护指令,应用软件可以用来管理cache一致性。运行在EL1或更高异常等级的软件可以使能/禁用EL0的一些功能:
(1)SCTLR_EL1.UCI == 1
运行在EL0的软件可以访问数据cache维护指令(DC CVAC/DC CVAU/DC CIVAC)和指令cache维护指令(IC IVAU)
(2)SCTLR_EL1.UCT== 1
运行在EL0的软件可以访问cache type register.
(3)SCTLR_EL1.DZE== 1
运行在EL0的软件可以访问1数据cache zero指令(DC ZVA)
可以通过如下方法解决数据一致性问题:
(1)不使用cache。使用non-cached memory,直写memory; 不要使能系统中的cache;
(2)使用cache维护指令来管理软件中的一致性问题;
(3)通过使用硬件一致性机制来保证不同共享域的观察者所见的内存访问是一致的;
下面以修改一条指令为例说明如何保证数据一致性:
(1)STR Wt, [Xn]
将新的修改的指令存入Xn指向的内存(实际存入了data cache);
(2)DC CVAU, Xn
将data cache中数据真正刷入内存;
(3)DSB ISH
等前面的DC指令执行完成后再执行后面的指令;
(4)IC IVAU, Xn
无效指令cache到PoU的数据;
(5)DSB ISH
等前面的IC指令执行完成;
(6)ISB
将指令或数据提前放入cache来加快内存访问速度
A64指令必须是word(32bits)对齐,试图从一个PC未对齐的位置取指会引发PC对齐错误
必须对齐,否则会引发unalignment fault;
(1) Load-Exclusive/Store-Exclusive and Load-Acquire/Store-Release
任何访问地址没有对齐到访问元素将会产生对齐错误
(2) 其它情况
a). SCTLR_ELx.A==1,使能对齐检查,任何访问地址没有对齐到元素将会产生对齐错误;
b). SCTLR_ELx.A==0,不使能对齐检查,支持对非对齐的访问
注:SCTLR_EL1.A只能在EL1访问,设置的EL0和EL1的对齐检查
(1) 如果从Non-secure EL0或EL1访问,如果齐检查失败发生在地址转换的第一阶段,异常将传递给EL1;
(2) 如果从Non-secure EL0或EL1访问,如果对齐检查失败发生在地址转换的第二阶段,异常将传递给EL2;
(3) 对于除(1)(2)的其它情况,如果对齐检查失败,异常将传递给能处理此异常的最低异常级别,但要遵循异常发生时异常等级不能降低的原则:
EL0或EL1下的对齐异常会传给EL1;
EL2下的对齐异常会传给EL2;
EL3下的对齐异常会传给EL3;
(1)除字节外,单次拷贝不能保证是原子的;
(2)相比于对齐访问,非对齐访问会花费额外的时钟;
(3)非对齐访问会跨越页边界,执行两次访问,会比单次访问更容易引发data abort异常
大端存储:高位存在低地址,低位存在高地址;
小端存储:高位存在高地址,低位存在低地址;
A64指令固定为32bit,且为小端存储
在EL1或更高的异常级别通过配置SCTLR_EL1.E0E来决定EL0下数据为大端还是小端
见 ARMV8体系结构简介:AArch64应用级体系结构之Atomicity 一文
当PE正在修改指令时,要保证没有其它PE在执行此指令;
单处理器:PE修改了内存(cached)中的指令,需要清data cache,无效指令cache;
多处理器:通过广播告知所有PE无效指令cache,每个PE需通过ISB等待修改操作完成
见 ARMV8体系结构简介:AArch64应用级体系结构之Memory order 一文
见 ARMV8体系结构简介:AArch64应用级体系结构之Memory Type and Attributes 一文
见 ARMV8体系结构简介:AArch64应用级体系结构之Synchronization and semapores 一文
[1] DDI0487A_k_armv8_arm_iss10775.pdf
[2] ARMv8之Atomicity