Commit b6ccb980 authored by Will Deacon's avatar Will Deacon Committed by Russell King

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: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent afdd3bba
...@@ -3,11 +3,6 @@ ...@@ -3,11 +3,6 @@
#ifdef __KERNEL__ #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/futex.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/errno.h> #include <asm/errno.h>
...@@ -164,6 +159,5 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ...@@ -164,6 +159,5 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
return ret; return ret;
} }
#endif /* !(CPU_USE_DOMAINS && SMP) */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_ARM_FUTEX_H */ #endif /* _ASM_ARM_FUTEX_H */
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ #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_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */
#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ #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) #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
......
...@@ -446,7 +446,6 @@ config CPU_32v5 ...@@ -446,7 +446,6 @@ config CPU_32v5
config CPU_32v6 config CPU_32v6
bool bool
select CPU_USE_DOMAINS if CPU_V6 && MMU
select TLS_REG_EMUL if !CPU_32v6K && !MMU select TLS_REG_EMUL if !CPU_32v6K && !MMU
config CPU_32v6K config CPU_32v6K
...@@ -671,7 +670,7 @@ config ARM_VIRT_EXT ...@@ -671,7 +670,7 @@ config ARM_VIRT_EXT
config SWP_EMULATE config SWP_EMULATE
bool "Emulate SWP/SWPB instructions" bool "Emulate SWP/SWPB instructions"
depends on !CPU_USE_DOMAINS && CPU_V7 depends on CPU_V7
default y if SMP default y if SMP
select HAVE_PROC_CPU if PROC_FS select HAVE_PROC_CPU if PROC_FS
help help
......
...@@ -510,6 +510,16 @@ static void __init build_mem_type_table(void) ...@@ -510,6 +510,16 @@ static void __init build_mem_type_table(void)
s2_pgprot = cp->pte_s2; s2_pgprot = cp->pte_s2;
hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; 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. * ARMv6 and above have extended page tables.
*/ */
......
...@@ -112,13 +112,9 @@ ...@@ -112,13 +112,9 @@
* 100x 1 0 1 r/o no acc * 100x 1 0 1 r/o no acc
* 10x0 1 0 1 r/o no acc * 10x0 1 0 1 r/o no acc
* 1011 0 0 1 r/w 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 * 110x 1 1 1 r/o r/o
* 11x0 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 .macro armv6_mt_table pfx
\pfx\()_mt_table: \pfx\()_mt_table:
...@@ -137,7 +133,7 @@ ...@@ -137,7 +133,7 @@
.long PTE_EXT_TEX(2) @ L_PTE_MT_DEV_NONSHARED .long PTE_EXT_TEX(2) @ L_PTE_MT_DEV_NONSHARED
.long 0x00 @ unused .long 0x00 @ unused
.long 0x00 @ unused .long 0x00 @ unused
.long 0x00 @ unused .long PTE_CACHEABLE | PTE_BUFFERABLE | PTE_EXT_APX @ L_PTE_MT_VECTORS
.endm .endm
.macro armv6_set_pte_ext pfx .macro armv6_set_pte_ext pfx
...@@ -158,24 +154,21 @@ ...@@ -158,24 +154,21 @@
tst r1, #L_PTE_USER tst r1, #L_PTE_USER
orrne r3, r3, #PTE_EXT_AP1 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 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 tst r1, #L_PTE_XN
orrne r3, r3, #PTE_EXT_XN orrne r3, r3, #PTE_EXT_XN
orr r3, r3, r2 eor r3, r3, r2
tst r1, #L_PTE_YOUNG tst r1, #L_PTE_YOUNG
tstne r1, #L_PTE_PRESENT tstne r1, #L_PTE_PRESENT
moveq r3, #0 moveq r3, #0
#ifndef CONFIG_CPU_USE_DOMAINS
tstne r1, #L_PTE_NONE tstne r1, #L_PTE_NONE
movne r3, #0 movne r3, #0
#endif
str r3, [r0] str r3, [r0]
mcr p15, 0, r0, c7, c10, 1 @ flush_pte mcr p15, 0, r0, c7, c10, 1 @ flush_pte
......
...@@ -90,21 +90,14 @@ ENTRY(cpu_v7_set_pte_ext) ...@@ -90,21 +90,14 @@ ENTRY(cpu_v7_set_pte_ext)
tst r1, #L_PTE_USER tst r1, #L_PTE_USER
orrne r3, r3, #PTE_EXT_AP1 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 tst r1, #L_PTE_XN
orrne r3, r3, #PTE_EXT_XN orrne r3, r3, #PTE_EXT_XN
tst r1, #L_PTE_YOUNG tst r1, #L_PTE_YOUNG
tstne r1, #L_PTE_VALID tstne r1, #L_PTE_VALID
#ifndef CONFIG_CPU_USE_DOMAINS
eorne r1, r1, #L_PTE_NONE eorne r1, r1, #L_PTE_NONE
tstne r1, #L_PTE_NONE tstne r1, #L_PTE_NONE
#endif
moveq r3, #0 moveq r3, #0
ARM( str r3, [r0, #2048]! ) ARM( str r3, [r0, #2048]! )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment