Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@
#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__
+1 −2
Original line number Diff line number Diff line
@@ -446,7 +446,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
@@ -671,7 +670,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
+10 −0
Original line number Diff line number Diff line
@@ -510,6 +510,16 @@ static void __init build_mem_type_table(void)
	s2_pgprot = cp->pte_s2;
	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.
	 */
+6 −13
Original line number Diff line number Diff line
@@ -112,13 +112,9 @@
 *  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:
@@ -137,7 +133,7 @@
	.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
@@ -158,24 +154,21 @@

	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
Loading