Cache和DMA本身似乎是兩個毫不相關的事物。Cache被用作CPU針對記憶體的緩存利用程式的空間局部性和時間局部性原理,達到較高的命中率,從而避免CPU每次都必須要與相對慢速的記憶體交互數據來提高數據的訪問速率。DMA可以作為記憶體與外設之間傳輸數據的方式,在這種傳輸方式之下,數據並不需要經過CPU中 ...
Cache和DMA本身似乎是兩個毫不相關的事物。Cache被用作CPU針對記憶體的緩存利用程式的空間局部性和時間局部性原理,達到較高的命中率,從而避免CPU每次都必須要與相對慢速的記憶體交互數據來提高數據的訪問速率。DMA可以作為記憶體與外設之間傳輸數據的方式,在這種傳輸方式之下,數據並不需要經過CPU中轉。
假設DMA針對記憶體的目的地址與 Cache緩存的對象沒有重疊區域(如圖11.12所示)DMA和 Cache之間將相安無事。但是,如果DMA的目的地址與 Cache所緩存的記憶體地址訪問有重疊(如圖11.13所示),經過DMA操作,與 Cache緩存對應的記憶體中的數據已經被修改,而CPU本身並不知道,它仍然認為 Cache中的數據就是記憶體中的數據,那在以後訪問 Cache映射的記憶體時f,它仍然使用陳舊的 Cache數據。這樣就會發生 Cache與記憶體之間數據“不一致性”的錯誤。
所謂 Cache數據與記憶體數據的不一致性,是指在採用 Cache的系統中,同樣一個數據可能既存在於 Cache中,也存在於主存中, Cache與主存中的數據一樣則具有一致性,數據若不一樣則具有不一致性。需要特別註意的是, Cache與記憶體的一致性問題經常被初學者遺忘。在發生 Cache與記憶體不一致性錯誤後,驅動將無法正常運行。如果沒有相關的背景知識,工程師幾乎無法定位錯誤的原因,因為這時所有的程式看起來都是完全正確的。 Cache的不一致性問題並不是只發生在DMA的情況下,實際上,它還存在於 Cache使能和關閉的時刻。例如,對於帶MMU功能的ARM處理器,在開啟MMU之前,需要先置 Cache無效,對於TLB,也是如此,代碼清單11.12給出的這段彙編可用來完成此任務。
/* 使cache無效 */
mov r0, #0
mcr p15, 0, r0, c7, c7, 0
mcr p15, 0, r0, c7, c10, 4
mcr p15, 0, r0, c8, c7, 0
因此申請DMA記憶體而避免Cache不一致的問題的話,就需要使用dma_alloc_coherent()
等方法申請;