ARM: 7954/1: mm: remove remaining domain support from ARMv6
authorWill Deacon <will.deacon@arm.com>
Fri, 7 Feb 2014 18:12:27 +0000 (19:12 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 6 May 2014 14:55:26 +0000 (07:55 -0700)
commit b6ccb9803e90c16b212cf4ed62913a7591e79a39 upstream.

CPU_32v6 currently selects CPU_USE_DOMAINS if CPU_V6 and MMU. This is
because ARM 1136 r0pX CPUs lack the v6k extensions, and therefore do
not have hardware thread registers. The lack of these registers requires
the kernel to update the vectors page at each context switch in order to
write a new TLS pointer. This write must be done via the userspace
mapping, since aliasing caches can lead to expensive flushing when using
kmap. Finally, this requires the vectors page to be mapped r/w for
kernel and r/o for user, which has implications for things like put_user
which must trigger CoW appropriately when targetting user pages.

The upshot of all this is that a v6/v7 kernel makes use of domains to
segregate kernel and user memory accesses. This has the nasty
side-effect of making device mappings executable, which has been
observed to cause subtle bugs on recent cores (e.g. Cortex-A15
performing a speculative instruction fetch from the GIC and acking an
interrupt in the process).

This patch solves this problem by removing the remaining domain support
from ARMv6. A new memory type is added specifically for the vectors page
which allows that page (and only that page) to be mapped as user r/o,
kernel r/w. All other user r/o pages are mapped also as kernel r/o.
Patch co-developed with Russell King.

Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/include/asm/futex.h
arch/arm/include/asm/pgtable-2level.h
arch/arm/mm/Kconfig
arch/arm/mm/mmu.c
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-v7-2level.S

index e42cf59..2aff798 100644 (file)
@@ -3,11 +3,6 @@
 
 #ifdef __KERNEL__
 
-#if defined(CONFIG_CPU_USE_DOMAINS) && defined(CONFIG_SMP)
-/* ARM doesn't provide unprivileged exclusive memory accessors */
-#include <asm-generic/futex.h>
-#else
-
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
@@ -164,6 +159,5 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
        return ret;
 }
 
-#endif /* !(CPU_USE_DOMAINS && SMP) */
 #endif /* __KERNEL__ */
 #endif /* _ASM_ARM_FUTEX_H */
index f97ee02..c98c9c8 100644 (file)
 #define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2)      /* 1100 */
 #define L_PTE_MT_DEV_WC                (_AT(pteval_t, 0x09) << 2)      /* 1001 */
 #define L_PTE_MT_DEV_CACHED    (_AT(pteval_t, 0x0b) << 2)      /* 1011 */
+#define L_PTE_MT_VECTORS       (_AT(pteval_t, 0x0f) << 2)      /* 1111 */
 #define L_PTE_MT_MASK          (_AT(pteval_t, 0x0f) << 2)
 
 #ifndef __ASSEMBLY__
index 08c9fe9..c21082d 100644 (file)
@@ -436,7 +436,6 @@ config CPU_32v5
 
 config CPU_32v6
        bool
-       select CPU_USE_DOMAINS if CPU_V6 && MMU
        select TLS_REG_EMUL if !CPU_32v6K && !MMU
 
 config CPU_32v6K
@@ -651,7 +650,7 @@ config ARM_VIRT_EXT
 
 config SWP_EMULATE
        bool "Emulate SWP/SWPB instructions"
-       depends on !CPU_USE_DOMAINS && CPU_V7
+       depends on CPU_V7
        default y if SMP
        select HAVE_PROC_CPU if PROC_FS
        help
index daf336f..fb3c446 100644 (file)
@@ -459,6 +459,16 @@ static void __init build_mem_type_table(void)
        hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte;
 
        /*
+        * We don't use domains on ARMv6 (since this causes problems with
+        * v6/v7 kernels), so we must use a separate memory type for user
+        * r/o, kernel r/w to map the vectors page.
+        */
+#ifndef CONFIG_ARM_LPAE
+       if (cpu_arch == CPU_ARCH_ARMv6)
+               vecs_pgprot |= L_PTE_MT_VECTORS;
+#endif
+
+       /*
         * ARMv6 and above have extended page tables.
         */
        if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
index e3c48a3..ee1d805 100644 (file)
  *  100x   1   0   1   r/o     no acc
  *  10x0   1   0   1   r/o     no acc
  *  1011   0   0   1   r/w     no acc
- *  110x   0   1   0   r/w     r/o
- *  11x0   0   1   0   r/w     r/o
- *  1111   0   1   1   r/w     r/w
- *
- * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
  *  110x   1   1   1   r/o     r/o
  *  11x0   1   1   1   r/o     r/o
+ *  1111   0   1   1   r/w     r/w
  */
        .macro  armv6_mt_table pfx
 \pfx\()_mt_table:
        .long   PTE_EXT_TEX(2)                                  @ L_PTE_MT_DEV_NONSHARED
        .long   0x00                                            @ unused
        .long   0x00                                            @ unused
-       .long   0x00                                            @ unused
+       .long   PTE_CACHEABLE | PTE_BUFFERABLE | PTE_EXT_APX    @ L_PTE_MT_VECTORS
        .endm
 
        .macro  armv6_set_pte_ext pfx
 
        tst     r1, #L_PTE_USER
        orrne   r3, r3, #PTE_EXT_AP1
-#ifdef CONFIG_CPU_USE_DOMAINS
-       @ allow kernel read/write access to read-only user pages
        tstne   r3, #PTE_EXT_APX
-       bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
-#endif
+
+       @ user read-only -> kernel read-only
+       bicne   r3, r3, #PTE_EXT_AP0
 
        tst     r1, #L_PTE_XN
        orrne   r3, r3, #PTE_EXT_XN
 
-       orr     r3, r3, r2
+       eor     r3, r3, r2
 
        tst     r1, #L_PTE_YOUNG
        tstne   r1, #L_PTE_PRESENT
        moveq   r3, #0
-#ifndef CONFIG_CPU_USE_DOMAINS
        tstne   r1, #L_PTE_NONE
        movne   r3, #0
-#endif
 
        str     r3, [r0]
        mcr     p15, 0, r0, c7, c10, 1          @ flush_pte
index b3997c7..bb20ba0 100644 (file)
@@ -90,21 +90,14 @@ ENTRY(cpu_v7_set_pte_ext)
 
        tst     r1, #L_PTE_USER
        orrne   r3, r3, #PTE_EXT_AP1
-#ifdef CONFIG_CPU_USE_DOMAINS
-       @ allow kernel read/write access to read-only user pages
-       tstne   r3, #PTE_EXT_APX
-       bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
-#endif
 
        tst     r1, #L_PTE_XN
        orrne   r3, r3, #PTE_EXT_XN
 
        tst     r1, #L_PTE_YOUNG
        tstne   r1, #L_PTE_VALID
-#ifndef CONFIG_CPU_USE_DOMAINS
        eorne   r1, r1, #L_PTE_NONE
        tstne   r1, #L_PTE_NONE
-#endif
        moveq   r3, #0
 
  ARM(  str     r3, [r0, #2048]! )