Linux 內存cache

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章