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

Commit 247055aa authored by Catalin Marinas's avatar Catalin Marinas Committed by Russell King
Browse files

ARM: 6384/1: Remove the domain switching on ARMv6k/v7 CPUs



This patch removes the domain switching functionality via the set_fs and
__switch_to functions on cores that have a TLS register.

Currently, the ioremap and vmalloc areas share the same level 1 page
tables and therefore have the same domain (DOMAIN_KERNEL). When the
kernel domain is modified from Client to Manager (via the __set_fs or in
the __switch_to function), the XN (eXecute Never) bit is overridden and
newer CPUs can speculatively prefetch the ioremap'ed memory.

Linux performs the kernel domain switching to allow user-specific
functions (copy_to/from_user, get/put_user etc.) to access kernel
memory. In order for these functions to work with the kernel domain set
to Client, the patch modifies the LDRT/STRT and related instructions to
the LDR/STR ones.

The user pages access rights are also modified for kernel read-only
access rather than read/write so that the copy-on-write mechanism still
works. CPU_USE_DOMAINS gets disabled only if the hardware has a TLS register
(CPU_32v6K is defined) since writing the TLS value to the high vectors page
isn't possible.

The user addresses passed to the kernel are checked by the access_ok()
function so that they do not point to the kernel space.

Tested-by: default avatarAnton Vorontsov <cbouatmailru@gmail.com>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent ff8b16d7
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#endif

#include <asm/ptrace.h>
#include <asm/domain.h>

/*
 * Endian independent macros for shifting bytes within registers.
@@ -206,12 +207,12 @@
 */
#ifdef CONFIG_THUMB2_KERNEL

	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort
	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
9999:
	.if	\inc == 1
	\instr\cond\()bt \reg, [\ptr, #\off]
	\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
	.elseif	\inc == 4
	\instr\cond\()t \reg, [\ptr, #\off]
	\instr\cond\()\t\().w \reg, [\ptr, #\off]
	.else
	.error	"Unsupported inc macro argument"
	.endif
@@ -246,13 +247,13 @@

#else	/* !CONFIG_THUMB2_KERNEL */

	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
	.rept	\rept
9999:
	.if	\inc == 1
	\instr\cond\()bt \reg, [\ptr], #\inc
	\instr\cond\()b\()\t \reg, [\ptr], #\inc
	.elseif	\inc == 4
	\instr\cond\()t \reg, [\ptr], #\inc
	\instr\cond\()\t \reg, [\ptr], #\inc
	.else
	.error	"Unsupported inc macro argument"
	.endif
+29 −2
Original line number Diff line number Diff line
@@ -45,13 +45,17 @@
 */
#define DOMAIN_NOACCESS	0
#define DOMAIN_CLIENT	1
#ifdef CONFIG_CPU_USE_DOMAINS
#define DOMAIN_MANAGER	3
#else
#define DOMAIN_MANAGER	1
#endif

#define domain_val(dom,type)	((type) << (2*(dom)))

#ifndef __ASSEMBLY__

#ifdef CONFIG_MMU
#ifdef CONFIG_CPU_USE_DOMAINS
#define set_domain(x)					\
	do {						\
	__asm__ __volatile__(				\
@@ -74,5 +78,28 @@
#define modify_domain(dom,type)	do { } while (0)
#endif

/*
 * Generate the T (user) versions of the LDR/STR and related
 * instructions (inline assembly)
 */
#ifdef CONFIG_CPU_USE_DOMAINS
#define T(instr)	#instr "t"
#else
#define T(instr)	#instr
#endif
#endif /* !__ASSEMBLY__ */

#else /* __ASSEMBLY__ */

/*
 * Generate the T (user) versions of the LDR/STR and related
 * instructions
 */
#ifdef CONFIG_CPU_USE_DOMAINS
#define T(instr)	instr ## t
#else
#define T(instr)	instr
#endif

#endif /* __ASSEMBLY__ */

#endif /* !__ASM_PROC_DOMAIN_H */
+5 −4
Original line number Diff line number Diff line
@@ -13,12 +13,13 @@
#include <linux/preempt.h>
#include <linux/uaccess.h>
#include <asm/errno.h>
#include <asm/domain.h>

#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
	__asm__ __volatile__(					\
	"1:	ldrt	%1, [%2]\n"				\
	"1:	" T(ldr) "	%1, [%2]\n"			\
	"	" insn "\n"					\
	"2:	strt	%0, [%2]\n"				\
	"2:	" T(str) "	%0, [%2]\n"			\
	"	mov	%0, #0\n"				\
	"3:\n"							\
	"	.pushsection __ex_table,\"a\"\n"		\
@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
	pagefault_disable();	/* implies preempt_disable() */

	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
	"1:	ldrt	%0, [%3]\n"
	"1:	" T(ldr) "	%0, [%3]\n"
	"	teq	%0, %1\n"
	"	it	eq	@ explicit IT needed for the 2b label\n"
	"2:	streqt	%2, [%3]\n"
	"2:	" T(streq) "	%2, [%3]\n"
	"3:\n"
	"	.pushsection __ex_table,\"a\"\n"
	"	.align	3\n"
+2 −0
Original line number Diff line number Diff line
@@ -27,4 +27,6 @@ static inline int in_exception_text(unsigned long ptr)
extern void __init early_trap_init(void);
extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);

extern void *vectors_page;

#endif
+8 −8
Original line number Diff line number Diff line
@@ -227,7 +227,7 @@ do { \

#define __get_user_asm_byte(x,addr,err)				\
	__asm__ __volatile__(					\
	"1:	ldrbt	%1,[%2]\n"				\
	"1:	" T(ldrb) "	%1,[%2],#0\n"			\
	"2:\n"							\
	"	.pushsection .fixup,\"ax\"\n"			\
	"	.align	2\n"					\
@@ -263,7 +263,7 @@ do { \

#define __get_user_asm_word(x,addr,err)				\
	__asm__ __volatile__(					\
	"1:	ldrt	%1,[%2]\n"				\
	"1:	" T(ldr) "	%1,[%2],#0\n"			\
	"2:\n"							\
	"	.pushsection .fixup,\"ax\"\n"			\
	"	.align	2\n"					\
@@ -308,7 +308,7 @@ do { \

#define __put_user_asm_byte(x,__pu_addr,err)			\
	__asm__ __volatile__(					\
	"1:	strbt	%1,[%2]\n"				\
	"1:	" T(strb) "	%1,[%2],#0\n"			\
	"2:\n"							\
	"	.pushsection .fixup,\"ax\"\n"			\
	"	.align	2\n"					\
@@ -341,7 +341,7 @@ do { \

#define __put_user_asm_word(x,__pu_addr,err)			\
	__asm__ __volatile__(					\
	"1:	strt	%1,[%2]\n"				\
	"1:	" T(str) "	%1,[%2],#0\n"			\
	"2:\n"							\
	"	.pushsection .fixup,\"ax\"\n"			\
	"	.align	2\n"					\
@@ -366,10 +366,10 @@ do { \

#define __put_user_asm_dword(x,__pu_addr,err)			\
	__asm__ __volatile__(					\
 ARM(	"1:	strt	" __reg_oper1 ", [%1], #4\n"	)	\
 ARM(	"2:	strt	" __reg_oper0 ", [%1]\n"	)	\
 THUMB(	"1:	strt	" __reg_oper1 ", [%1]\n"	)	\
 THUMB(	"2:	strt	" __reg_oper0 ", [%1, #4]\n"	)	\
 ARM(	"1:	" T(str) "	" __reg_oper1 ", [%1], #4\n"	)	\
 ARM(	"2:	" T(str) "	" __reg_oper0 ", [%1]\n"	)	\
 THUMB(	"1:	" T(str) "	" __reg_oper1 ", [%1]\n"	)	\
 THUMB(	"2:	" T(str) "	" __reg_oper0 ", [%1, #4]\n"	)	\
	"3:\n"							\
	"	.pushsection .fixup,\"ax\"\n"			\
	"	.align	2\n"					\
Loading