分类: LINUX
2013-05-31 15:29:33
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日志中。