88

baron · 2月24日 · 江苏

DMB、DSB 和 ISB指令的深度解读

术语: DMB – Data Memory Barrier DSB – Data Synchronization Barrier ISB – Instruction Synchronization Barrier
思考:内存屏障到底屏的什么?为什么要用内存屏障?乱序执行是怎样的一个乱序?为什么会出现乱序?

1、背景

DMB、DSB、ISB 看似三条简单的指令,网上有着一大堆博客、也有着一大堆的Linux Kernel教程,都会介绍这几个命令,简而言之,分别就是:数据内存屏障、数据同步屏障、指令同步屏障..... 虽然看似很简单,但是真的很难理解,因为其中蕴含着丰富的硬件基础原理,今年我们就剖开事务看本质,从最底层到应用实列,来理解这几个命令。

2、ARM是怎样执行指令的三级流水

如下图所示,ARM有三级流水线,分别是: 取指、译码、发射(issue)&执行image.png取指、译码阶段,是有序的。而是发射(issue)阶段,是无序的。

以上只是当前主流的架构 ,但并不意味着所有的Core都是这样的。如下贴出了一个表格,注意其中的 Outof orderInorder, 这里所说的也正式issue(发射)阶段的有序或乱序image.png

这个时候,可能就会有同学发问了:对于 Inorder的core,是不是就不需要DSB/DMB/ISB这样的指令了呢?当然不是,因为此时还要去看,你是不是multi-pipeline?还是single-pipeline 例如:A53、A7等,它们虽然是 Inorder,但也是 dual-pipeline(1) A53:In-order pipelinewithsymmetric dual-issue of most instructions(2) A7的pipeline如下所示,具有5个端口(Integer、Multiply、Floating、Dual Issue、Load/Store),A7具有可同时提供到这些端口的两条指令的组合,即可以发出两条指令的有序流水线
image.png
所以,尽管你是 Inorder的,但是你可以同时发出两条指令的流水线,后发射的也是有可能先执行完成的,所以整体来看还是无序的。即DMB/DSB/ISB还是需要的。

其实,我发现一个很有趣的现象:

  • 只要in-order的core,都是dual-pipeline
  • 只要是outer-of-order的core,都是single pipeline

in-order:顺序流水线, 是指处理器按照它们在内存中出现的顺序发出指令(issue)。下一条指令不会早于上一条指令发出,但是如果是多pipeline的,那么一次还是可以发送多条指令的out-of-order: 乱序流水线, 是指处理器可以不按照指令在内存中的顺序发出(issue)指令

in-orderout-of-order的区别如下所示:
image.png

3、DMB/DSB/ISB 指令的介绍

由于很多处理器的 Out-of-order execution(乱序执行)和 speculative execution(推测执行), 所以也意味着你的访问内存可能没有按照程序顺序进行 。在大多数的情况下,我们都无需关心访问的顺序,但有些情况下却是不得不考虑,例如:

  • 在不同的threads/cores之间共享数据
  • 传递数据给peripherals, 如DMA操作
  • 修改指令所在的内存,如load一个程序到RAM
  • 修改内存管理方案,如context switching

ARM Architecture提供了三个同步指令:

  • DMB – Data Memory Barrier 数据内存屏障 确保位于 “DMB 指令前的所有显式内存访问” 早于 " DMB 指令后的显示内存访问"( 注意:data cache的操作也被看做是显示的访问)
  • DSB – Data Synchronization Barrier 数据同步屏障 确保 (1)位于此指令前的所有显式内存访问均完成。(2)位于此指令前的所有缓存、跳转预测和 TLB 维护操作全部完( 注意:**cache/TLB/branch的维护操作是广播,那么要等待广播的完成)
  • ISB – Instruction Synchronization Barrier 指令同步屏障 确保提取时间晚于 ISB 指令的指令能够检测到 ISB 指令执行前就已经执行的上下文更改操作的执行效果

很明显数据存储屏障(DMB)比数据同步屏障(DSB)限制少。下面也举了一些代码示例,注意看注释.

image.png

4、不同的观察者(observers)

core的instruction interface、 data interface、MMU table walker 被看做不同的观察者(observers)

如下一段代码中,有两个观察者, 由于乱序读写内存,可能会导致 I-cache 操作的是旧的数据

image.png

5、Barrier Qualifiers(限定符)

image.png

(1)、Shareability domain:

  • Full System
  • Outer Shareable
  • Inner Shareable
  • Non‐shareable

(2)、Accesses for which the barrier operates (before – after):

  • Load – Load/Store (new to Armv8‐A)
  • Store – Store
  • Any – Any

6、示例

6.1、Mail box example

image.png

6.2 Speculation across barriers

image.png

6.3 Memory mapped peripherals

image.png

6.4 ISB示例

Context‐changing 操作:

  • Cache、TLB、分支预测维护操作
  • 系统寄存器的改变(如 SCTLREL1,TCREL1、TTBRn\_EL1...)

Context‐changing只有在下面事件之后才会被确认:

  • taking一个异常
  • 退出一个一次
  • ISB

Instruction Synchronization Barrier (ISB)

  • 确保ISB之后的指令 可以看到 ISB之前的Context‐changing
  • 确保ISB之后的Context‐changing,仅影响ISB之后的指

image.png

7. One‐Way Barriers

image.png

  • Load‐Acquire (LDAR) (1) 所有在LDAR之后的内存访问,必需在LDAR之后被观察到 (2) 所有在LDAR之前的内存访问,不受影响
  • Store‐Release (STLR) (1)所有在STLR之前的内存访问 ,必需在STLR之前被观察到 (2) 所有在STLR之后的内存访问,不受影响
思考: 在Linux Kernel中你是怎样读写寄存器的?调用的哪个接口?答案:正是使用的ldar指令:
image.png
但是在一些代码中,如ATF等,也许是直接赋值的,这种方式显然没有ldar更严谨
image.png

8、Linux Kernel Barries API

![]image.png

使用方式,例如:
image.png

作者:baron
文章来源:ARM精选

推荐阅读

欢迎关注ARM精选专栏, 欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。

image.png

推荐阅读
关注数
9332
内容数
48
ARMv8/ARMv9架构、SOC架构、Trustzone/TEE安全、终端安全、SOC安全、ARM安全、ATF、OPTEE等
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息