From: Andrea Arcangeli Date: Thu, 7 Feb 2013 01:25:50 +0000 (+1100) Subject: Revert "x86, mm: Make spurious_fault check explicitly check the PRESENT bit" X-Git-Tag: next-20130218~1^2~564 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=d63d94f75655bd1e383b520c886139dffb417c17;p=karo-tx-linux.git Revert "x86, mm: Make spurious_fault check explicitly check the PRESENT bit" I got a report for a minor regression introduced by commit 027ef6c87853b ("mm: thp: fix pmd_present for split_huge_page and PROT_NONE with THP"). So the problem is, pageattr creates kernel pagetables (pte and pmds) that breaks pte_present/pmd_present and the patch above exposed this invariant breakage for pmd_present. The same problem already existed for the pte and pte_present and it was fixed by commit 660a293ea9be709 ("x86, mm: Make spurious_fault check explicitly check the PRESENT bit") (if it wasn't for that commit, it wouldn't even be a regression). That fix avoids the pagefault to use pte_present. I could follow through by stopping using pmd_present/pmd_huge too. However I think it's more robust to fix pageattr and to clear the PSE/GLOBAL bitflags too in addition to the present bitflag. So the kernel page fault can keep using the regular pte_present/pmd_present/pmd_huge. The confusion arises because _PAGE_GLOBAL and _PAGE_PROTNONE are sharing the same bit, and in the pmd case we pretend _PAGE_PSE to be set only in present pmds (to facilitate split_huge_page final tlb flush). This patch: Revert commit 660a293ea9be709 ("x86, mm: Make spurious_fault check explicitly check the PRESENT bit"). Signed-off-by: Andrea Arcangeli Cc: Andi Kleen Cc: Shaohua Li Cc: "H. Peter Anvin" Cc: Mel Gorman Cc: Hugh Dickins Cc: Ingo Molnar Cc: Thomas Gleixner Signed-off-by: Andrew Morton --- diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index fb674fd3fc22..2b97525246d4 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -939,14 +939,8 @@ spurious_fault(unsigned long error_code, unsigned long address) if (pmd_large(*pmd)) return spurious_fault_check(error_code, (pte_t *) pmd); - /* - * Note: don't use pte_present() here, since it returns true - * if the _PAGE_PROTNONE bit is set. However, this aliases the - * _PAGE_GLOBAL bit, which for kernel pages give false positives - * when CONFIG_DEBUG_PAGEALLOC is used. - */ pte = pte_offset_kernel(pmd, address); - if (!(pte_flags(*pte) & _PAGE_PRESENT)) + if (!pte_present(*pte)) return 0; ret = spurious_fault_check(error_code, pte);