裝置驅動程式與核心模組

ioremap(映射裝置記憶體)

/ EYE-oh-ree-map /

裝置的暫存器住在某個實體位址——比方說硬體規格書寫著「控制暫存器在 0xFED00000」。但核心執行於虛擬記憶體,無法直接解參考一個原始實體位址;它需要一個由 MMU 映射到那個實體位置的虛擬位址。ioremap 就是建立那個映射的函式:你把一段實體位址範圍交給它,它回傳一個核心虛擬指標,讓你用來抵達裝置的暫存器。

具體而言,你呼叫 base = ioremap(phys_addr, size),核心便設定分頁表項目,使回傳的指標 base 指向裝置的 MMIO 區域——而且重要的是,它把那塊區域映射成裝置記憶體(無快取、帶正確的存取規則),而不是普通的可快取 RAM。接著你以 base + offset 存取暫存器,使用 writel/readl 系列存取器,而非單純解參考。完成時(在驅動程式的清理或 remove 路徑中),你呼叫 iounmap(base) 把映射拆掉。一個常見模式是 devm_ioremap_resource,即裝置管理版本,會在驅動程式卸離時自動解除映射,消除一整類洩漏。

ioremap 之所以重要,是因為它是從規格書上的實體硬體位址到驅動程式碼中可用指標的橋樑——幾乎每個 MMIO 驅動程式都從 ioremap 它的暫存器區塊開始。兩個誠實的提醒:ioremap 回傳的指標只對 I/O 存取函式與核心有效,對使用者空間無效,也不能像對 RAM 那樣 memcpy;把它當普通記憶體(快取它、讓編譯器在它附近重排)正是 MMIO 屏障紀律所要防範的臭蟲。此外,你只能 ioremap 你的驅動程式擁有的真實裝置空間記憶體——映射錯誤的範圍在硬體層面是未定義的。

void __iomem *base; base = ioremap(0xFED00000, 0x1000); // 映射 4 KiB 的暫存器 if (!base) return -ENOMEM; writel(1, base + 0x00); // 啟動裝置 ... iounmap(base); // 在清理/remove 中 // 或用 devm_ioremap_resource() 自動解除映射

ioremap 把實體暫存器位址轉成一個映射為裝置記憶體的核心虛擬指標;iounmap 釋放它。

回傳的指標僅供 I/O 存取器(writel/readl)使用——不給使用者空間、不給 memcpy、不是可快取的 RAM 指標。每個 ioremap 都要配對 iounmap,或用 devm_ioremap_resource 自動清理。

又稱
I/O remapmap device registers映射裝置暫存器