2013-06-04 35 views
2

簡介:Linux內核flush_cache_range()調用顯得無能爲力

我們有哪些Linux在ARM上運行的應用程序從外部處理器接收數據,DMA的數據到ARM的內存空間。 ARM然後需要從用戶模式代碼訪問這些數據。

地址範圍必須物理連續,因爲外部處理器中的DMA引擎不支持分散/聚集。這個內存範圍最初是通過調用__get_free_pages(GFP_KERNEL | __GFP_DMA,order)從ARM內核分配的,因爲這可以保證我們分配的內存在物理上是連續的。然後,對返回的指針的virt_to_phys()調用會給我們提供物理地址,然後在進程開始時將其提供給外部處理器。

該物理地址對於Linux用戶模式代碼也是已知的,它使用它(在用戶模式下)調用mmap()API來獲取用戶模式指針指向該內存區域。然後,我們的Linux內核驅動程序會在驅動程序的file_operations結構中看到對其mmap例程的相應調用。然後,驅動程序保留vm_area_struct「vma」指針,該指針在調用mmap例程時傳遞給它,供以後使用。

當用戶模式代碼收到一個信號,說明新數據已經DMA到該內存地址時,它需要通過用戶模式指針從我們從上面提到的調用mmap()中獲取用戶模式。在用戶模式代碼執行之前,必須刷新與此內存範圍對應的高速緩存。要完成此刷新,用戶模式代碼將調用驅動程序(通過ioctl),並在內核模式下調用flush_cache_range():

flush_cache_range(vma,start,end);

傳遞給上述調用的參數是驅動程序在調用mmap例程時捕獲的「vma」,「start」和「end」是從用戶模式代碼傳入驅動程序的用戶模式地址提供給ioctl()調用的結構。

問題:

我們所看到的是,緩衝區似乎並不如我們所看到的似乎從用戶模式訪問是由時是過時的數據被刷新得到。作爲一個測試,而不是從mmap()調用我們的驅動程序獲取用戶模式地址,而是將mmap()API調用到/ dev/mem。在這種情況下,我們獲得對緩衝區的無緩存訪問(不需要衝洗),然後一切都完美無缺。

我們的內核版本是3.8.3,它運行在ARM9上。我們嘗試的方法中是否存在邏輯錯誤?

謝謝!

+0

另一個線索是,如果不是調用flush_cache_range(vma,start,end);我調用flush_cache_mm(vma-> vm_mm);那麼代碼完美地工作。 – user1967844

回答

0

我有幾個問題後,我可能會回答: 1)如何在你的mmap()調用中使用「PHYSICAL」地址? mmap應該與物理地址無關。 2)你究竟做了什麼來獲得你的驅動程序中的用戶虛擬地址? 3)你如何將這些用戶虛擬地址映射到物理地址,以及你在哪裏做到這一點? 4)由於您使用get_free_pages()預先分配,您是否使用ioremap_cache()將其映射到內核空間?