ARM 学习笔记(三)
参考文献:《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》
《ARM Cortex-A (ARMv7-A) Series Programmer’s Guide》
1、内存类型
ARMv7-A 处理器中,将 Memory 定义为几种类型(Memory Type):
- Strongly-ordered
- Normal
- Device
2、Normal memory
2.1 Non-shareable
Normal memory must also be designated either as Shareable or Non-Shareable. A region of Normal memory with the Non-Shareable attribute is one that is used only by this core. There is no requirement for the core to make accesses to this location coherent with other cores. If other cores do share this memory, any coherency issues must be handled in software. For example, this can be done by having individual cores perform cache maintenance and barrier operations.
——————《ARM Cortex-A (ARMv7-A) Series Programmer’s Guide》
对于 Normal memory 类型的内存区域:
-
必须指定为 Shareable 或 Non-Shareable
-
如果它被标记为 Non-Shareable:
- 硬件不会保证这块内存在多个核心之间的数据一致性
- 默认认为只有当前核心在使用这块内存
- 如果实际上多个核心访问这块内存,那就必须靠软件来保证一致性,比如通过缓存管理(清除/失效)、内存屏障(DMB/DSB/ISB)、通信协议等手段来同步数据
既然 Non-Shareable 需要手动维护一致性,那它存在的意义和优势是什么?
实际上,Non-Shareable 并不是没有用,而是出于以下几个考虑,它在某些场景下非常有意义:
✅ 一、性能更高
在多核系统中,如果你使用 Shareable memory(尤其是 SMP 系统中的 Inner Shareable):
- 每次访问缓存行都可能触发硬件级的 cache coherency 协议(如 MESI、MOESI 等);
- 这会引入额外的 总线/互联传输负担 和 延迟;
- 也可能导致 cache line bouncing,尤其当多个核频繁修改同一个变量时。
而使用 Non-Shareable memory:
- 硬件默认只在当前核心访问,不涉及其它核;
- 避免了不必要的 cache coherency 操作;
- 访问更快,cache 命中率更高,延迟更低;
- 适合性能敏感、访问频繁、无需共享的私有数据。
✅ 二、明确分工与控制
Non-Shareable 强制开发者:
- 明确哪些内存区域是只在本核使用的;
- 哪些区域需要小心处理共享和同步;
- 有助于提升系统结构的清晰度和可维护性;
- 对一些实时性要求高的系统(RTOS)非常有用,避免因不必要的一致性导致时间不确定性。
2.2 Inner Shareable, and Outer Shareable
A region of Normal memory with the Shareable attribute is one for which data accesses to memory by different observers within the same shareability domain are coherent
——————《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》
具有 Shareable 属性的 Normal memory 区域,其特点是:在同一共享域内的不同观察者对该内存的数据访问是一致的。
在 ARMv7 架构中,可共享属性(Shareability Attributes)用于定义一组观察者(Observers),使得 data or unified caches 对特定访问透明化。这些观察者的集合被称为可共享域(Shareability Domains),其具体行为由系统实现决定。以下通过示例说明其应用场景:
举一个案例:
某虚拟内存系统架构(VMSA)的实现包含 two clusters of processors,需满足以下要求:
- 对于每个 clusters :若数据访问标记为 Inner Shareable,则集群内所有处理器的 data or unified caches 对该访问透明(即缓存一致性自动维护)
- 两个 cluster 之间:
- 仅标记为 Inner Shareable 的访问无法跨集群维护缓存透明性
- 标记为 Outer Shareable 的访问则能在两个集群间实现缓存透明。此时,每个集群构成独立的 Inner Shareable 域,而整个子系统属于同一个 Outer Shareable 域。
若系统包含多个此类子系统,且子系统间的缓存互不透明,则每个子系统将形成独立的 Outer Shareable 域。
为什么需要分层设计?
设置两个层次的可共享性属性(Inner Shareable 和 Outer Shareable)意味着系统设计者可以减少对于不需要参与 Outer Shareable 域的共享内存区域的性能与功耗开销。
- 多级共享域的设计允许系统更灵活地控制共享粒度;
- 如果某块内存只在一个 CPU cluster 内共享,就设置为 Inner Shareable,避免跨 cluster 的 coherency 同步开销;
- 避免不必要的 Outer Shareable 标记 → 减少 coherency 机制触发 → 更高效、节能。
In a VMSA implementation, for Shareable Normal memory, whether there is a distinction between Inner Shareable and Outer Shareable is IMPLEMENTATION DEFINED
——————《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》
需要注意的是,在 VMSA(虚拟内存系统架构)的实现中,对于 Shareable 类型的 Normal memory,是否区分 Inner Shareable 和 Outer Shareable 是由具体实现决定的(实现自定义)。
对于 Shareable 类型的 Normal memory,Load-Exclusive 和 Store-Exclusive(即 LDREX/STREX)同步原语会考虑到同一 shareability 域内多个观察者可能同时访问该地址的情况
- ARM 的原子指令(如 LDREX/STREX)依赖于共享域概念;
- 若两个核在同一 Inner Shareable 域内,它们的原子操作会被视为相关;
- 如果不在同一共享域中,它们可能不会观察到彼此的修改 → 可能导致同步失败。
系统设计者可以使用 Shareable 属性来指定哪些 Normal memory 区域需要具备缓存一致性的要求。但为了便于软件移植,软件开发人员不能因为某块内存被标记为 Non-shareable,就假设多个处理器之间访问该内存一定是非一致性的。
- 也就是说,Non-shareable ≠ 一定不一致;
- 有些系统中,Non-shareable 的内存可能也通过某种方式被多个核缓存一致;
- 所以不能依赖 Non-shareable 来推导“多个核访问时不一致”的行为;
This architecture is written with an expectation that all processors using the same operating system or hypervisor are in the same Inner Shareable shareability domain
——————《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》
本架构(ARMv7-A)假设:所有运行在同一操作系统或同一 hypervisor 下的处理器,属于同一个 Inner Shareable 共享域。
2.3 Write-Through、Write-Back、Non-cacheable
在 ARMv7 架构中,除了 Shareability(可共享性)(Outer Shareable / Inner Shareable / Non-shareable)之外,Normal Memory(普通内存) 还需要设置 Cacheability(缓存属性),以决定 CPU 如何缓存该内存区域。
缓存属性主要分为以下三种:
- Write-Through Cacheable.
- A cache in which when a cache hit occurs on a store access, the data is written both to the cache and to main memory.
This is normally done via a write buffer, to avoid slowing down the processor
- A cache in which when a cache hit occurs on a store access, the data is written both to the cache and to main memory.
- Write-Back Cacheable.
- A cache in which when a cache hit occurs on a store access, the data is only written to the cache. Data in the cache
can therefore be more up-to-date than data in main memory. Any such data is written back to main memory when
the cache line is cleaned or reallocated. Another common term for a write-back cache is a copy-back cache
- A cache in which when a cache hit occurs on a store access, the data is only written to the cache. Data in the cache
- Non-cacheable
- 这个比较好理解,就是内存不带 cache,即对这块内存的访问,不会经过 cache
In some cases, the use of Write-Through Cacheable or Non-cacheable regions of memory might provide a better mechanism for controlling coherency than the use of hardware coherency mechanisms or the use of cache maintenance routines
——————《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》
在某些情况下,使用 Write-Through 缓存策略或 Non-cacheable 的内存区域,可能比依赖硬件缓存一致性机制或缓存维护指令,更适合作为控制一致性的一种机制。用合理的缓存策略(Memory Attributes)来“避免麻烦”,可能比“处理麻烦”更好。
3、 Device and Strongly-ordered memory
3.1 概念
在 ARMv7 架构中,设备内存(Device Memory) 和 强序内存(Strongly-ordered Memory) 通常用于映射内存映射外设(Memory-mapped Peripherals) 和 I/O 地址空间(I/O Locations)。
System peripherals will almost always be mapped as Device memory.
——————《ARM Cortex-A (ARMv7-A) Series Programmer’s Guide》
对于处理器显式访问标记为 Device 或 Strongly-ordered 的内存区域,需遵循以下规则:
- 访问大小严格匹配程序定义:所有访问必须按照程序中指定的数据宽度(如 8 位、16 位、32 位)执行,不可拆分或合并。
- 对 Device/Strongly-ordered 内存的每次访问(如 STR/LDR)必须作为一个完整单元执行。例如,32 位寄存器写入不可拆分为两个 16 位写入。
- 访问次数严格匹配程序定义:访问次数必须与程序指定的次数一致,不可因优化而增减。
- 编译器/硬件不得对这类内存进行访问合并(如合并相邻写操作)或冗余访问消除(如省略重复读操作)
硬件实现限制:
除非由于异常(Exception)(如中断、缺页)导致额外访问,否则处理器不得对 Device 或 Strongly-ordered 内存执行比程序顺序执行所规定的更多访问。本节将讨论异常对访问行为的允许影响。
从上面这些分析可以看出,ARMv7 对 Device/Strongly-ordered 内存的严格访问规则,确保了硬件寄存器和关键 I/O 操作的可预测性
下面再总结下,Device and Strongly-ordered memory 的一些特性:
- The architecture does not permit speculative data accesses to memory marked as Device or Strongly-ordered
- The architecture does not permit unaligned accesses to Strongly-ordered or Device memory
- Address locations marked as Device or Strongly-ordered are never held in a cache
- In the ARMv7 architecture, the core can re-order Normal memory accesses around Strongly-ordered or Device memory accesses
3.2 Device and Strongly-ordered 区别
第一个区别就是共享域的区别:
- a region of Device memory can be described as one of
- Outer Shareable Device memory.
- Inner Shareable Device memory.
- Non-shareable Device memory
- Strongly ordered memory regions are always shareable
关于 shareable,ARMv7 手册中有这样一段描述:
ARM deprecates the marking of Device memory with a shareability attribute other than Outer Shareable or Shareable. This means ARM strongly recommends that Device memory is never assigned a shareability attribute of Non-shareable or Inner Shareable
——————《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》
ARM 不建议你对 Device memory 设置为除了 “Outer Shareable” 或早期架构中通用的 “Shareable” 之外的任何 shareability 属性。尤其要避免使用 “Inner Shareable” 或 “Non-shareable”。
第二个区别就是完成时的区别:
The only architecturally-required difference between Device and
Strongly-ordered memory is that:
- A write to Strongly-ordered memory can complete only when it reaches the peripheral or memory component accessed by the write.
- A write to Device memory is permitted to complete before it reaches the peripheral or memory component accessed by the write.
上面这个说法是官方的意思,我理解一下,应该是 Strongly-ordered 不惜牺牲性能,去做保序的要求,一定要实际访问到外设,而 Device 类型的访问指令,可能还在路上(流水线中);
4、总结
4.1 关于 Inner Shareable, and Outer Shareable 的疑惑
关于 Inner Shareable, and Outer Shareable 属性,初学者经常会疑惑,这两个属性是从什么角度去定义的?从上面的分析来看,是从 cahce 一致性角度来定义的?直接上结论:
Shareable 确实和 cache 一致性密切相关。但 Shareable 的概念并不仅限于 Normal memory,它是一种通信语义或访问语义的定义,用来告诉处理器系统(包括缓存子系统、互联、总线和外设)这个区域是否可能被多个观察者访问。
例如,Device 类型的 memory,虽然不带 cache,但是也有 Inner Shareable, and Outer Shareable 属性。
- Device memory 是不能被缓存的,所以 Shareable 与否不会影响缓存行为。
- 但是在 Barrier(内存屏障)语义中,Shareable 的 Device memory 和 Non-shareable 的 Device memory 是不一样的:
DMB
等指令中的 Shareable,就是在说:“这个屏障要作用于 Shareable 范围内所有可能看到这个地址空间的主体。”- 比如 CPU 和 DMA 共享一个外设寄存器区,这个区域应该标记为 Device + Shareable,这样
DMB
可以保证这些外设访问的顺序一致性。
ARM 中的内存屏障指令 DMB
#define dma_wmb() dmb(oshst)
#define __smp_wmb() dmb(ishst)
- ISHST
DMB operation that waits only for stores to complete, and only to the inner shareable domain - OSHST
DMB operation that waits only for stores to complete, and only to the outer shareable domain
我们要明白,Shareable 并不等于“能被多个主体访问”,而是告诉系统:这个 memory 区域的访问顺序、一致性、barrier 等行为可能涉及多个 observer,系统必须尊重这点。
4.2 注意项
有一点非常重要:内存类型(如 Normal、Device、Strongly-Ordered)并不会对整个指令流的执行顺序产生可靠影响,它们只对内存访问的顺序产生影响。
- 指令的执行顺序 ≠ 内存访问的顺序
- 内存类型(如 Device、Normal)只能控制 load/store 的顺序
- 想要确保 某个写操作之后再执行某条指令 → 你得用 DMB, DSB, ISB 这类内存屏障指令
- 千万不要以为 “把内存设成 Strongly-Ordered,就等于所有指令顺序都被保留了” ——这只是内存访问顺序的保证,不是执行语义的全局保证