PAT(頁面屬性工作表Page Attribute Table)
X86的頁面屬性工作表(PAT)能夠在頁面級的粒度上設定記憶體屬性。PAT是對MTRR的補充,通過MTRR可以為物理地址地區設定記憶體類型。但是PAT比MTRR更靈活,因為它可以在頁面層級設定屬性,而且硬體上也不限制屬性設定的數量。PAT相當靈活,即使多個虛擬記憶體地址映射到同一個實體記憶體地址,也不會引起記憶體類型的衝突。
通過PAT能夠設定多種類型的記憶體屬性,其中最常用的有4種:寫回(Write-back),不緩衝(Uncached),寫聯合(Write-combined)以及Uncached Minus。
PAT APIs
核心中提供了很多能夠在頁面級設定記憶體屬性的API。為了避免混淆,需要小心地使用這些介面。下表中列出了這些介面、它們的功能以及它們與記憶體屬性的關係。這些API都使用reserve_memtype()/free_memtype()介面來操作物理地址地區,以避免衝突。
|
API |
RAM |
ACPI,... |
Reserved/Holes |
|
ioremap |
-- |
UC- |
UC- |
|
ioremap_cache |
-- |
WB |
WB |
|
ioremap_nocache |
-- |
UC- |
UC- |
|
ioremap_wc |
-- |
-- |
WC |
|
set_memory_uc
set_memory_wb |
UC- |
-- |
-- |
|
set_memory_wc
set_memory_wb |
WC |
-- |
-- |
|
pci sysfs resource |
-- |
-- |
UC- |
|
pci sysfs resource_wc
is IORESOURCE_PREFETCH |
-- |
-- |
WC |
|
pci proc
!PCIIOC_WRITE_COMBINE |
-- |
-- |
UC- |
|
pci proc
PCIIOC_WRITE_COMBINE |
-- |
-- |
WC |
|
/dev/mem
read-write |
-- |
WB/WC/UC- |
WB/WC/UC- |
|
/dev/mem
mmap SYNC flag |
-- |
UC- |
UC- |
|
/dev/mem
mmap !SYNC flag
and
any alias to this area |
-- |
WB/WC/UC-
(from
existing alias) |
WB/WC/UC-
(from
existing alias) |
|
/dev/mem
mmap !SYNC flag
no alias to this area
and
MTRR says WB |
-- |
WB |
WB |
|
/dev/mem
mmap !SYNC flag
no alias to this area
and
MTRR says !WB |
-- |
-- |
UC- |
針對裝置驅動的進階APIs
A. 如果要將頁面匯出到使用者空間,可以使用介面remap_pfn_range, io_remap_pfn_range,,vm_insert_pfn
在驅動程式中,有時會希望將一些頁面匯出到使用者空間。此時可以使用mmap介面與下列函數的組合。
1)
pgprot_noncached()
2)
io_remap_pfn_range() 或
remap_pfn_range() 或 vm_insert_pfn()
在PAT的支援下,Linux引入了一個新的API,pgprot_writecombine。因此,驅動能夠持續地使用上述操作序列。首先,在步驟1調用pgprot_noncached()或pgprot_writecombine()。然後在採取步驟二。
步驟二為了確保不會產生映射衝突,將跟蹤記憶體類型列表中那些標記為UC或WC的地區。
需要指出的是,這組API僅僅對IO地址空間有效,對RAM則無效。如果驅動程式希望匯出一個RAM地區,則需在步驟1之前再執行一個步驟0,即調用set_memory_uc()或set_memory_wc(),同時也需要跟蹤那些頁面的使用方式,在頁面被釋放到空閑池之前調用函數set_memory_wb()。
注意:
上面表格中的“--”符號表示“不推薦使用此API”。其中一些是核心嚴格規定不能使用的。其它一些,雖然目前沒有這麼嚴格的限制,但是將來有可能會出現這樣的情況。
對於通過/sys或/proc進行的ioremap與pci訪問,如果在被訪問的地址上存在衝突,將返回一個較為嚴格的記憶體類型。比如:如果已經存在了uncached映射,那麼操作ioremap_wc()會返回uncached映射而不是申請的write-combine。
set_memory_[uc|wc]和set_memory_wb需要成對的使用,此時,驅動將首先申請一個uc或wc地區,在使用之後,再將該地區切換為wb。
對/proc/mtrr的操作已經不再被推薦了,取而代之,可以使用基於PAT的介面。
驅動程式可以使用ioremap_[uc|wc]訪問PCI BARs,相應的訪問類型為[uc|wc]。
驅動程式可以使用set_memory_[uc|wc]為RAM地區設定訪存類型。
PAT調試
如果使能了CONFIG_DEBUG_FS選項,僅能夠通過下面的方式檢查PAT的記憶體類型列表。
# 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設定。
另外,通過核心啟動選項“debugpat”可以擷取更加詳細的PAT調試資訊。設定此參數後,各種調試資訊將列印在dmesg日誌中。