--- arch/x86_64/mm/pageattr.c | 3 - arch/x86_64/mm/pat.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) Index: linux/arch/x86_64/mm/pageattr.c =================================================================== --- linux.orig/arch/x86_64/mm/pageattr.c +++ linux/arch/x86_64/mm/pageattr.c @@ -13,7 +13,7 @@ #include #include -static inline pte_t *lookup_address(unsigned long address) +pte_t *lookup_address(unsigned long address) { pgd_t *pgd = pgd_offset_k(address); pud_t *pud; @@ -120,6 +120,7 @@ __change_page_attr(unsigned long address pte_t *kpte; struct page *kpte_page; pgprot_t ref_prot2; + printk("cpa address %lx prot %lx\n", address, pgprot_val(prot)); kpte = lookup_address(address); if (!kpte) return 0; kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK); Index: linux/arch/x86_64/mm/pat.c =================================================================== --- linux.orig/arch/x86_64/mm/pat.c +++ linux/arch/x86_64/mm/pat.c @@ -177,8 +177,10 @@ static int revert_hole(unsigned long *ho unsigned long i = -1; int err = 0; u64 len = end - start; + printk("revert hole len %lu end %lx\n", len, end); while ((i = find_next_zero_bit(holemap, len, i + 1)) < len) { *flush = 1; + printk("revert hole %lx\n", (start >> PAGE_SHIFT) + i); err = __change_page_attr_pfn((start >> PAGE_SHIFT) + i, 1, PAGE_KERNEL); if (err) @@ -310,6 +312,7 @@ void *get_pages_mattr(gfp_t mask, unsign return NULL; err = reserve_mattr(__pa(p), __pa(p) + (order< + +void *page2; + +void bench(char *name, void *p) +{ + u64 start, end, rd, wr; + int i, k; + rd = wr = 0; + for (k = 0; k < 10; k++) { + for (i = 0; i < PAGE_SIZE; i += 64) + asm volatile("clflush (%0)" :: "r" (p + i)); + rdtscll(start); + memset(p, 0, PAGE_SIZE); + rdtscll(end); + rd += end-start; + + for (i = 0; i < PAGE_SIZE; i += 64) + asm volatile("clflush (%0)" :: "r" (p + i)); + rdtscll(start); + memcpy(page2, p, PAGE_SIZE); + rdtscll(end); + + wr += end-start; + } + printk("%s: write %lu\n", name, wr/10); + printk("%s: read %lu\n", name, rd/10); +} + +#define C(x) if ((err=(x)) < 0) printk("%d:%s failed with %d\n", __LINE__,#x,err) +#define CT(x) if ((err=(x)) != !0) printk("%d:%s failed with %d\n", __LINE__,#x,err) +#define CE(x) if ((err=(x)) != 0) printk("%d:%s failed with %d\n", __LINE__,#x,err) +int test(void) +{ + int i, err; + printk("testing PAT\n"); + + page2 = (void *)__get_free_page(GFP_KERNEL); + void *np = (void *)get_pages_mattr(GFP_KERNEL, 0, _PAGE_WC); + bench("cached", page2); + bench("wc", np); + + free_page((unsigned long) page2); + free_pages_mattr(np, 0, _PAGE_WC); + + C(reserve_mattr(__pa(np), __pa(np)+PAGE_SIZE, _PAGE_WC, NULL)); + + for (i = 0; i < N; i++) { + unsigned long attr2; + pages[i] = get_pages_mattr(GFP_KERNEL, 0, _PAGE_WC); + CT(pages[i] != NULL); + C(reserve_mattr(__pa(pages[i]), __pa(pages[i])+PAGE_SIZE, + _PAGE_PCD, NULL)); + C(reserve_mattr(__pa(pages[i]), __pa(pages[i])+PAGE_SIZE, + -1, &attr2)); + if (attr2 != _PAGE_WC) + printk("unexpected attr2 %lx\n", attr2); + C(free_mattr(__pa(pages[i]), __pa(pages[i])+PAGE_SIZE, + attr2)); + + pte_t *pte = lookup_address((unsigned long)pages[i]) ; + if (!pte) { + printk("pte of %p not found\n", pages[i]); + continue; + } + if (pgprot_nonstd(pte_pgprot(*pte)) != _PAGE_WC) + printk("direct %p unexpected pte %lx attr %lx\n", pages[i], + pte_val(*pte), pgprot_nonstd(pte_pgprot(*pte))); + } + + printk("freeing\n"); + for (i = 0; i < N; i++) { + free_pages_mattr(pages[i], 0, _PAGE_WC); + } + + + printk("large test\n"); + void *large; + unsigned long attr; + large = __get_free_pages(GFP_KERNEL, 8); + if (large) { + C(reserve_mattr(__pa(large), + __pa(large) + (7<