Strong order -> noncached;memcpy 必须要 源地址 与 目的地址对齐。
使用pgprot_noncached() 映射的内存
-------------------------------分界线----------------------------------------------
非strong order -> cachabled. memcpy 允许 源地址 与 目的地址 非对齐。
使用pgprot_writecombine() 映射的内存
Cache类型:
IA中,Cache类型一共有6种,
l Strong Uncacheable (UC)
这种cache类型的memory,任何读写操作都不经过cache。一般是memory-map的IO地址可以使用这种类型。一般的ram强烈推荐不使用这种cache,否则效率会非常低。
l Uncacheable (UC-)
特性与UC(Strong uncacheable)相同,唯一不同的是,这种类型的memory,可以通过修改MTRR来把它改变成WC
l Write Combining (WC)
这种类型的cache,特性与UC相似,不同的地方是它可以被speculative read(什么叫speculative read?)每次write都可能被delay,write的内容会buffer到一个叫“write combining buffer”的地方。可以通过 对MTRR编程来设置WC,也可以通过设置PAT来设置WC(pat是什么?)
l Write – through (WT)
这个很好理解,每次write,都要write到memory,同时write到对应的cache(if write hits)。WT方式保证了cache与memory是一致的。
l Write – back (WB)
这种类型的memory,read和write,都跟一般的cache一样。只是write的时候,当写到了cache中,不会立即write到memory里(这个就跟WT不一样了)。CPU会等到适当的时候再write到memory里—比如当cache满了。 这种类型是效率最高的类型,
l Write-protected (WP)
Read跟wb一样,但每次write,都会引起cache invalidate
#define ioremap(addr, size) __ioremap((addr), (size), pgprot_noncached(PAGE_KERNEL))
#define ioremap_wc(addr, size) __ioremap((addr), (size), pgprot_writecombine(PAGE_KERNEL))
#define ioremap_nocache(addr, size) ioremap((addr), (size))
#define ioremap_wt(addr, size) ioremap((addr), (size))
#define ioremap_cache ioremap_cache
void *memremap(resource_size_t offset, size_t size, unsigned long flags)
{
int is_ram = region_intersects(offset, size,
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
void *addr = NULL;
if (!flags)
return NULL;
if (is_ram == REGION_MIXED) {
WARN_ONCE(1, "memremap attempted on mixed range %pa size: %#lx\n",
&offset, (unsigned long) size);
return NULL;
}
/* Try all mapping types requested until one returns non-NULL */
if (flags & MEMREMAP_WB) {
/*
* MEMREMAP_WB is special in that it can be satisifed
* from the direct map. Some archs depend on the
* capability of memremap() to autodetect cases where
* the requested range is potentially in System RAM.
*/
if (is_ram == REGION_INTERSECTS)
addr = try_ram_remap(offset, size);
if (!addr)
addr = arch_memremap_wb(offset, size);
}
/*
* If we don't have a mapping yet and other request flags are
* present then we will be attempting to establish a new virtual
* address mapping. Enforce that this mapping is not aliasing
* System RAM.
*/
if (!addr && is_ram == REGION_INTERSECTS && flags != MEMREMAP_WB) {
WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
&offset, (unsigned long) size);
return NULL;
}
if (!addr && (flags & MEMREMAP_WT))
addr = ioremap_wt(offset, size);
if (!addr && (flags & MEMREMAP_WC))
addr = ioremap_wc(offset, size);
return addr;
}