Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=626c2c9d065da0cbd9997e112501487958fde690
Commit:     626c2c9d065da0cbd9997e112501487958fde690
Parent:     cc0f21bbc12dc9f05b2e7f2469128f8717b2f4d3
Author:     Arjan van de Ven <[EMAIL PROTECTED]>
AuthorDate: Mon Feb 4 16:48:05 2008 +0100
Committer:  Ingo Molnar <[EMAIL PROTECTED]>
CommitDate: Mon Feb 4 16:48:05 2008 +0100

    x86: use the pfn from the page when change its attributes
    
    When changing the attributes of a pte, we should use the PFN from the
    existing PTE rather than going through hoops calculating what we think
    it might have been; this is both fragile and totally unneeded. It also
    makes it more hairy to call any of these functions on non-direct maps
    for no good reason whatsover.
    
    With this change, __change_page_attr() no longer takes a pfn as argument,
    which simplifies all the callers.
    
    Signed-off-by: Arjan van de Ven <[EMAIL PROTECTED]>
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
---
 arch/x86/mm/pageattr.c |   31 +++++++++++++++++--------------
 1 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index bf5e33f..6c55fbd 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -277,17 +277,12 @@ out_unlock:
 }
 
 static int
-__change_page_attr(unsigned long address, unsigned long pfn,
-                  pgprot_t mask_set, pgprot_t mask_clr)
+__change_page_attr(unsigned long address, pgprot_t mask_set, pgprot_t mask_clr)
 {
        struct page *kpte_page;
        int level, err = 0;
        pte_t *kpte;
 
-#ifdef CONFIG_X86_32
-       BUG_ON(pfn > max_low_pfn);
-#endif
-
 repeat:
        kpte = lookup_address(address, &level);
        if (!kpte)
@@ -298,17 +293,25 @@ repeat:
        BUG_ON(PageCompound(kpte_page));
 
        if (level == PG_LEVEL_4K) {
-               pgprot_t new_prot = pte_pgprot(*kpte);
                pte_t new_pte, old_pte = *kpte;
+               pgprot_t new_prot = pte_pgprot(old_pte);
+
+               if(!pte_val(old_pte)) {
+                       WARN_ON_ONCE(1);
+                       return -EINVAL;
+               }
 
                pgprot_val(new_prot) &= ~pgprot_val(mask_clr);
                pgprot_val(new_prot) |= pgprot_val(mask_set);
 
                new_prot = static_protections(new_prot, address);
 
-               new_pte = pfn_pte(pfn, canon_pgprot(new_prot));
-               BUG_ON(pte_pfn(new_pte) != pte_pfn(old_pte));
-
+               /*
+                * We need to keep the pfn from the existing PTE,
+                * after all we're only going to change it's attributes
+                * not the memory it points to
+                */
+               new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot));
                set_pte_atomic(kpte, new_pte);
        } else {
                err = split_large_page(kpte, address);
@@ -337,11 +340,11 @@ static int
 change_page_attr_addr(unsigned long address, pgprot_t mask_set,
                      pgprot_t mask_clr)
 {
-       unsigned long phys_addr = __pa(address);
-       unsigned long pfn = phys_addr >> PAGE_SHIFT;
        int err;
 
 #ifdef CONFIG_X86_64
+       unsigned long phys_addr = __pa(address);
+
        /*
         * If we are inside the high mapped kernel range, then we
         * fixup the low mapping first. __va() returns the virtual
@@ -351,7 +354,7 @@ change_page_attr_addr(unsigned long address, pgprot_t 
mask_set,
                address = (unsigned long) __va(phys_addr);
 #endif
 
-       err = __change_page_attr(address, pfn, mask_set, mask_clr);
+       err = __change_page_attr(address, mask_set, mask_clr);
        if (err)
                return err;
 
@@ -375,7 +378,7 @@ change_page_attr_addr(unsigned long address, pgprot_t 
mask_set,
                 * everything between 0 and KERNEL_TEXT_SIZE, so do
                 * not propagate lookup failures back to users:
                 */
-               __change_page_attr(address, pfn, mask_set, mask_clr);
+               __change_page_attr(address, mask_set, mask_clr);
        }
 #endif
        return err;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to