2016-01-19 25 views
1

我有一個基於7000賽靈思ZYNQ板與在具有DMA能力的FPGA架構的外圍(上賽靈思/ ARM的SoC(ZYNQ 7000)DMA緩衝區AXI總線)。我們開發了一個電路並在ARM內核上運行Linux。硬件填充後,我們遇到性能問題,從用戶空間訪問DMA緩衝區。需要幫助映射預先保留** **緩存上

摘要:

在啓動時我們已預先保留DRAM的部分用作大DMA緩衝區。我們顯然使用錯誤的API來映射此緩衝區,因爲它看起來沒有緩存,並且訪問速度很糟糕。

使用它,甚至作爲一個反彈緩衝是慢難以維持,由於可怕的性能。 IIUC,ARM高速緩存不連貫的DMA,所以我會很感激關於如何做到以下一些見解:

  1. 地圖DRAM的一個區域到內核的虛擬地址空間,但確保它是緩存
  2. 確保將它映射到用戶空間並不會產生不良影響,即使這需要我們通過我們自己的驅動程序提供mmap調用。
  3. 在執行DMA之前,從緩存層次結構中顯式地使物理內存區域無效,以確保一致性。

更多信息:

我一直在試圖詢問之前仔細研究這個。不幸的是,這是一個ARM SoC/FPGA,這方面的信息很少,所以我必須直接詢問專家。

因爲這是一個系統級芯片,很多東西是硬編碼的u-boot。例如,在將控制交給內核之前,內核和ramdisk被加載到DRAM中的特定位置。我們利用這個優勢爲DMA緩衝區預留了64MB的DRAM部分(它的確需要那麼大,這就是我們預先保留它的原因)。沒有任何擔心內存類型衝突或內核在內存中跺腳,因爲引導參數告訴內核哪個區域的DRAM可以控制。

最初,我們嘗試使用ioremap將此物理地址範圍映射到內核空間,但似乎標記區域不可緩存,並且訪問速度非常糟糕,即使我們試圖使用memcpy使其成爲反彈緩衝區。我們使用/ dev/mem將其映射到用戶空間中,並將memcpy的時間定義爲70MB/sec左右。

基於對這個主題的大量搜索,似乎有一半的人希望像這樣使用ioremap(這可能是我們從中得到的想法),ioremap不應該用於這個目的以及應該使用DMA相關的API來代替。不幸的是,似乎DMA緩衝區分配是完全動態的,我還沒有想出如何告訴它,「這是一個已經分配的物理地址 - 使用它。」我看着

一號文件是這一個,但它的方式太x86和PC爲中心的: https://www.kernel.org/doc/Documentation/DMA-API-HOWTO.txt

而且這個問題也是在我的搜索上面來了,但沒有真正的答案: get the physical address of a buffer under Linux

望着標準要求,dma_set_mask_and_coherent和家人不會採取預先定義的地址,並希望爲PCI設備結構。我沒有這樣的結構,因爲這是沒有PCI的ARM SoC。我可以手動填充這樣的結構,但是這對我來說就像濫用API一樣,而不是按照預期使用它。

BTW:這是一個環形緩衝區,我們DMA數據塊到不同的偏移,但我們對齊緩存行邊界,所以沒有虛假分擔風險。

非常感謝您爲您提供的任何幫助!

更新:看來,如果以正常方式進行操作,ARM上不存在可緩存的DMA緩衝區。也許如果我不進行ioremap調用,該區域不會被標記爲不可緩存,但是我必須弄清楚如何在ARM上進行緩存管理,這是我無法弄清楚的。其中一個問題是用戶空間中的memcpy顯得非常糟糕。是否有一個memcpy實現爲我可以使用的未緩存內存進行了優化?也許我可以寫一個。我必須弄清楚這個處理器是否有Neon。

+0

您正在使用哪個版本的Linux內核?您是否嘗試過使用**連續內存分配器**?... – TheCodeArtist

+0

@ TheCodeArtist「Linux(none)3.17.0-xilinx-dirty#13 SMP PREEMPT Mon Aug 3 12:10:57 MDT 2015 armv7l GNU/Linux」 另外,我沒有看過CMA。如果我能正確映射這個緩衝區,它不應該要求CMA,除非完全不可能從預保留的物理地址指定DMA緩衝區。 –

+0

獲取Linux下的緩衝區的物理地址(這是來自用戶空間)http://stackoverflow.com/a/28987409/1163019。對於DMA/uncached東西afaik,老實說我不記得所有的細節,並且我沒有成功完成我的不同任務,但是我能從代碼中看到的是我正在嘗試「dma_alloc_coherent」 - >「update vma-> vm_page_prot作爲寫通過「 - > dma_mmap_from_coherent - > remap_pfn_range。也可能是這個演示文稿的幫助? http://events.linuxfoundation.org/sites/events/files/slides/20141015-dma.pdf – auselen

回答

1

您是否嘗試過與mmap()方法重新映射你的緩衝區緩存(通過remap_pfn_range()方式)實現自己的字符設備?

0

我相信你需要一個驅動程序來實現mmap(),如果你想映射被緩存。

我們使用這兩設備驅動程序:portalmem和zynqportal。在Connectal Project,中,我們將用戶空間軟件和FPGA邏輯之間的連接稱爲「門戶」。這些驅動程序需要dma-buf,自從Linux內核版本3.8.x以來,它一直保持穩定。

portalmem的驅動程序提供一個ioctl分配的存儲器中的參考計數的塊,並返回與該存儲器相關聯的文件描述符。該驅動程序執行dma-buf sharing。它還實現了mmap(),以便用戶空間應用程序可以訪問內存。

在分配時,應用程序可能會選擇緩存或未緩存的內存映射。在x86上,映射總是被緩存。我們對mmap()的實現目前開始於line 173 of the portalmem driver。如果映射未緩存,則使用pgprot_writecombine()修改vma-> vm_page_prot,從而啓用緩衝寫入但禁用緩存。

的portalmem驅動器還提供一個ioctl無效和任選回寫數據高速緩存行。

portalmem驅動程序不瞭解FPGA。爲此,我們提供了zynqportal驅動程序,該驅動程序提供了一個將轉換表傳送到FPGA的ioctl,以便我們可以在FPGA上使用邏輯上連續的地址並將它們轉換爲實際的DMA地址。 portalmem使用的分配方案旨在生成緊湊的轉換表。

我們使用相同的驅動程序portalmem與pcieportal的PCI Express連接的FPGA,而無需更改用戶的軟件。

+0

在x86上,所有這些都很簡單。對於ARM,我一直在研究如何通過AXI協議來實現緩存一致性,但是我還沒有弄清楚如何分配或映射可緩存的DMA緩衝區。一些建議(如memremap)是我有機會時需要測試的一些東西。 –

+0

對於ARM,它取決於AXI如何連接到內存基礎架構。例如,在Zynq上,有5個可編程的AXI端口可用於訪問處理器的DRAM。它們中的4個不會被處理器緩存窺探,所以不是緩存一致的。第五個(ACP)被窺探,因此可能是緩存一致的。內存區域需要被緩存到用戶進程中。 –

0

Zynq具有neon指令,使用氖指令的memcpy的彙編代碼實現,使用高速緩存邊界(32字節)對齊將達到300 MB/s速率或更高。