diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2010-09-13 11:03:21 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-11-04 11:44:31 -0400 |
commit | 247055aa21ffef1c49dd64710d5e94c2aee19b58 (patch) | |
tree | e9e026b96597d080de4c16bb88c17b0495c61904 /arch/arm/include/asm | |
parent | ff8b16d7e15a8ba2a6086645614a483e048e3fbf (diff) |
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: Anton Vorontsov <cbouatmailru@gmail.com>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/include/asm')
-rw-r--r-- | arch/arm/include/asm/assembler.h | 13 | ||||
-rw-r--r-- | arch/arm/include/asm/domain.h | 31 | ||||
-rw-r--r-- | arch/arm/include/asm/futex.h | 9 | ||||
-rw-r--r-- | arch/arm/include/asm/traps.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/uaccess.h | 16 |
5 files changed, 51 insertions, 20 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 062b58c029ab..4e84d09c9c1b 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
21 | #include <asm/domain.h> | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * Endian independent macros for shifting bytes within registers. | 24 | * Endian independent macros for shifting bytes within registers. |
@@ -206,12 +207,12 @@ | |||
206 | */ | 207 | */ |
207 | #ifdef CONFIG_THUMB2_KERNEL | 208 | #ifdef CONFIG_THUMB2_KERNEL |
208 | 209 | ||
209 | .macro usraccoff, instr, reg, ptr, inc, off, cond, abort | 210 | .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T() |
210 | 9999: | 211 | 9999: |
211 | .if \inc == 1 | 212 | .if \inc == 1 |
212 | \instr\cond\()bt \reg, [\ptr, #\off] | 213 | \instr\cond\()b\()\t\().w \reg, [\ptr, #\off] |
213 | .elseif \inc == 4 | 214 | .elseif \inc == 4 |
214 | \instr\cond\()t \reg, [\ptr, #\off] | 215 | \instr\cond\()\t\().w \reg, [\ptr, #\off] |
215 | .else | 216 | .else |
216 | .error "Unsupported inc macro argument" | 217 | .error "Unsupported inc macro argument" |
217 | .endif | 218 | .endif |
@@ -246,13 +247,13 @@ | |||
246 | 247 | ||
247 | #else /* !CONFIG_THUMB2_KERNEL */ | 248 | #else /* !CONFIG_THUMB2_KERNEL */ |
248 | 249 | ||
249 | .macro usracc, instr, reg, ptr, inc, cond, rept, abort | 250 | .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=T() |
250 | .rept \rept | 251 | .rept \rept |
251 | 9999: | 252 | 9999: |
252 | .if \inc == 1 | 253 | .if \inc == 1 |
253 | \instr\cond\()bt \reg, [\ptr], #\inc | 254 | \instr\cond\()b\()\t \reg, [\ptr], #\inc |
254 | .elseif \inc == 4 | 255 | .elseif \inc == 4 |
255 | \instr\cond\()t \reg, [\ptr], #\inc | 256 | \instr\cond\()\t \reg, [\ptr], #\inc |
256 | .else | 257 | .else |
257 | .error "Unsupported inc macro argument" | 258 | .error "Unsupported inc macro argument" |
258 | .endif | 259 | .endif |
diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h index cc7ef4080711..af18ceaacf5d 100644 --- a/arch/arm/include/asm/domain.h +++ b/arch/arm/include/asm/domain.h | |||
@@ -45,13 +45,17 @@ | |||
45 | */ | 45 | */ |
46 | #define DOMAIN_NOACCESS 0 | 46 | #define DOMAIN_NOACCESS 0 |
47 | #define DOMAIN_CLIENT 1 | 47 | #define DOMAIN_CLIENT 1 |
48 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
48 | #define DOMAIN_MANAGER 3 | 49 | #define DOMAIN_MANAGER 3 |
50 | #else | ||
51 | #define DOMAIN_MANAGER 1 | ||
52 | #endif | ||
49 | 53 | ||
50 | #define domain_val(dom,type) ((type) << (2*(dom))) | 54 | #define domain_val(dom,type) ((type) << (2*(dom))) |
51 | 55 | ||
52 | #ifndef __ASSEMBLY__ | 56 | #ifndef __ASSEMBLY__ |
53 | 57 | ||
54 | #ifdef CONFIG_MMU | 58 | #ifdef CONFIG_CPU_USE_DOMAINS |
55 | #define set_domain(x) \ | 59 | #define set_domain(x) \ |
56 | do { \ | 60 | do { \ |
57 | __asm__ __volatile__( \ | 61 | __asm__ __volatile__( \ |
@@ -74,5 +78,28 @@ | |||
74 | #define modify_domain(dom,type) do { } while (0) | 78 | #define modify_domain(dom,type) do { } while (0) |
75 | #endif | 79 | #endif |
76 | 80 | ||
81 | /* | ||
82 | * Generate the T (user) versions of the LDR/STR and related | ||
83 | * instructions (inline assembly) | ||
84 | */ | ||
85 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
86 | #define T(instr) #instr "t" | ||
87 | #else | ||
88 | #define T(instr) #instr | ||
77 | #endif | 89 | #endif |
78 | #endif /* !__ASSEMBLY__ */ | 90 | |
91 | #else /* __ASSEMBLY__ */ | ||
92 | |||
93 | /* | ||
94 | * Generate the T (user) versions of the LDR/STR and related | ||
95 | * instructions | ||
96 | */ | ||
97 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
98 | #define T(instr) instr ## t | ||
99 | #else | ||
100 | #define T(instr) instr | ||
101 | #endif | ||
102 | |||
103 | #endif /* __ASSEMBLY__ */ | ||
104 | |||
105 | #endif /* !__ASM_PROC_DOMAIN_H */ | ||
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index 540a044153a5..b33fe7065b38 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h | |||
@@ -13,12 +13,13 @@ | |||
13 | #include <linux/preempt.h> | 13 | #include <linux/preempt.h> |
14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | #include <asm/errno.h> | 15 | #include <asm/errno.h> |
16 | #include <asm/domain.h> | ||
16 | 17 | ||
17 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | 18 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ |
18 | __asm__ __volatile__( \ | 19 | __asm__ __volatile__( \ |
19 | "1: ldrt %1, [%2]\n" \ | 20 | "1: " T(ldr) " %1, [%2]\n" \ |
20 | " " insn "\n" \ | 21 | " " insn "\n" \ |
21 | "2: strt %0, [%2]\n" \ | 22 | "2: " T(str) " %0, [%2]\n" \ |
22 | " mov %0, #0\n" \ | 23 | " mov %0, #0\n" \ |
23 | "3:\n" \ | 24 | "3:\n" \ |
24 | " .pushsection __ex_table,\"a\"\n" \ | 25 | " .pushsection __ex_table,\"a\"\n" \ |
@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | |||
97 | pagefault_disable(); /* implies preempt_disable() */ | 98 | pagefault_disable(); /* implies preempt_disable() */ |
98 | 99 | ||
99 | __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" | 100 | __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" |
100 | "1: ldrt %0, [%3]\n" | 101 | "1: " T(ldr) " %0, [%3]\n" |
101 | " teq %0, %1\n" | 102 | " teq %0, %1\n" |
102 | " it eq @ explicit IT needed for the 2b label\n" | 103 | " it eq @ explicit IT needed for the 2b label\n" |
103 | "2: streqt %2, [%3]\n" | 104 | "2: " T(streq) " %2, [%3]\n" |
104 | "3:\n" | 105 | "3:\n" |
105 | " .pushsection __ex_table,\"a\"\n" | 106 | " .pushsection __ex_table,\"a\"\n" |
106 | " .align 3\n" | 107 | " .align 3\n" |
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index 491960bf4260..af5d5d1388c6 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h | |||
@@ -27,4 +27,6 @@ static inline int in_exception_text(unsigned long ptr) | |||
27 | extern void __init early_trap_init(void); | 27 | extern void __init early_trap_init(void); |
28 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); | 28 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); |
29 | 29 | ||
30 | extern void *vectors_page; | ||
31 | |||
30 | #endif | 32 | #endif |
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 33e4a48fe103..b293616a1a1a 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h | |||
@@ -227,7 +227,7 @@ do { \ | |||
227 | 227 | ||
228 | #define __get_user_asm_byte(x,addr,err) \ | 228 | #define __get_user_asm_byte(x,addr,err) \ |
229 | __asm__ __volatile__( \ | 229 | __asm__ __volatile__( \ |
230 | "1: ldrbt %1,[%2]\n" \ | 230 | "1: " T(ldrb) " %1,[%2],#0\n" \ |
231 | "2:\n" \ | 231 | "2:\n" \ |
232 | " .pushsection .fixup,\"ax\"\n" \ | 232 | " .pushsection .fixup,\"ax\"\n" \ |
233 | " .align 2\n" \ | 233 | " .align 2\n" \ |
@@ -263,7 +263,7 @@ do { \ | |||
263 | 263 | ||
264 | #define __get_user_asm_word(x,addr,err) \ | 264 | #define __get_user_asm_word(x,addr,err) \ |
265 | __asm__ __volatile__( \ | 265 | __asm__ __volatile__( \ |
266 | "1: ldrt %1,[%2]\n" \ | 266 | "1: " T(ldr) " %1,[%2],#0\n" \ |
267 | "2:\n" \ | 267 | "2:\n" \ |
268 | " .pushsection .fixup,\"ax\"\n" \ | 268 | " .pushsection .fixup,\"ax\"\n" \ |
269 | " .align 2\n" \ | 269 | " .align 2\n" \ |
@@ -308,7 +308,7 @@ do { \ | |||
308 | 308 | ||
309 | #define __put_user_asm_byte(x,__pu_addr,err) \ | 309 | #define __put_user_asm_byte(x,__pu_addr,err) \ |
310 | __asm__ __volatile__( \ | 310 | __asm__ __volatile__( \ |
311 | "1: strbt %1,[%2]\n" \ | 311 | "1: " T(strb) " %1,[%2],#0\n" \ |
312 | "2:\n" \ | 312 | "2:\n" \ |
313 | " .pushsection .fixup,\"ax\"\n" \ | 313 | " .pushsection .fixup,\"ax\"\n" \ |
314 | " .align 2\n" \ | 314 | " .align 2\n" \ |
@@ -341,7 +341,7 @@ do { \ | |||
341 | 341 | ||
342 | #define __put_user_asm_word(x,__pu_addr,err) \ | 342 | #define __put_user_asm_word(x,__pu_addr,err) \ |
343 | __asm__ __volatile__( \ | 343 | __asm__ __volatile__( \ |
344 | "1: strt %1,[%2]\n" \ | 344 | "1: " T(str) " %1,[%2],#0\n" \ |
345 | "2:\n" \ | 345 | "2:\n" \ |
346 | " .pushsection .fixup,\"ax\"\n" \ | 346 | " .pushsection .fixup,\"ax\"\n" \ |
347 | " .align 2\n" \ | 347 | " .align 2\n" \ |
@@ -366,10 +366,10 @@ do { \ | |||
366 | 366 | ||
367 | #define __put_user_asm_dword(x,__pu_addr,err) \ | 367 | #define __put_user_asm_dword(x,__pu_addr,err) \ |
368 | __asm__ __volatile__( \ | 368 | __asm__ __volatile__( \ |
369 | ARM( "1: strt " __reg_oper1 ", [%1], #4\n" ) \ | 369 | ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \ |
370 | ARM( "2: strt " __reg_oper0 ", [%1]\n" ) \ | 370 | ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \ |
371 | THUMB( "1: strt " __reg_oper1 ", [%1]\n" ) \ | 371 | THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \ |
372 | THUMB( "2: strt " __reg_oper0 ", [%1, #4]\n" ) \ | 372 | THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \ |
373 | "3:\n" \ | 373 | "3:\n" \ |
374 | " .pushsection .fixup,\"ax\"\n" \ | 374 | " .pushsection .fixup,\"ax\"\n" \ |
375 | " .align 2\n" \ | 375 | " .align 2\n" \ |