Merge branch 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / arch / x86 / mm / fault.c
index 06fe3d51d385b88111961c0b5addc673fcd597a2..800de815519cd1061c090e70fab09bd62bbd8ddd 100644 (file)
@@ -172,14 +172,15 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
  * 6. T1   : reaches here, sees vma_pkey(vma)=5, when we really
  *          faulted on a pte with its pkey=4.
  */
-static void fill_sig_info_pkey(int si_code, siginfo_t *info, u32 *pkey)
+static void fill_sig_info_pkey(int si_signo, int si_code, siginfo_t *info,
+               u32 *pkey)
 {
        /* This is effectively an #ifdef */
        if (!boot_cpu_has(X86_FEATURE_OSPKE))
                return;
 
        /* Fault not from Protection Keys: nothing to do */
-       if (si_code != SEGV_PKUERR)
+       if ((si_code != SEGV_PKUERR) || (si_signo != SIGSEGV))
                return;
        /*
         * force_sig_info_fault() is called from a number of
@@ -218,7 +219,7 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address,
                lsb = PAGE_SHIFT;
        info.si_addr_lsb = lsb;
 
-       fill_sig_info_pkey(si_code, &info, pkey);
+       fill_sig_info_pkey(si_signo, si_code, &info, pkey);
 
        force_sig_info(si_signo, &info, tsk);
 }
@@ -438,18 +439,13 @@ static noinline int vmalloc_fault(unsigned long address)
        if (pgd_none(*pgd_ref))
                return -1;
 
-       if (pgd_none(*pgd)) {
-               set_pgd(pgd, *pgd_ref);
-               arch_flush_lazy_mmu_mode();
-       } else if (CONFIG_PGTABLE_LEVELS > 4) {
-               /*
-                * With folded p4d, pgd_none() is always false, so the pgd may
-                * point to an empty page table entry and pgd_page_vaddr()
-                * will return garbage.
-                *
-                * We will do the correct sanity check on the p4d level.
-                */
-               BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+       if (CONFIG_PGTABLE_LEVELS > 4) {
+               if (pgd_none(*pgd)) {
+                       set_pgd(pgd, *pgd_ref);
+                       arch_flush_lazy_mmu_mode();
+               } else {
+                       BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+               }
        }
 
        /* With 4-level paging, copying happens on the p4d level. */
@@ -458,7 +454,7 @@ static noinline int vmalloc_fault(unsigned long address)
        if (p4d_none(*p4d_ref))
                return -1;
 
-       if (p4d_none(*p4d)) {
+       if (p4d_none(*p4d) && CONFIG_PGTABLE_LEVELS == 4) {
                set_p4d(p4d, *p4d_ref);
                arch_flush_lazy_mmu_mode();
        } else {
@@ -469,6 +465,7 @@ static noinline int vmalloc_fault(unsigned long address)
         * Below here mismatches are bugs because these lower tables
         * are shared:
         */
+       BUILD_BUG_ON(CONFIG_PGTABLE_LEVELS < 4);
 
        pud = pud_offset(p4d, address);
        pud_ref = pud_offset(p4d_ref, address);