Linux I/O 共享記憶體訪問

Linux I/O 共享記憶體訪問

我對 linux 如何管理 I/O 共享記憶體以與使用它的裝置進行通訊感到非常困惑。

如果我理解正確的話,linux 核心會從 0x100000 開始映射(以避免第一個兆位元組的遺留 ram 資料並儲存在連續的記憶體位置),然後進入保護模式後:

  • 在 32 位元系統上有這樣的映射

在此輸入影像描述

ZONE_NORMAL 應低於 896 MB,因此內核線性 1GB 與物理 896 MB 之間的映射始終是可能的。現在讓我們忽略 ZONE_DMA(我讀到這只適用於舊系統,因為 PCI 現在可以在記憶體中的任何地方使用 DMA 傳輸)

  • 在 64 位元系統上,核心線性位址空間應從 PAGE_OFFSET= 0xffff810000000000 開始,依次類推

在這兩種情況下,如果核心空間中的位址大於 PAGE_OFFSET,則應引用 ioremap 映射(透過分頁解析),如果它低於 PAGE_OFFSET,則可以使用簡單的 NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET 來解析。它是否正確?

額外問題:當核心啟動並運行並且整理完成後,它是否仍然物理地駐留在 0x100000 往復(在第一個 GB 內)?即使在 64 位元系統上?

答案1

在 PC 上,硬體記憶體映射 IO 範圍由 BIOS 分配給 3GiB 到 4 GiB 之間的實體記憶體位址。當驅動程式請求存取記憶體時,核心會將其映射到核心虛擬位址空間中的某個位置。

您的其他兩個問題似乎都與共享記憶體無關,但是:

在這兩種情況下,如果核心空間中的位址大於 PAGE_OFFSET,則應引用 ioremap 映射(透過分頁解析),如果它低於 PAGE_OFFSET,則可以使用簡單的 NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET 來解析。它是否正確?

從精神上來說,是的。無論哪種情況,硬體都會使用頁表。

答案2

認為你的問題看起來像,ioremap 是如何運作的..

vaddr = ioremap(paddr_io_mapped_device, 大小);

vaddr 是傳回的核心空間中的虛擬位址。核心為虛擬位址範圍( vaddr ,大小)建立頁表條目,並將其對應到實體位址 paddr_io_shared_device 。因此,如果存取虛擬位址範圍,則與存取 io_mapped 裝置內​​的實體位址一樣好。

重要的是,返回的 vaddr 是不可緩存。每次讀取/寫入位址範圍時,都會從 io_mapped 裝置而不是從快取讀取/寫入。

相關內容