ARMv8-A非对齐数据访问支持(Alignment support)

目录

1,对齐传输和非对齐传输

2,AArch32 Alignment support

2.1 Instruction alignment 指令对齐

2.2 Unaligned data access 非对齐数据访问

 2.3 SCTLR.A  Alignment check enable

3,AArch64 Alignment support

3.1 Instruction alignment 指令对齐

3.2 Alignment of data accesses 对齐数据访问

3.3 普通Load 和Store指令(包括单寄存器和多寄存器)

3.4 Load-Exclusive/ Store-Exclusive 和Atomic 指令

3.7 FEAT_LSE2, Large System Extensions v2

3.8 对齐访问SP寄存器

3.9 对齐访问 PC寄存器


如果非对齐访问出错,可以考虑以下问题:

  • 当前架构是否支持非对齐数据访问。
  • 系统控制寄存器SCTLR.A是否打开对齐访问检查功能。
  • 使用的指令是否支持非对齐访问。
  • 操作的对象(SP,PC,Normal memory,Device memory)是否支持非对齐访问。
  • 当前系统所使用的是大端还是小端。
  • 1,对齐传输和非对齐传输

    参考Cortex-M3与Cortex-M4权威指南 第6.6章:

    由于存储器系统为32位的(至少从编程模型的角度来看是这样的),大小为32位(4 byte(字节)字节,或 1 word(字))或16位(2字节,或半字)可以是对齐也可以是不对齐的。

    对齐传输的意思是地址值为大小(以字节为单位)的整数倍。例如,字大小的对齐传输可以执行的地址为0x00000000、0x00000004、···、0x00001000、0x00001004等;类似地,半字大小的对齐传输可以执行的地址则为0x00000000、0x00000002、···、0x00001000、0x00001002等。
    对齐和非对齐传输的实例下图所示。

     一般来说,多数经典ARM处理器(如ARM7 /ARM9 /ARM10)都只允许对齐传输。这就意味着在访问存储器时,字传输地址的bit[1]和bit[0]为0,而半字传输地址的bit[0]为0。例如,字数据可位于0x1000或0x1004,而不能位于0x1001、0x1002或0x1003,对于半字数据,地址可以为 0x1000 或 0x1002,而不能为 0x1001。所有的字节传输都是对齐的。
    Cortex-M3和Cortex-M4处理器都支持普通存储器访问(如LDR、LDRH,STR以及STRH 指令)的非对齐数据传输。
    另外还有一些限制:

  • 多加载/存储指令不支持非对齐传输。
  • 栈操作指令(PUSH/POP)必须是对齐的。
  • 排他访问(如 LDREX 或 STREX)必须是对齐的,否则就会触发错误异常(使用错误)。
  • 位段操作不支持非对齐传输,因为其结果是不可预测的。
  • 当非对齐传输是由处理器发起时,它们实际上会被处理器的总线接口单元转换为多个对齐传输。这个转换是不可见的,因此应用程序开发人员无须考虑这个问题。

    不过,当产生非对齐传输时,它会被拆分为几个对齐传输,因此本次数据访问会花费更多的时钟周期,可能对需要高性能的情形不利。若追求更高的性能,确保数据处于合适的对齐是有必要的。
    多数情况下,C编译器不会产生非对齐传输,它只会在以下情况中出现:

    1. 直接操作指针。
    2. 包含非对齐数据的数据结构增加“_packed”属性。
    3. 内联/嵌入式汇编代码。

    2,AArch32 Alignment support

    2.1 Instruction alignment 指令对齐

    A32 指令是 字对齐的(word-aligned)。

    T32 指令是 半字对齐的(halfword-aligned)。

    2.2 Unaligned data access 非对齐数据访问

    在ARM A系列的实现中,通过一些Load/Store 指令是支持对Normal memory进行非对齐数据访问的。关于Normal memory和device memory的细节描述,可以参考博文:ARMv8内存属性与类型(Memory types and attributes)简介_arm 内存属性_SOC罗三炮的博客-CSDN博客

    如下图红框中所示,有一部分的 Load/Store指令可以实现非对齐访问,比如最常用的LDR与STR指令。当然前提是,系统控制寄存器SCTLR里的对齐检查位没有被enable,即SCTLR.A = 0:

  • 通过设置 SCTLR.A 位,可以控制除了Hyp mode外,其他任何模式下的对齐访问。
  • 通过设置HSCTLR.A 位,可以控制Hyp mode下的对齐访问。
  •  

     任何对Device memory的非对齐访问,都会产生对齐异常。

     2.3 SCTLR.A  Alignment check enable

    SCTLR.A位控制住系统对Normal memory的非对齐访问。在PL0或者PL1下,检查对齐错误:

  • SCTLR.A = 0, reset value,disable 对齐错误检查,在PL0或者PL1时,不会检查 Load/Store指令对一个或者多个寄存器进行操作时,访问的数据元素的大小与地址是否对齐。
  • SCTLR.A = 1,enable 对齐错误检查,在PL0或者PL1时,不会检查 Load/Store指令对一个或者多个寄存器进行操作时,访问的数据元素的大小与地址是否对齐。如果发现非对齐访问,会产生Data Abort 异常。
  • 此外,Load/store exclusive 和load-acquire/store-release指令自带对齐检查,所以会忽略SCTLR.A的值。

    3,AArch64 Alignment support

    3.1 Instruction alignment 指令对齐

    A64 指令是 字对齐的(word-aligned)。

    3.2 Alignment of data accesses 对齐数据访问

    同A32一样,任何对Device memory属性的非对齐访问,都会造成对齐错误,产生Data Abort异常。

     对于Normal memory的非对齐访问,其行为取决于:

  • 内存访问的指令(load、store)
  • 被访问的内存的内存属性(Normal 或者Device)
  • SCTLR_ELx.{A, nAA}的值,是否打开对齐访问检查。
  • FEAT_LSE2是否实现。
  • 3.3 普通Load 和Store指令(包括单寄存器和多寄存器)

    对于 普通的Load 和Store指令,无论是单寄存器操作还是多寄存器操作,如果被访问的地址与被访问的数据元素的大小不一致(非对齐访问),则:

  • 如果SCTLR_ELx.A = 1,将会产生一个对齐错误。
  • 如果SCTLR_ELx.A = 0,将执行非对齐访问(Normal memory)。
  • 3.4 Load-Exclusive/ Store-Exclusive 和Atomic 指令

    对于Load-Exclusive/ Store-Exclusive 和Atomic 指令,如果SCTLR_ELx.A = 1,将会产生一个对齐错误。

    如果SCTLR_ELx.A = 0,这取决于FEAT_LSE2,具体分析可以查看文档:DDI0487G_a_armv8_arm.pdf。

    3.7 FEAT_LSE2, Large System Extensions v2
     

    FEAT_LSE2为 load和store操作引入 单次拷贝原子性需求(single-copy atomicity requirements)以及对齐访问需求(alignment requirements)。

  • This feature is supported in AArch64 state only.
  • This feature is OPTIONAL in Armv8.2 implementations.
  • This feature is mandatory in Armv8.4 implementations
  • 可通过ID_AA64MMFR2_EL1的AT位来查看是否实现了该属性。

    与对齐的访问相比,未对齐的访问通常需要额外的周期(cycles)才能完成。

    3.8 对齐访问SP寄存器

    64 bit宽的Stack Pointer 寄存器,堆栈指针需要16个byte对齐。

    当堆栈指针被用作计算的基址时,不管指令应用了任何偏移量,其中堆栈指针的[3:0]位不是0b0000,这就是非对齐的堆栈指针。处理器可以配置为:如果load/store指令使用了未对齐的堆栈指针,处理器将生成栈指针未对齐异常。

    伪代码如下:

     通过判断 SCTLR的 SA0或者SA位是否为0,从而决定是否产生栈指针非对齐异常。

    3.9 对齐访问 PC寄存器

    64 bit宽的Program Counter 寄存器里保存着当前执行的指令的地址。如果执行A64 指令的时候不是 字对齐(word-aligned),将会产生PC 对齐错误。

    PC对齐检查将生成一个与指令获取相关的PC对齐错误异常,在AArch64状态时,试图从架构上执行一条指令,该指令是用未对齐的PC获取的。非对齐的PC是指PC的[1:0]位不是0b00,也就是地址需要以0、4 、 8 、c结尾,比如PC可以为0x1000或0x1004,而不能为0x1001、0x1002或0x1003

    一个PC 非对齐异常将会 把Exception Syndrome Register (ESR)寄存器的EC 位写入 0x22,并且会产生一系列的错误。

    检查PC非对齐异常的伪代码如下:

     

     

    参考文章: 

    一文带你深入了解《C语言对齐与非对齐访问》(ARM指令集)_对齐访问和非对齐访问_狂奔De鸵鸟的博客-CSDN博客

    物联沃分享整理
    物联沃-IOTWORD物联网 » ARMv8-A非对齐数据访问支持(Alignment support)

    发表评论