Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=d8b57bb700a73872fd06b891d7c9bc4cea1a6af4
Commit:     d8b57bb700a73872fd06b891d7c9bc4cea1a6af4
Parent:     3aa4b37d3e899cfe7a9cbdcda2b277df4c1f210d
Author:     Thomas Gleixner <[EMAIL PROTECTED]>
AuthorDate: Wed Feb 6 22:39:43 2008 +0100
Committer:  Ingo Molnar <[EMAIL PROTECTED]>
CommitDate: Wed Feb 6 22:39:43 2008 +0100

    x86: make spurious fault handler aware of large mappings
    
    In very rare cases, on certain CPUs, we could end up in the spurious
    fault handler and ignore a large pud/pmd mapping. The resulting pte
    pointer points into the mapped physical space and dereferencing it
    will fault recursively.
    
    Make the code aware of large mappings and do the permission check
    on the pmd/pud entry, when a large pud/pmd mapping is detected.
    
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
---
 arch/x86/mm/fault.c |   23 +++++++++++++++++------
 1 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index ad8b973..d8ed400 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -428,6 +428,16 @@ static noinline void pgtable_bad(unsigned long address, 
struct pt_regs *regs,
 }
 #endif
 
+static int spurious_fault_check(unsigned long error_code, pte_t *pte)
+{
+       if ((error_code & PF_WRITE) && !pte_write(*pte))
+               return 0;
+       if ((error_code & PF_INSTR) && !pte_exec(*pte))
+               return 0;
+
+       return 1;
+}
+
 /*
  * Handle a spurious fault caused by a stale TLB entry.  This allows
  * us to lazily refresh the TLB when increasing the permissions of a
@@ -457,20 +467,21 @@ static int spurious_fault(unsigned long address,
        if (!pud_present(*pud))
                return 0;
 
+       if (pud_large(*pud))
+               return spurious_fault_check(error_code, (pte_t *) pud);
+
        pmd = pmd_offset(pud, address);
        if (!pmd_present(*pmd))
                return 0;
 
+       if (pmd_large(*pmd))
+               return spurious_fault_check(error_code, (pte_t *) pmd);
+
        pte = pte_offset_kernel(pmd, address);
        if (!pte_present(*pte))
                return 0;
 
-       if ((error_code & PF_WRITE) && !pte_write(*pte))
-               return 0;
-       if ((error_code & PF_INSTR) && !pte_exec(*pte))
-               return 0;
-
-       return 1;
+       return spurious_fault_check(error_code, pte);
 }
 
 /*
-
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