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)
committerBen Hutchings <ben@decadent.org.uk>
Wed, 30 Apr 2014 15:23:19 +0000 (16:23 +0100)
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>
[bwh: Backported to 3.2:
 - Adjust filename, context
 - Drop condition on CONFIG_ARM_LPAE]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
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.S

index 253cc86..aefd459 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>
@@ -163,6 +158,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 cd7e627..1cb80c4 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)
 
 #endif /* _ASM_PGTABLE_2LEVEL_H */
index 67f75a0..4e1ef6e 100644 (file)
@@ -458,7 +458,6 @@ config CPU_32v5
 config CPU_32v6
        bool
        select TLS_REG_EMUL if !CPU_32v6K && !MMU
-       select CPU_USE_DOMAINS if CPU_V6 && MMU
 
 config CPU_32v6K
        bool
@@ -652,7 +651,7 @@ config ARM_THUMBEE
 
 config SWP_EMULATE
        bool "Emulate SWP/SWPB instructions"
-       depends on !CPU_USE_DOMAINS && CPU_V7
+       depends on CPU_V7
        select HAVE_PROC_CPU if PROC_FS
        default y if SMP
        help
index 9e28fdb..082fa18 100644 (file)
@@ -425,6 +425,14 @@ static void __init build_mem_type_table(void)
                mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
                mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
        }
+       /*
+        * 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.
+        */
+       if (cpu_arch == CPU_ARCH_ARMv6)
+               vecs_pgprot |= L_PTE_MT_VECTORS;
+
        /*
         * ARMv6 and above have extended page tables.
         */
index 29a6021..8a3edd4 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 21b09f2..43c6981 100644 (file)
@@ -160,21 +160,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_PRESENT
-#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]! )