1.简介
不同的处理器架构有不同的内存属性(memory type)及不同的行为。为了便于理解和使用,Linux内核在处理器架构的基础上抽象了一套软件接口,定义了noncached、writecombine、writethrough、device等通用的内存属性接口。内核开发者直接使用即可,不需要关注具体处理器架构的内存属性。
内核通用内存属性接口定义在include/linux/pgtable.h和include/asm-generic/io.h文件中,前者定义的内存属性用于将内核空间地址映射到用户空间,即remap_pfn_range函数,后者用于映射memory-mapped I/O设备空间。这些内存属性接口是architecture implementation,若架构没有实现,则使用内核通用接口。
[include/linux/pgtable.h]
#ifndef pgprot_noncached
#define pgprot_noncached(prot) (prot)
#endif
#ifndef pgprot_writecombine
#define pgprot_writecombine pgprot_noncached
#endif
#ifndef pgprot_writethrough
#define pgprot_writethrough pgprot_noncached
#endif
#ifndef pgprot_device
#define pgprot_device pgprot_noncached
#endif
[include/asm-generic/io.h]
#ifndef ioremap
#define ioremap ioremap
static inline void __iomem *ioremap(phys_addr_t addr, size_t size)
{
/* _PAGE_IOREMAP needs to be supplied by the architecture */
return ioremap_prot(addr, size, _PAGE_IOREMAP);
}
#endif
#endif /* !CONFIG_MMU || CONFIG_GENERIC_IOREMAP */
#ifndef ioremap_wc
#define ioremap_wc ioremap
#endif
#ifndef ioremap_wt
#define ioremap_wt ioremap
#endif
/*
* ioremap_uc is special in that we do require an explicit architecture
* implementation. In general you do not want to use this function in a
* driver and use plain ioremap, which is uncached by default. Similarly
* architectures should not implement it unless they have a very good
* reason.
*/
#ifndef ioremap_uc
#define ioremap_uc ioremap_uc
static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
{
return NULL;
}
#endif
/*
* ioremap_np needs an explicit architecture implementation, as it
* requests stronger semantics than regular ioremap(). Portable drivers
* should instead use one of the higher-level abstractions, like
* devm_ioremap_resource(), to choose the correct variant for any given
* device and bus. Portable drivers with a good reason to want non-posted
* write semantics should always provide an ioremap() fallback in case
* ioremap_np() is not available.
*/
#ifndef ioremap_np
#define ioremap_np ioremap_np
static inline void __iomem *ioremap_np(phys_addr_t offset, size_t size)
{
return NULL;
}
#endif
下面表格中总结了X86、ARM64、RISC-V架构内存属性接口分别对应的内存属性,若架构中没有定义相应的接口,则使用通用的接口。
| 内存属性接口 | 内存属性 | |||
| 通用 | X86 | ARM64 | RISC-V | |
| pgprot_cached | 未实现 | 未实现,默认为_PAGE_CACHE_MODE_WB | MT_NORMAL | 未实现,默认为_PAGE_PMA_THEAD |
| pgprot_noncached | port | _PAGE_CACHE_MODE_UC_MINUS | MT_DEVICE_nGnRnE | _PAGE_IO |
| pgprot_writecombine | pgprot_noncached | _PAGE_CACHE_MODE_WC | MT_NORMAL_NC | _PAGE_NOCACHE |
| pgprot_writethrough | pgprot_noncached | _PAGE_CACHE_MODE_WT | MT_DEVICE_nGnRnE | _PAGE_IO |
| pgprot_device | pgprot_noncached | _PAGE_CACHE_MODE_UC_MINUS | MT_DEVICE_nGnRE | _PAGE_IO |
下面表格中总结了X86、ARM64、RISC-V架构IO地址映射接口分别对应的内存属性,若架构中没有定义相应的接口,则使用通用的接口。
| 属性接口 | 内存属性 | |||
| 通用 | X86 | ARM64 | RISC-V | |
| ioremap | _PAGE_IOREMAP | _PAGE_CACHE_MODE_UC_MINUS | MT_DEVICE_nGnRE | _PAGE_IO |
| ioremap_uc | 未实现 | _PAGE_CACHE_MODE_UC | 未实现 | 未实现 |
| ioremap_wc | ioremap | _PAGE_CACHE_MODE_WC | MT_NORMAL_NC | _PAGE_IO |
| ioremap | ||||

468

被折叠的 条评论
为什么被折叠?



