[隨筆]DBG、DMB、DSB 和 ISB -幾條不常用的ARM指令

DBG、DMB、DSB 和 ISB


調試指令、數據內存屏障指令、數據同步屏障指令和指令同步屏障指令。


語法
DBG{cond} {#option}

DMB{cond} {option}

DSB{cond} {option}

ISB{cond} {option}

其中:

cond
是一個可選的條件代碼(請參閱條件執行)。

option
對提示操作的可選限制。

用法
這些是提示指令。 是否實現這些指令是可選的。 只要其中任何一個指令未實現,則與 NOP 效果相同。


DBG

調試提示可向調試系統及其相關係統發送提示。 有關這些系統如何使用此指令的信息,請參這些系統的文檔。

DMB

數據內存屏障可作爲內存屏障使用。 它可確保會先檢測到程序中位於 DMB 指令前的所有顯式內存訪問指令,然後再檢測到程序中位於DMB 指令後的顯式內存訪問指令。它不影響其他指令在處理器上的執行順序。

option 的允許值爲:

SY
完整的系統DMB 操作。 這是缺省情況,可以省略。

DSB

數據同步屏障是一種特殊類型的內存屏障。 只有當此指令執行完畢後,纔會執行程序中位於此指令後的指令。 當滿足以下條件時,此指令纔會完成:

位於此指令前的所有顯式內存訪問均完成。

位於此指令前的所有緩存、跳轉預測和 TLB 維護操作全部完成。

允許的值爲:

SY
完整的系統 DSB 操作。 這是缺省情況,可以省略。

UN
只可完成於統一點的DSB 操作。

ST
存儲完成後纔可執行的DSB 操作。

UNST
只有當存儲完成後纔可執行的DSB 操作,並且只會完成於統一點。

ISB

指令同步屏障可刷新處理器中的管道,因此可確保在 ISB 指令完成後,才從高速緩存或內存中提取位於該指令後的其他所有指令。這可確保提取時間晚於ISB 指令的指令能夠檢測到 ISB 指令執行前就已經執行的上下文更改操作的執行效果,例如更改ASID 或已完成的 TLB 維護操作,跳轉預測維護操作以及對 CP15 寄存器所做的所有更改。

此外,ISB 指令可確保程序中位於其後的所有跳轉指令總會被寫入跳轉預測邏輯,其寫入上下文可確保 ISB 指令後的指令均可檢測到這些跳轉指令。這是指令流能夠正確執行的前提條件。

option 的允許值爲:

SY
完整的系統DMB 操作。 這是缺省情況,可以省略。

體系結構
這些 ARM 和 32 位 Thumb 指令可用於 ARMv7。

這些指令均無 16 位 Thumb 版本。


訪問存儲器指令

編譯器不能用C語言直接生成的主存儲器指令是用於裝載和存儲的專用指令(LDREX和STREX)。這些指令常常專用於存儲器的存取操作,例如在不同的線程之間提供人工干預操作。

屏蔽指令
Cortex-M3,這種內核支持許多屏蔽指令。在下一個指令或者事件開始執行以前,這些屏蔽指令常常用於確保必然事件執行完成。
在處理器內部,指令同步屏蔽(ISB)刷新流水線;以致於這個指令執行完以後,緊接着從緩存或者存儲器取出指令表。這個表會改變這個系統,例如MPU立即生效。
數據同步屏蔽(DSB)指令作爲一種特殊的存儲器屏蔽指令。訪問外部存儲器操作完成之前,執行完成數據同步屏蔽指令(DSB)。執行數據同步屏蔽指令,在該指令沒有完成以前不再執行任何指令——換句話說,執行完成所有的掛起操作。
數據存儲屏蔽(DMB)指令作爲一種存儲器屏蔽指令。數據存儲屏蔽(DMB)指令和數據同步屏蔽(DSB)指令有微小的差別。數據存儲屏蔽(DMB)指令確保:數據同步屏蔽(DSB)指令執行完成之前,訪問任意存儲器;執行數據同步屏蔽(DSB)指令後,緊接着執行訪問任意存儲器操作。
如例8所示,典型MPU代碼的一部分顯示如何這些屏蔽指令。用嵌入彙編完成一個小的功能,每個功能都含有一條屏蔽指令。編譯時鏈接器將連接這些功能。
例8用預處理指令使用屏蔽指令的範例

/*pseudo_intrinsics.c */
/*Small embedded assembly functions for barrier instructions*/
/*Link with armlink --inline ... */
__asmvoid __ISB(void)
{
    ISB
    BXlr
}
__asmvoid __DSB(void)
{
    DSB
    BXlr
}
/*scs.c - Initialize System Control Space registers */
voidSCS_init(void)
{
    /*Code to configure the MPU regions inserted here
    …
    */
    /*Enable the MPU */
    SCS.MPU.Ctrl|= 1;
    /*Force Memory Writes before continuing */
    __DSB();
    /*Flush and refill pipline with updated permissions */
    __ISB();
}

彙編語言:指令隔離(barrier)指令和存儲器隔離指令

CM3 中的另一股新鮮空氣是一系列的隔離指令(亦可以譯成“屏障”、“路障”,可互換使用——譯者 注)。它們在一些結構比較複雜的存儲器系統中是需要的(典型地用於流水線和寫緩衝——譯者注)。在 這類系統中,如果沒有必要的隔離,會導致系統發生紊亂危象(race condition),(相當於數電中的“競爭 與冒險”——譯者注).

舉例來說,如果可以在運行時更改存儲器的映射關係或者內存保護區的設置,(通過寫 MPU 的寄存 器),就必須在更改之後立即補上一條 DSB 指令(數據同步指令)。因爲對 MPU 的寫操作很可能會被放 到一個寫緩衝中。寫緩衝是爲了提高存儲器的總體訪問效率而設的,但它也有副作用,其中之一,就是 會導致寫內存的指令被延遲幾個週期執行,因此對存儲器的設置不能即刻生效,這會導致緊臨着的下一 條指令仍然使用舊的存儲器設置——但程序員的本意顯然是使用新的存儲器設置。這種紊亂危象是後患 無窮的,常會破壞未知地址的數據,有時也會產生非法地址訪問 fault。紊亂危象還有其它的表現形式, 後續章節會一一介紹。CM3 提供隔離指令族,就是要消滅這些紊亂危象(在有些講解計算機體系體系結 構的書中,這類紊亂危象也被稱爲“存儲器相關”——譯註)。

CM3 中共有3 條隔離指令,如表4.27 所列

表4.27 隔離指令

指令名

功能描述

DMB

數據存儲器隔離。DMB 指令保證: 僅當所有在它前面的存儲器訪問操作

都執行完畢後,才提交(commit)在它後面的存儲器訪問操作。

DSB

數據同步隔離。比 DMB 嚴格: 僅當所有在它前面的存儲器訪問操作

都執行完畢後,才執行在它後面的指令(亦即任何指令都要等待存儲器訪 問操作——譯者注)

ISB

指令同步隔離。最嚴格:它會清洗流水線,以保證所有它前面的指令都執

行完畢之後,才執行它後面的指令。

DMB 在雙口 RAM 以及多核架構的操作中很有用。如果 RAM 的訪問是帶緩衝的,並且寫完之後

馬上讀,就必須讓它“喘口氣”——用 DMB 指令來隔離,以保證緩衝中的數據已經落實到 RAM 中。 DSB 比 DMB 更保險(當然也是有執行代價的),它是寧可錯殺也不漏網——清空了寫緩衝,使得任 何它後面的指令,不管要不要使用先前的存儲器訪問結果,通通等待訪問完成。大蝦們可以在有絕 對信心時使用 DMB,新手還是使用 DSB 比較保險。

同 DMB/DSB 相比,ISB 指令看起來似乎最強悍,但是卻一身都是“愣勁”,不由分說就“動粗”。不過它還有其它的用場——對於高級底層技巧:“自我更新”(self-mofifying)代碼,非常有用。舉例 來說,如果某個程序從下一條要執行的指令處更新了自己,但是先前的舊指令已經被預取到流水線 中去了,此時就必須清洗流水線,把舊版本的指令洗出去,再預取新版本的指令。因此,必須在被 更新代碼段的前面使用 ISB,以保證舊的代碼從流水線中被清洗出去,不再有機會執行(譯者覺得 這種做法太工於技巧,有點“作秀”,現實編程中應該極少會用到,因此讀者不必太鑽它)

發佈了29 篇原創文章 · 獲贊 44 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章