aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2014-02-07 13:12:27 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-02-10 06:48:13 -0500
commitb6ccb9803e90c16b212cf4ed62913a7591e79a39 (patch)
treee077cbf203e4b7fbaaa0e0b4807b01c0f028405a
parentafdd3bba3ca18e6b0515b2e60101a932f5fa9afa (diff)
ARM: 7954/1: mm: remove remaining domain support from ARMv6
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. Cc: <stable@vger.kernel.org> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/futex.h6
-rw-r--r--arch/arm/include/asm/pgtable-2level.h1
-rw-r--r--arch/arm/mm/Kconfig3
-rw-r--r--arch/arm/mm/mmu.c10
-rw-r--r--arch/arm/mm/proc-macros.S19
-rw-r--r--arch/arm/mm/proc-v7-2level.S7
6 files changed, 18 insertions, 28 deletions
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index e42cf597f6e6..2aff798fbef4 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -3,11 +3,6 @@
3 3
4#ifdef __KERNEL__ 4#ifdef __KERNEL__
5 5
6#if defined(CONFIG_CPU_USE_DOMAINS) && defined(CONFIG_SMP)
7/* ARM doesn't provide unprivileged exclusive memory accessors */
8#include <asm-generic/futex.h>
9#else
10
11#include <linux/futex.h> 6#include <linux/futex.h>
12#include <linux/uaccess.h> 7#include <linux/uaccess.h>
13#include <asm/errno.h> 8#include <asm/errno.h>
@@ -164,6 +159,5 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
164 return ret; 159 return ret;
165} 160}
166 161
167#endif /* !(CPU_USE_DOMAINS && SMP) */
168#endif /* __KERNEL__ */ 162#endif /* __KERNEL__ */
169#endif /* _ASM_ARM_FUTEX_H */ 163#endif /* _ASM_ARM_FUTEX_H */
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index dfff709fda3c..219ac88a9542 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -140,6 +140,7 @@
140#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ 140#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */
141#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ 141#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */
142#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ 142#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */
143#define L_PTE_MT_VECTORS (_AT(pteval_t, 0x0f) << 2) /* 1111 */
143#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) 144#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2)
144 145
145#ifndef __ASSEMBLY__ 146#ifndef __ASSEMBLY__
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 1f8fed94c2a4..ca8ecdee47d8 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -446,7 +446,6 @@ config CPU_32v5
446 446
447config CPU_32v6 447config CPU_32v6
448 bool 448 bool
449 select CPU_USE_DOMAINS if CPU_V6 && MMU
450 select TLS_REG_EMUL if !CPU_32v6K && !MMU 449 select TLS_REG_EMUL if !CPU_32v6K && !MMU
451 450
452config CPU_32v6K 451config CPU_32v6K
@@ -671,7 +670,7 @@ config ARM_VIRT_EXT
671 670
672config SWP_EMULATE 671config SWP_EMULATE
673 bool "Emulate SWP/SWPB instructions" 672 bool "Emulate SWP/SWPB instructions"
674 depends on !CPU_USE_DOMAINS && CPU_V7 673 depends on CPU_V7
675 default y if SMP 674 default y if SMP
676 select HAVE_PROC_CPU if PROC_FS 675 select HAVE_PROC_CPU if PROC_FS
677 help 676 help
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4f08c133cc25..6ec07a84f759 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -511,6 +511,16 @@ static void __init build_mem_type_table(void)
511 hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; 511 hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte;
512 512
513 /* 513 /*
514 * We don't use domains on ARMv6 (since this causes problems with
515 * v6/v7 kernels), so we must use a separate memory type for user
516 * r/o, kernel r/w to map the vectors page.
517 */
518#ifndef CONFIG_ARM_LPAE
519 if (cpu_arch == CPU_ARCH_ARMv6)
520 vecs_pgprot |= L_PTE_MT_VECTORS;
521#endif
522
523 /*
514 * ARMv6 and above have extended page tables. 524 * ARMv6 and above have extended page tables.
515 */ 525 */
516 if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) { 526 if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index e3c48a3fe063..ee1d80593958 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -112,13 +112,9 @@
112 * 100x 1 0 1 r/o no acc 112 * 100x 1 0 1 r/o no acc
113 * 10x0 1 0 1 r/o no acc 113 * 10x0 1 0 1 r/o no acc
114 * 1011 0 0 1 r/w no acc 114 * 1011 0 0 1 r/w no acc
115 * 110x 0 1 0 r/w r/o
116 * 11x0 0 1 0 r/w r/o
117 * 1111 0 1 1 r/w r/w
118 *
119 * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
120 * 110x 1 1 1 r/o r/o 115 * 110x 1 1 1 r/o r/o
121 * 11x0 1 1 1 r/o r/o 116 * 11x0 1 1 1 r/o r/o
117 * 1111 0 1 1 r/w r/w
122 */ 118 */
123 .macro armv6_mt_table pfx 119 .macro armv6_mt_table pfx
124\pfx\()_mt_table: 120\pfx\()_mt_table:
@@ -137,7 +133,7 @@
137 .long PTE_EXT_TEX(2) @ L_PTE_MT_DEV_NONSHARED 133 .long PTE_EXT_TEX(2) @ L_PTE_MT_DEV_NONSHARED
138 .long 0x00 @ unused 134 .long 0x00 @ unused
139 .long 0x00 @ unused 135 .long 0x00 @ unused
140 .long 0x00 @ unused 136 .long PTE_CACHEABLE | PTE_BUFFERABLE | PTE_EXT_APX @ L_PTE_MT_VECTORS
141 .endm 137 .endm
142 138
143 .macro armv6_set_pte_ext pfx 139 .macro armv6_set_pte_ext pfx
@@ -158,24 +154,21 @@
158 154
159 tst r1, #L_PTE_USER 155 tst r1, #L_PTE_USER
160 orrne r3, r3, #PTE_EXT_AP1 156 orrne r3, r3, #PTE_EXT_AP1
161#ifdef CONFIG_CPU_USE_DOMAINS
162 @ allow kernel read/write access to read-only user pages
163 tstne r3, #PTE_EXT_APX 157 tstne r3, #PTE_EXT_APX
164 bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 158
165#endif 159 @ user read-only -> kernel read-only
160 bicne r3, r3, #PTE_EXT_AP0
166 161
167 tst r1, #L_PTE_XN 162 tst r1, #L_PTE_XN
168 orrne r3, r3, #PTE_EXT_XN 163 orrne r3, r3, #PTE_EXT_XN
169 164
170 orr r3, r3, r2 165 eor r3, r3, r2
171 166
172 tst r1, #L_PTE_YOUNG 167 tst r1, #L_PTE_YOUNG
173 tstne r1, #L_PTE_PRESENT 168 tstne r1, #L_PTE_PRESENT
174 moveq r3, #0 169 moveq r3, #0
175#ifndef CONFIG_CPU_USE_DOMAINS
176 tstne r1, #L_PTE_NONE 170 tstne r1, #L_PTE_NONE
177 movne r3, #0 171 movne r3, #0
178#endif
179 172
180 str r3, [r0] 173 str r3, [r0]
181 mcr p15, 0, r0, c7, c10, 1 @ flush_pte 174 mcr p15, 0, r0, c7, c10, 1 @ flush_pte
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index bdd3be4be77a..1f52915f2b28 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -90,21 +90,14 @@ ENTRY(cpu_v7_set_pte_ext)
90 90
91 tst r1, #L_PTE_USER 91 tst r1, #L_PTE_USER
92 orrne r3, r3, #PTE_EXT_AP1 92 orrne r3, r3, #PTE_EXT_AP1
93#ifdef CONFIG_CPU_USE_DOMAINS
94 @ allow kernel read/write access to read-only user pages
95 tstne r3, #PTE_EXT_APX
96 bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
97#endif
98 93
99 tst r1, #L_PTE_XN 94 tst r1, #L_PTE_XN
100 orrne r3, r3, #PTE_EXT_XN 95 orrne r3, r3, #PTE_EXT_XN
101 96
102 tst r1, #L_PTE_YOUNG 97 tst r1, #L_PTE_YOUNG
103 tstne r1, #L_PTE_VALID 98 tstne r1, #L_PTE_VALID
104#ifndef CONFIG_CPU_USE_DOMAINS
105 eorne r1, r1, #L_PTE_NONE 99 eorne r1, r1, #L_PTE_NONE
106 tstne r1, #L_PTE_NONE 100 tstne r1, #L_PTE_NONE
107#endif
108 moveq r3, #0 101 moveq r3, #0
109 102
110 ARM( str r3, [r0, #2048]! ) 103 ARM( str r3, [r0, #2048]! )