天天看點

ARM外設寄存器Cache一緻性問題

ARM外設寄存器Cache一緻性問題  

   MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_NCNB);

以上是DM9000裸機代碼,其中關掉了DM9000的cache功能,下面給出原因:

volatile限定符,是可以防止編譯器優化對裝置寄存器的通路,但是對于有Cache的平台,僅僅這樣還不夠,還是無法防止Cache優化對裝置寄存器的通路。在通路普通的記憶體單元時,Cache對程式員是透明的,比如執行了movzbl 0x804a019,%eax這樣一條指令,我們并不知道eax的值是真的從記憶體位址0x804a019讀到的,還是從Cache中讀到的,如果Cache已經緩存了這個位址的資料就從Cache讀,如果Cache沒有緩存就從記憶體讀,這些步驟都是硬體自動做的,而不是用指令控制Cache去做的,程式員寫的指令中隻有寄存器、記憶體位址,而沒有Cache,程式員甚至不需要知道Cache的存在。同樣道理,如果執行了mov %al,0x804a01a這樣一條指令,我們并不知道寄存器的值是真的寫回記憶體了,還是隻寫到了Cache中,以後再由Cache寫回記憶體,即使隻寫到了Cache中而暫時沒有寫回記憶體,下次讀0x804a01a這個位址時仍然可以從Cache中讀到上次寫的資料。然而,在讀寫裝置寄存器時Cache的存在就不容忽視了,如果序列槽發送和接收寄存器的記憶體位址被Cache緩存了會有什麼問題呢?如下圖所示。

ARM外設寄存器Cache一緻性問題

如果序列槽發送寄存器的位址被Cahce緩存,CPU執行單元對序列槽發送寄存器做寫操作都寫到Cache中去了,序列槽發送寄存器并沒有及時得到資料,也就不能及時發送,CPU執行單元先後發出的1、2、3三個位元組都會寫到Cache中的同一個單元,最後Cache中隻儲存了第3個位元組,如果這時 Cache把資料寫回到序列槽發送寄存器,隻能把第3個位元組發送出去,前兩個位元組就丢失了。與此類似,如果序列槽接收寄存器的位址被Cache緩存,CPU執行單元在讀第1個位元組時,Cache會從序列槽接收寄存器讀上來緩存,然而序列槽接收寄存器後面收到的2、3兩個位元組Cache并不知道,因為Cache把序列槽接收寄存器當作普通記憶體單元,并且相信記憶體單元中的資料是不會自己變的,以後每次讀序列槽接收寄存器時,Cache都會把緩存的第1個位元組提供給CPU執行單元。

如果把外設寄存器配置成Cache或寫緩沖,那麼通常會産生問題,是以最好将他們配置成不适用cache,并且不适用寫緩沖,這就強制處理器在每次通路時都去讀外設端口寄存器,而不是從cache中讀取陳舊的資訊

通常,有Cache的平台都有辦法對某一段位址範圍禁用Cache,一般是在頁表中設定的,可以設定哪些頁面允許Cache緩存,哪些頁面不允許Cache緩存,MMU不僅要做位址轉換和通路權限檢查,也要和Cache協同工作。

轉載處連結:

http://blog.chinaunix.net/uid-21977330-id-3217248.html