--- arch/i386/mm/pageattr.c | 25 ++++++++++++++----------- arch/x86_64/mm/pageattr.c | 23 +++++++++++++++-------- include/asm-i386/cacheflush.h | 1 + include/asm-x86_64/cacheflush.h | 1 + 4 files changed, 31 insertions(+), 19 deletions(-) Index: linux/arch/i386/mm/pageattr.c =================================================================== --- linux.orig/arch/i386/mm/pageattr.c +++ linux/arch/i386/mm/pageattr.c @@ -120,23 +120,18 @@ static inline void revert_page(struct pa ref_prot)); } -static int -__change_page_attr(struct page *page, pgprot_t prot) +static int __change_page_attr(unsigned long address, pgprot_t prot) { pte_t *kpte; - unsigned long address; struct page *kpte_page; - BUG_ON(PageHighMem(page)); - address = (unsigned long)page_address(page); - kpte = lookup_address(address); if (!kpte) return -EINVAL; kpte_page = virt_to_page(kpte); if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { if ((pte_val(*kpte) & _PAGE_PSE) == 0) { - set_pte_atomic(kpte, mk_pte(page, prot)); + set_pte_atomic(kpte, pfn_pte(pte_pfn(*kpte), prot)); } else { pgprot_t ref_prot; struct page *split; @@ -152,7 +147,7 @@ __change_page_attr(struct page *page, pg } page_private(kpte_page)++; } else if ((pte_val(*kpte) & _PAGE_PSE) == 0) { - set_pte_atomic(kpte, mk_pte(page, PAGE_KERNEL)); + set_pte_atomic(kpte, pfn_pte(pte_pfn(*kpte), PAGE_KERNEL)); BUG_ON(page_private(kpte_page) == 0); page_private(kpte_page)--; } else @@ -191,15 +186,17 @@ static inline void flush_map(void) * * Caller must call global_flush_tlb() after this. */ -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 err = 0; int i; unsigned long flags; spin_lock_irqsave(&cpa_lock, flags); - for (i = 0; i < numpages; i++, page++) { - err = __change_page_attr(page, prot); + for (i = 0; i < numpages; i++, pfn++) { + unsigned long addr; + addr = (unsigned long)__va(pfn << PAGE_SHIFT); + err = __change_page_attr(addr, prot); if (err) break; } @@ -207,6 +204,12 @@ int change_page_attr(struct page *page, return err; } +int change_page_attr(struct page *page, int numpages, pgprot_t prot) +{ + BUG_ON(PageHighMem(page)); + return __change_page_attr_pfn(page_to_pfn(page), numpages, prot); +} + void global_flush_tlb(void) { struct list_head l; Index: linux/arch/x86_64/mm/pageattr.c =================================================================== --- linux.orig/arch/x86_64/mm/pageattr.c +++ linux/arch/x86_64/mm/pageattr.c @@ -170,30 +170,37 @@ __change_page_attr(unsigned long address * * Caller must call global_flush_tlb() after this. */ -int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot) +int __change_page_attr_pfn(unsigned long pfn, int numpages, pgprot_t prot) { int err = 0; int i; - down_write(&init_mm.mmap_sem); - for (i = 0; i < numpages; i++, address += PAGE_SIZE) { - unsigned long pfn = __pa(address) >> PAGE_SHIFT; - - err = __change_page_attr(address, pfn, prot, PAGE_KERNEL); + for (i = 0; i < numpages; i++, pfn++) { + unsigned long addr; + addr = (unsigned long)__va(pfn << PAGE_SHIFT); + err = __change_page_attr(addr, pfn, prot, PAGE_KERNEL); if (err) break; /* Handle kernel mapping too which aliases part of the * lowmem */ - if (__pa(address) < KERNEL_TEXT_SIZE) { + if (pfn < KERNEL_TEXT_SIZE >> PAGE_SHIFT) { unsigned long addr2; pgprot_t prot2; - addr2 = __START_KERNEL_map + __pa(address); + addr2 = __START_KERNEL_map + (pfn << PAGE_SHIFT); /* Make sure the kernel mappings stay executable */ prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot))); err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC); } } + return err; +} + +int change_page_attr_addr(unsigned long addr, int numpages, pgprot_t prot) +{ + int err; + down_write(&init_mm.mmap_sem); + err = __change_page_attr_pfn(__pa(addr) >> PAGE_SHIFT, numpages, 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 @@ -25,6 +25,7 @@ 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); #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,7 @@ 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 __change_page_attr_pfn(unsigned long pfn, int numpages, pgprot_t prot); #ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro(void);