[architecture]-DMB、DSB 和 ISB指令的深度解读
快速鏈接:
.
👉👉👉 個(gè)人博客筆記導(dǎo)讀目錄(全部) 👈👈👈
術(shù)語:
DMB – Data Memory Barrier
DSB – Data Synchronization Barrier
ISB – Instruction Synchronization Barrier
思考:
內(nèi)存屏障到底屏的什么?
為什么要用內(nèi)存屏障? 亂序執(zhí)行是怎樣的一個(gè)亂序?為什么會(huì)出現(xiàn)亂序
目錄
- 1、背景
- 2、ARM是怎樣執(zhí)行指令的三級(jí)流水
- 3、DMB/DSB/ISB 指令的介紹
- 4、不同的觀察者(observers)
- 5、Barrier Qualifiers(限定符)
- 6、示例
- 6.1、Mail box example
- 6.2 Speculation across barriers
- 6.3 Memory mapped peripherals
- 6.4 ISB示例
- 7. One‐Way Barriers
- 8、Linux Kernel Barries API
1、背景
DMB、DSB、ISB 看似三條簡(jiǎn)單的指令,網(wǎng)上有著一大堆博客、也有著一大堆的Linux Kernel教程,都會(huì)介紹這幾個(gè)命令,簡(jiǎn)而言之,分別就是:數(shù)據(jù)內(nèi)存屏障、數(shù)據(jù)同步屏障、指令同步屏障…
雖然看似很簡(jiǎn)單,但是真的很難理解,因?yàn)槠渲刑N(yùn)含著豐富的硬件基礎(chǔ)原理,今年我們就剖開事務(wù)看本質(zhì),從最底層到應(yīng)用實(shí)列,來理解這幾個(gè)命令。
2、ARM是怎樣執(zhí)行指令的三級(jí)流水
如下圖所示,ARM有三級(jí)流水線,分別是: 取指、譯碼、發(fā)射(issue)&執(zhí)行
在取指、譯碼階段,是有序的。而是發(fā)射(issue)階段,是無序的。
以上只是當(dāng)前主流的架構(gòu) ,但并不意味著所有的Core都是這樣的。如下貼出了一個(gè)表格,注意其中的Out of order、In order, 這里所說的也正式issue(發(fā)射)階段的有序或亂序
這個(gè)時(shí)候,可能就會(huì)有同學(xué)發(fā)問了:對(duì)于In order的core,是不是就不需要DSB/DMB/ISB這樣的指令了呢?
當(dāng)然不是,因?yàn)榇藭r(shí)還要去看,你是不是multi-pipeline? 還是single-pipeline
例如:A53、A7等,它們雖然是In order,但也是dual-pipeline
(1)A53 : In-order pipeline with symmetric dual-issue of most instructions
(2) A7的pipeline如下所示,具有5個(gè)端口(Integer、Multiply、Floating、Dual Issue、Load/Store),A7具有可同時(shí)提供到這些端口的兩條指令的組合,即可以發(fā)出兩條指令的有序流水線
所以,盡管你是In order的,但是你可以同時(shí)發(fā)出兩條指令的流水線,后發(fā)射的也是有可能先執(zhí)行完成的,所以整體來看還是無序的。即DMB/DSB/ISB還是需要的。
其實(shí),我發(fā)現(xiàn)一個(gè)很有趣的現(xiàn)象:
- 只要in-order的core,都是dual-pipeline
- 只要是outer-of-order的core,都是single pipeline
in-order:順序流水線, 是指處理器按照它們?cè)趦?nèi)存中出現(xiàn)的順序發(fā)出指令(issue)。下一條指令不會(huì)早于上一條指令發(fā)出,但是如果是多pipeline的,那么一次還是可以發(fā)送多條指令的
out-of-order: 亂序流水線, 是指處理器可以不按照指令在內(nèi)存中的順序發(fā)出(issue)指令
in-order 和 out-of-order的區(qū)別如下所示:
3、DMB/DSB/ISB 指令的介紹
由于很多處理器的 Out-of-order execution(亂序執(zhí)行)和 speculative execution(推測(cè)執(zhí)行), 所以也意味著你的訪問內(nèi)存可能沒有按照程序順序進(jìn)行 。 在大多數(shù)的情況下,我們都無需關(guān)心訪問的順序,但有些情況下卻是不得不考慮,例如:
- 在不同的threads/cores之間共享數(shù)據(jù)
- 傳遞數(shù)據(jù)給peripherals, 如DMA操作
- 修改指令所在的內(nèi)存,如load一個(gè)程序到RAM
- 修改內(nèi)存管理方案,如context switching
ARM Architecture提供了三個(gè)同步指令:
- DMB – Data Memory Barrier 數(shù)據(jù)內(nèi)存屏障
確保位于 “DMB 指令前的所有顯式內(nèi)存訪問” 早于 " DMB 指令后的顯示內(nèi)存訪問"( 注意:data cache的操作也被看做是顯示的訪問) - DSB – Data Synchronization Barrier 數(shù)據(jù)同步屏障
確保
(1)位于此指令前的所有顯式內(nèi)存訪問均完成。
(2)位于此指令前的所有緩存、跳轉(zhuǎn)預(yù)測(cè)和 TLB 維護(hù)操作全部完( 注意:**cache/TLB/branch的維護(hù)操作是廣播,那么要等待廣播的完成) - ISB – Instruction Synchronization Barrier 指令同步屏障
確保提取時(shí)間晚于 ISB 指令的指令能夠檢測(cè)到 ISB 指令執(zhí)行前就已經(jīng)執(zhí)行的上下文更改操作的執(zhí)行效果
很明顯數(shù)據(jù)存儲(chǔ)屏障(DMB)比數(shù)據(jù)同步屏障(DSB)限制少。 下面也舉了一些代碼示例,注意看注釋.
LDR X0, [X1] ? //Must be seen by memory system before STR DMB SY ADD X2, #1 ? //May be executed before or after memory system sees LDR STR X3, [X4] ? //Must be seen by memory system after LDR DC CVAC, X5 LDR X0, [X1] ? //Effect of data cache clean might not be seen by this instruction DMB SY LDR X2, [X3] ? //Effect of data cache clean will be seen by this instruction DC ISW ? //Operation must have completed before DSB can complete STR X0, [X1] ? //Access must have completed before DSB can complete DSB SY ADD X2, X2, #3 ? //Cannot be executed until DSB completes4、不同的觀察者(observers)
core的instruction interface、 data interface、MMU table walker 被看做不同的觀察者(observers)
如下一段代碼中,有兩個(gè)觀察者, 由于亂序讀寫內(nèi)存,可能會(huì)導(dǎo)致I-cache 操作的是舊的數(shù)據(jù)
DC CVAU, X0 ; //Operations are executed in any order IC IVAU, X0 ; //despite address dependency. Could lead to I cache re-fetching old values!加上DSB完美解決上述問題
DC CVAU, X0 DSB ISH IC IVAU, X0 //I cache now guaranteed to see new values5、Barrier Qualifiers(限定符)
(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
6.2 Speculation across barriers
6.3 Memory mapped peripherals
6.4 ISB示例
Context‐changing 操作:
- Cache、TLB、分支預(yù)測(cè)維護(hù)操作
- 系統(tǒng)寄存器的改變(如 SCTLR_EL1,TCR_EL1、TTBRn_EL1…)
Context‐changing只有在下面事件之后才會(huì)被確認(rèn):
- taking一個(gè)異常
- 退出一個(gè)一次
- ISB
Instruction Synchronization Barrier (ISB)
- 確保ISB之后的指令 可以看到 ISB之前的Context‐changing
- 確保ISB之后的Context‐changing,僅影響ISB之后的指
7. One‐Way Barriers
-
Load‐Acquire (LDAR)
(1) 所有在LDAR之后的內(nèi)存訪問,必需在LDAR之后被觀察到
(2) 所有在LDAR之前的內(nèi)存訪問,不受影響 -
Store‐Release (STLR)
(1)所有在STLR之前的內(nèi)存訪問 ,必需在STLR之前被觀察到
(2) 所有在STLR之后的內(nèi)存訪問,不受影響
思考: 在Linux Kernel中你是怎樣讀寫寄存器的? 調(diào)用的哪個(gè)接口?
答案:正是使用的ldar指令:
但是在一些代碼中,如ATF等,也許是直接賦值的,這種方式顯然沒有l(wèi)dar更嚴(yán)謹(jǐn)
8、Linux Kernel Barries API
使用方式,例如:
總結(jié)
以上是生活随笔為你收集整理的[architecture]-DMB、DSB 和 ISB指令的深度解读的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [architecture]-处理器的顺
- 下一篇: [architecture]-spin_