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;
}