Index: linux/arch/x86_64/mm/pageattr.c =================================================================== --- linux.orig/arch/x86_64/mm/pageattr.c +++ linux/arch/x86_64/mm/pageattr.c @@ -176,10 +176,19 @@ __change_page_attr(unsigned long address */ int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot) { + unsigned long start = __pa(address); int err = 0; int i; down_write(&init_mm.mmap_sem); + err = mattr_get(start, start + numpages*PAGE_SIZE,prot); + if (err) { + printk(KERN_INFO + "%s: change_page_attr: cache conflict %lx-%lx\n", + current->comm, start, start+numpages*PAGE_SIZE); + up_write(&init_mm.mmap_sem); + return err; + } for (i = 0; i < numpages; i++, address += PAGE_SIZE) { unsigned long pfn = __pa(address) >> PAGE_SHIFT; @@ -196,6 +205,8 @@ int change_page_attr_addr(unsigned long err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC); } } + if (err) + mattr_put(start, start+numpages*PAGE_SIZE, prot); up_write(&init_mm.mmap_sem); return err; } Index: linux/include/asm-i386/cacheflush.h =================================================================== --- linux.orig/include/asm-i386/cacheflush.h +++ linux/include/asm-i386/cacheflush.h @@ -26,6 +26,8 @@ void global_flush_tlb(void); int change_page_attr(struct page *page, int numpages, pgprot_t prot); int change_page_attr_pfn(unsigned long pfn, int numpages, pgprot_t prot); +int mattr_get(unsigned long pfn, unsigned long end, pgprot_t prot); +void mattr_put(unsigned long pfn, unsigned long end, pgprot_t prot); #ifdef CONFIG_DEBUG_PAGEALLOC /* internal debugging function */ Index: linux/include/asm-x86_64/cacheflush.h =================================================================== --- linux.orig/include/asm-x86_64/cacheflush.h +++ linux/include/asm-x86_64/cacheflush.h @@ -26,6 +26,8 @@ void global_flush_tlb(void); int change_page_attr(struct page *page, int numpages, pgprot_t prot); int change_page_attr_addr(unsigned long addr, int numpages, pgprot_t prot); +int mattr_get(unsigned long pfn, unsigned long end, pgprot_t prot); +void mattr_put(unsigned long pfn, unsigned long end, pgprot_t prot); #ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro(void); Index: linux/arch/i386/pci/i386.c =================================================================== --- linux.orig/arch/i386/pci/i386.c +++ linux/arch/i386/pci/i386.c @@ -288,10 +288,7 @@ int pci_mmap_page_range(struct pci_dev * else vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) - return -EAGAIN; - - return 0; + return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); } Index: linux/include/asm-generic/pgtable.h =================================================================== --- linux.orig/include/asm-generic/pgtable.h +++ linux/include/asm-generic/pgtable.h @@ -230,6 +230,11 @@ static inline int pmd_none_or_clear_bad( } return 0; } + +#ifndef pte_caching_nonstd +#define pte_caching_nonstd 0 +#endif + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_GENERIC_PGTABLE_H */ Index: linux/mm/memory.c =================================================================== --- linux.orig/mm/memory.c +++ linux/mm/memory.c @@ -640,6 +640,11 @@ static unsigned long zap_pte_range(struc struct page *page; page = vm_normal_page(vma, addr, ptent); + + if (pgprot_nonstd(pte_pgprot(ptent))) + change_page_attr_pfn(pte_pfn(ptent), 1, + PAGE_KERNEL); + if (unlikely(details) && page) { /* * unmap_shared_mapping_pages() wants to Index: linux/include/asm-x86_64/pgtable.h =================================================================== --- linux.orig/include/asm-x86_64/pgtable.h +++ linux/include/asm-x86_64/pgtable.h @@ -445,8 +445,9 @@ void vmalloc_sync_all(void); extern int kern_addr_valid(unsigned long addr); -#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ - remap_pfn_range(vma, vaddr, pfn, size, prot) +extern int io_remap_page_range(struct vm_area_struct *vma, + unsigned long vaddr, unsigned long pfn, + unsigned long size, pgprot_t prot); #define MK_IOSPACE_PFN(space, pfn) (pfn) #define GET_IOSPACE(pfn) 0