powerpc/booke64: Move mb() to __set_pte_at() with kernel-addr test
authorScott Wood <scottwood@freescale.com>
Sat, 18 Jul 2015 19:24:57 +0000 (14:24 -0500)
committerScott Wood <scottwood@freescale.com>
Sat, 8 Aug 2015 04:00:01 +0000 (23:00 -0500)
map_kernel() doesn't catch all places that create kernel PTEs.  In
particular, vmalloc() calls set_pte_at() directly.  This causes a
crash when booting a non-SMP kernel on e6500.

Move the sync to __set_pte(), to be executed only for kernel addresses.

Signed-off-by: Scott Wood <scottwood@freescale.com>
arch/powerpc/include/asm/pgtable.h
arch/powerpc/mm/pgtable_64.c

index 11a3863..0717693 100644 (file)
@@ -169,6 +169,17 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
         * cases, and 32-bit non-hash with 32-bit PTEs.
         */
        *ptep = pte;
+
+#ifdef CONFIG_PPC_BOOK3E_64
+       /*
+        * With hardware tablewalk, a sync is needed to ensure that
+        * subsequent accesses see the PTE we just wrote.  Unlike userspace
+        * mappings, we can't tolerate spurious faults, so make sure
+        * the new PTE will be seen the first time.
+        */
+       if (is_kernel_addr(addr))
+               mb();
+#endif
 #endif
 }
 
index 876232d..e92cb21 100644 (file)
@@ -149,17 +149,7 @@ int map_kernel_page(unsigned long ea, unsigned long pa, int flags)
 #endif /* !CONFIG_PPC_MMU_NOHASH */
        }
 
-#ifdef CONFIG_PPC_BOOK3E_64
-       /*
-        * With hardware tablewalk, a sync is needed to ensure that
-        * subsequent accesses see the PTE we just wrote.  Unlike userspace
-        * mappings, we can't tolerate spurious faults, so make sure
-        * the new PTE will be seen the first time.
-        */
-       mb();
-#else
        smp_wmb();
-#endif
        return 0;
 }