Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0879750f5d75dee0546316b7b0e83fb6cd258ad7
Commit:     0879750f5d75dee0546316b7b0e83fb6cd258ad7
Parent:     86f03989d99cfa2e1216cdd7aa996852236909cf
Author:     Thomas Gleixner <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 30 13:34:09 2008 +0100
Committer:  Ingo Molnar <[EMAIL PROTECTED]>
CommitDate: Wed Jan 30 13:34:09 2008 +0100

    x86: cpa cleanup the 64-bit alias math
    
    Cleanup the address calculations, which are necessary to identify the
    high/low alias mappings of the kernel on 64 bit machines. Instead of
    calling __pa/__va back and forth, calculate the physical address once
    and base the other calculations on it. Add understandable constants so
    we can use the already available within() helper. Also add comments,
    which help mere mortals to understand what this code does.
    
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
---
 arch/x86/mm/pageattr.c |   56 +++++++++++++++++++++++++----------------------
 1 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 532a40b..ec07c18 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -305,49 +305,53 @@ repeat:
  * Modules and drivers should use the set_memory_* APIs instead.
  */
 
+#define HIGH_MAP_START __START_KERNEL_map
+#define HIGH_MAP_END   (__START_KERNEL_map + KERNEL_TEXT_SIZE)
+
 static int
 change_page_attr_addr(unsigned long address, pgprot_t mask_set,
-                                                       pgprot_t mask_clr)
+                     pgprot_t mask_clr)
 {
-       int err = 0, kernel_map = 0;
-       unsigned long pfn;
+       unsigned long phys_addr = __pa(address);
+       unsigned long pfn = phys_addr >> PAGE_SHIFT;
+       int err;
 
 #ifdef CONFIG_X86_64
-       if (address >= __START_KERNEL_map &&
-                       address < __START_KERNEL_map + KERNEL_TEXT_SIZE) {
-
-               address = (unsigned long)__va(__pa((void *)address));
-               kernel_map = 1;
-       }
+       /*
+        * If we are inside the high mapped kernel range, then we
+        * fixup the low mapping first. __va() returns the virtual
+        * address in the linear mapping:
+        */
+       if (within(address, HIGH_MAP_START, HIGH_MAP_END))
+               address = (unsigned long) __va(phys_addr);
 #endif
 
-       pfn = __pa(address) >> PAGE_SHIFT;
-
-       if (!kernel_map || 1) {
-               err = __change_page_attr(address, pfn, mask_set, mask_clr);
-               if (err)
-                       return err;
-       }
+       err = __change_page_attr(address, pfn, mask_set, mask_clr);
+       if (err)
+               return err;
 
 #ifdef CONFIG_X86_64
        /*
-        * Handle kernel mapping too which aliases part of
-        * lowmem:
+        * If the physical address is inside the kernel map, we need
+        * to touch the high mapped kernel as well:
         */
-       if (__pa(address) < KERNEL_TEXT_SIZE) {
-               unsigned long addr2;
-
-               addr2 = __pa(address) + __START_KERNEL_map - phys_base;
+       if (within(phys_addr, 0, KERNEL_TEXT_SIZE)) {
+               /*
+                * Calc the high mapping address. See __phys_addr()
+                * for the non obvious details.
+                */
+               address = phys_addr + HIGH_MAP_START - phys_base;
                /* Make sure the kernel mappings stay executable */
                pgprot_val(mask_clr) |= _PAGE_NX;
+
                /*
-                * Our high aliases are imprecise, so do not propagate
-                * failures back to users:
+                * Our high aliases are imprecise, because we check
+                * everything between 0 and KERNEL_TEXT_SIZE, so do
+                * not propagate lookup failures back to users:
                 */
-               __change_page_attr(addr2, pfn, mask_set, mask_clr);
+               __change_page_attr(address, pfn, 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