13. PAT (頁屬性表)¶
x86 頁屬性表 (PAT) 允許在頁級別粒度上設定記憶體屬性。 PAT 是對 MTRR 設定的補充,MTRR 允許在物理地址範圍上設定記憶體型別。 但是,PAT 比 MTRR 更靈活,因為它能夠在頁級別設定屬性,而且由於允許的此類屬性設定數量沒有硬體限制。 增加的靈活性帶來了一些指導原則,即對於具有多個虛擬地址的同一物理記憶體,不要進行記憶體類型別名。
PAT 允許不同型別的記憶體屬性。 此時將支援的最常用的屬性是
WB |
寫回 |
UC |
非快取 |
WC |
寫合併 |
WT |
寫透 |
UC- |
非快取減 |
13.1. PAT API¶
核心中有許多不同的 API 允許在頁級別設定記憶體屬性。 為了避免別名,應謹慎使用這些介面。 下面是一個可用介面、其預期用途及其記憶體屬性關係的表。 在內部,這些 API 在物理地址範圍上使用 reserve_memtype()/free_memtype() 介面來避免任何別名。
API |
RAM |
ACPI,... |
保留/空洞 |
ioremap |
-- |
UC- |
UC- |
ioremap_cache |
-- |
WB |
WB |
ioremap_uc |
-- |
UC |
UC |
ioremap_wc |
-- |
-- |
WC |
ioremap_wt |
-- |
-- |
WT |
set_memory_uc, set_memory_wb |
UC- |
-- |
-- |
set_memory_wc, set_memory_wb |
WC |
-- |
-- |
set_memory_wt, set_memory_wb |
WT |
-- |
-- |
pci sysfs 資源 |
-- |
-- |
UC- |
pci sysfs resource_wc 是 IORESOURCE_PREFETCH |
-- |
-- |
WC |
pci proc !PCIIOC_WRITE_COMBINE |
-- |
-- |
UC- |
pci proc PCIIOC_WRITE_COMBINE |
-- |
-- |
WC |
/dev/mem 讀寫 |
-- |
WB/WC/UC- |
WB/WC/UC- |
/dev/mem mmap SYNC 標誌 |
-- |
UC- |
UC- |
/dev/mem mmap !SYNC 標誌以及此區域的任何別名 |
-- |
(來自現有別名) |
WB/WC/UC- (來自現有別名) |
/dev/mem mmap !SYNC 標誌,此區域沒有別名,並且 MTRR 指出 WB |
-- |
WB |
WB |
/dev/mem mmap !SYNC 標誌,此區域沒有別名,並且 MTRR 指出 !WB |
-- |
-- |
UC- |
13.2. 驅動程式的高階 API¶
A. 使用 remap_pfn_range、io_remap_pfn_range、vmf_insert_pfn 將頁面匯出給使用者。
希望將某些頁面匯出到使用者空間的驅動程式透過使用 mmap 介面和以下組合來完成:
pgprot_noncached()
io_remap_pfn_range() 或
remap_pfn_range()或vmf_insert_pfn()
透過 PAT 支援,正在新增一個新的 API pgprot_writecombine。 因此,驅動程式可以繼續使用上述序列,在步驟 1 中使用 pgprot_noncached() 或 pgprot_writecombine(),然後在步驟 2 中使用。
此外,步驟 2 在內部將該區域作為 UC 或 WC 跟蹤在 memtype 列表中,以確保沒有衝突的對映。
請注意,這組 API 僅適用於 IO(非 RAM)區域。 如果驅動程式想要匯出 RAM 區域,則必須執行 set_memory_uc() 或 set_memory_wc() 作為上面的步驟 0,並且還跟蹤這些頁面的使用情況,並在將頁面釋放到空閒池之前使用 set_memory_wb()。
13.3. MTRR 對 PAT / 非 PAT 系統的影響¶
下表提供了在非 PAT 和 PAT 系統上為 x86 使用 ioremap*() 呼叫時使用寫合併 MTRR 的影響。 理想情況下,mtrr_add() 的使用將在 arch_phys_wc_add() 的支援下逐步淘汰,這將是在啟用 PAT 的系統上的空操作。 進行 arch_phys_wc_add() 的區域應已使用 WC 屬性或 PAT 條目進行 ioremap,這可以透過使用 ioremap_wc() / set_memory_wc() 來完成。 將希望保持不可快取的 IO 記憶體區域與希望進行寫合併的區域組合在一起的裝置應考慮使用 ioremap_uc(),然後使用 set_memory_wc() 將有效的寫合併區域列入白名單。 然而,不鼓勵這種使用,因為有效的記憶體型別被認為是實現定義的,但這種策略可以用作在尺寸受限的區域中裝置的最後手段,否則 MTRR 寫合併將無效。
==== ======= === ========================= =====================
MTRR Non-PAT PAT Linux ioremap value Effective memory type
==== ======= === ========================= =====================
PAT Non-PAT | PAT
|PCD |
||PWT |
||| |
WC 000 WB _PAGE_CACHE_MODE_WB WC | WC
WC 001 WC _PAGE_CACHE_MODE_WC WC* | WC
WC 010 UC- _PAGE_CACHE_MODE_UC_MINUS WC* | UC
WC 011 UC _PAGE_CACHE_MODE_UC UC | UC
==== ======= === ========================= =====================
(*) denotes implementation defined and is discouraged
注意
-- 在上表中表示 “不建議用於 API”。 一些 --’s 由核心嚴格執行。 其他一些今天並沒有真正執行,但將來可能會執行。
對於透過 /sys 或 /proc 進行的 ioremap 和 pci 訪問 - 如果該地址有任何現有別名,則返回的實際型別可能會受到更多限制。 例如:如果存在現有的非快取對映,則新的 ioremap_wc 可以返回非快取對映來代替請求的寫合併。
set_memory_[uc|wc|wt] 和 set_memory_wb 應該成對使用,驅動程式首先將區域設定為 uc、wc 或 wt,然後在使用後將其切換回 wb。
隨著時間的推移,寫入 /proc/mtrr 將被棄用,取而代之的是使用基於 PAT 的介面。 建議寫入 /proc/mtrr 的使用者使用上面的介面。
驅動程式應使用 ioremap_[uc|wc] 來訪問具有 [uc|wc] 訪問型別的 PCI BAR。
驅動程式應使用 set_memory_[uc|wc|wt] 來設定 RAM 範圍的訪問型別。
13.4. PAT 除錯¶
啟用 CONFIG_DEBUG_FS 後,可以透過以下方式檢查 PAT memtype 列表:
# mount -t debugfs debugfs /sys/kernel/debug
# cat /sys/kernel/debug/x86/pat_memtype_list
PAT memtype list:
uncached-minus @ 0x7fadf000-0x7fae0000
uncached-minus @ 0x7fb19000-0x7fb1a000
uncached-minus @ 0x7fb1a000-0x7fb1b000
uncached-minus @ 0x7fb1b000-0x7fb1c000
uncached-minus @ 0x7fb1c000-0x7fb1d000
uncached-minus @ 0x7fb1d000-0x7fb1e000
uncached-minus @ 0x7fb1e000-0x7fb25000
uncached-minus @ 0x7fb25000-0x7fb26000
uncached-minus @ 0x7fb26000-0x7fb27000
uncached-minus @ 0x7fb27000-0x7fb28000
uncached-minus @ 0x7fb28000-0x7fb2e000
uncached-minus @ 0x7fb2e000-0x7fb2f000
uncached-minus @ 0x7fb2f000-0x7fb30000
uncached-minus @ 0x7fb31000-0x7fb32000
uncached-minus @ 0x80000000-0x90000000
此列表顯示物理地址範圍和用於訪問這些物理地址範圍的各種 PAT 設定。
另一種獲取與 PAT 相關的除錯訊息的更詳細的方法是使用 “debugpat” 啟動引數。 使用此引數,各種除錯訊息將列印到 dmesg 日誌。
13.5. PAT 初始化¶
下表描述了在各種配置下如何初始化 PAT。 必須由 Linux 更新 PAT MSR,才能支援 WC 和 WT 屬性。 否則,PAT MSR 具有韌體程式設計到其中的值。 請注意,Xen 在 PAT MSR 中為訪客啟用 WC 屬性。
MTRR
PAT
呼叫序列
PAT 狀態
PAT MSR
E
E
MTRR -> PAT 初始化
已啟用
作業系統
E
D
MTRR -> PAT 初始化
已停用
D
E
MTRR -> PAT 停用
已停用
BIOS
D
D
MTRR -> PAT 停用
已停用
np/E
PAT -> PAT 停用
已停用
BIOS
np/D
PAT -> PAT 停用
已停用
E
!P/E
MTRR -> PAT 初始化
已停用
BIOS
D
!P/E
MTRR -> PAT 停用
已停用
BIOS
!M
!P/E
MTRR stub -> PAT 停用
已停用
BIOS
圖例
E
CPU 中啟用的特性
D
CPU 中停用/不支援的特性
np
指定的 “nopat” 啟動選項
!P
未設定 CONFIG_X86_PAT 選項
!M
未設定 CONFIG_MTRR 選項
已啟用
PAT 狀態設定為已啟用
已停用
PAT 狀態設定為已停用
作業系統
PAT 使用作業系統設定初始化 PAT MSR
BIOS
PAT 使用 BIOS 設定保留 PAT MSR