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>
This commit is contained in:
Catalin Marinas 2010-09-13 16:03:21 +01:00 committed by Russell King
parent ff8b16d7e1
commit 247055aa21
15 changed files with 153 additions and 92 deletions

View File

@ -18,6 +18,7 @@
#endif #endif
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/domain.h>
/* /*
* Endian independent macros for shifting bytes within registers. * Endian independent macros for shifting bytes within registers.
@ -206,12 +207,12 @@
*/ */
#ifdef CONFIG_THUMB2_KERNEL #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: 9999:
.if \inc == 1 .if \inc == 1
\instr\cond\()bt \reg, [\ptr, #\off] \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
.elseif \inc == 4 .elseif \inc == 4
\instr\cond\()t \reg, [\ptr, #\off] \instr\cond\()\t\().w \reg, [\ptr, #\off]
.else .else
.error "Unsupported inc macro argument" .error "Unsupported inc macro argument"
.endif .endif
@ -246,13 +247,13 @@
#else /* !CONFIG_THUMB2_KERNEL */ #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 .rept \rept
9999: 9999:
.if \inc == 1 .if \inc == 1
\instr\cond\()bt \reg, [\ptr], #\inc \instr\cond\()b\()\t \reg, [\ptr], #\inc
.elseif \inc == 4 .elseif \inc == 4
\instr\cond\()t \reg, [\ptr], #\inc \instr\cond\()\t \reg, [\ptr], #\inc
.else .else
.error "Unsupported inc macro argument" .error "Unsupported inc macro argument"
.endif .endif

View File

@ -45,13 +45,17 @@
*/ */
#define DOMAIN_NOACCESS 0 #define DOMAIN_NOACCESS 0
#define DOMAIN_CLIENT 1 #define DOMAIN_CLIENT 1
#ifdef CONFIG_CPU_USE_DOMAINS
#define DOMAIN_MANAGER 3 #define DOMAIN_MANAGER 3
#else
#define DOMAIN_MANAGER 1
#endif
#define domain_val(dom,type) ((type) << (2*(dom))) #define domain_val(dom,type) ((type) << (2*(dom)))
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef CONFIG_MMU #ifdef CONFIG_CPU_USE_DOMAINS
#define set_domain(x) \ #define set_domain(x) \
do { \ do { \
__asm__ __volatile__( \ __asm__ __volatile__( \
@ -74,5 +78,28 @@
#define modify_domain(dom,type) do { } while (0) #define modify_domain(dom,type) do { } while (0)
#endif #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
#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 */

View File

@ -13,12 +13,13 @@
#include <linux/preempt.h> #include <linux/preempt.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/domain.h>
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: ldrt %1, [%2]\n" \ "1: " T(ldr) " %1, [%2]\n" \
" " insn "\n" \ " " insn "\n" \
"2: strt %0, [%2]\n" \ "2: " T(str) " %0, [%2]\n" \
" mov %0, #0\n" \ " mov %0, #0\n" \
"3:\n" \ "3:\n" \
" .pushsection __ex_table,\"a\"\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() */ pagefault_disable(); /* implies preempt_disable() */
__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
"1: ldrt %0, [%3]\n" "1: " T(ldr) " %0, [%3]\n"
" teq %0, %1\n" " teq %0, %1\n"
" it eq @ explicit IT needed for the 2b label\n" " it eq @ explicit IT needed for the 2b label\n"
"2: streqt %2, [%3]\n" "2: " T(streq) " %2, [%3]\n"
"3:\n" "3:\n"
" .pushsection __ex_table,\"a\"\n" " .pushsection __ex_table,\"a\"\n"
" .align 3\n" " .align 3\n"

View File

@ -27,4 +27,6 @@ static inline int in_exception_text(unsigned long ptr)
extern void __init early_trap_init(void); extern void __init early_trap_init(void);
extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
extern void *vectors_page;
#endif #endif

View File

@ -227,7 +227,7 @@ do { \
#define __get_user_asm_byte(x,addr,err) \ #define __get_user_asm_byte(x,addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: ldrbt %1,[%2]\n" \ "1: " T(ldrb) " %1,[%2],#0\n" \
"2:\n" \ "2:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
@ -263,7 +263,7 @@ do { \
#define __get_user_asm_word(x,addr,err) \ #define __get_user_asm_word(x,addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: ldrt %1,[%2]\n" \ "1: " T(ldr) " %1,[%2],#0\n" \
"2:\n" \ "2:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
@ -308,7 +308,7 @@ do { \
#define __put_user_asm_byte(x,__pu_addr,err) \ #define __put_user_asm_byte(x,__pu_addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: strbt %1,[%2]\n" \ "1: " T(strb) " %1,[%2],#0\n" \
"2:\n" \ "2:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
@ -341,7 +341,7 @@ do { \
#define __put_user_asm_word(x,__pu_addr,err) \ #define __put_user_asm_word(x,__pu_addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: strt %1,[%2]\n" \ "1: " T(str) " %1,[%2],#0\n" \
"2:\n" \ "2:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
@ -366,10 +366,10 @@ do { \
#define __put_user_asm_dword(x,__pu_addr,err) \ #define __put_user_asm_dword(x,__pu_addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
ARM( "1: strt " __reg_oper1 ", [%1], #4\n" ) \ ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \
ARM( "2: strt " __reg_oper0 ", [%1]\n" ) \ ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \
THUMB( "1: strt " __reg_oper1 ", [%1]\n" ) \ THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \
THUMB( "2: strt " __reg_oper0 ", [%1, #4]\n" ) \ THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \
"3:\n" \ "3:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \

View File

@ -735,7 +735,7 @@ ENTRY(__switch_to)
THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack
THUMB( str sp, [ip], #4 ) THUMB( str sp, [ip], #4 )
THUMB( str lr, [ip], #4 ) THUMB( str lr, [ip], #4 )
#ifdef CONFIG_MMU #ifdef CONFIG_CPU_USE_DOMAINS
ldr r6, [r2, #TI_CPU_DOMAIN] ldr r6, [r2, #TI_CPU_DOMAIN]
#endif #endif
set_tls r3, r4, r5 set_tls r3, r4, r5
@ -744,7 +744,7 @@ ENTRY(__switch_to)
ldr r8, =__stack_chk_guard ldr r8, =__stack_chk_guard
ldr r7, [r7, #TSK_STACK_CANARY] ldr r7, [r7, #TSK_STACK_CANARY]
#endif #endif
#ifdef CONFIG_MMU #ifdef CONFIG_CPU_USE_DOMAINS
mcr p15, 0, r6, c3, c0, 0 @ Set domain register mcr p15, 0, r6, c3, c0, 0 @ Set domain register
#endif #endif
mov r5, r0 mov r5, r0

View File

@ -45,6 +45,7 @@
#include <asm/fiq.h> #include <asm/fiq.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/traps.h>
static unsigned long no_fiq_insn; static unsigned long no_fiq_insn;
@ -77,7 +78,11 @@ int show_fiq_list(struct seq_file *p, void *v)
void set_fiq_handler(void *start, unsigned int length) void set_fiq_handler(void *start, unsigned int length)
{ {
#if defined(CONFIG_CPU_USE_DOMAINS)
memcpy((void *)0xffff001c, start, length); memcpy((void *)0xffff001c, start, length);
#else
memcpy(vectors_page + 0x1c, start, length);
#endif
flush_icache_range(0xffff001c, 0xffff001c + length); flush_icache_range(0xffff001c, 0xffff001c + length);
if (!vectors_high()) if (!vectors_high())
flush_icache_range(0x1c, 0x1c + length); flush_icache_range(0x1c, 0x1c + length);

View File

@ -37,6 +37,8 @@
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
void *vectors_page;
#ifdef CONFIG_DEBUG_USER #ifdef CONFIG_DEBUG_USER
unsigned int user_debug; unsigned int user_debug;
@ -759,7 +761,11 @@ static void __init kuser_get_tls_init(unsigned long vectors)
void __init early_trap_init(void) void __init early_trap_init(void)
{ {
#if defined(CONFIG_CPU_USE_DOMAINS)
unsigned long vectors = CONFIG_VECTORS_BASE; unsigned long vectors = CONFIG_VECTORS_BASE;
#else
unsigned long vectors = (unsigned long)vectors_page;
#endif
extern char __stubs_start[], __stubs_end[]; extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[]; extern char __vectors_start[], __vectors_end[];
extern char __kuser_helper_start[], __kuser_helper_end[]; extern char __kuser_helper_start[], __kuser_helper_end[];
@ -783,10 +789,10 @@ void __init early_trap_init(void)
* Copy signal return handlers into the vector page, and * Copy signal return handlers into the vector page, and
* set sigreturn to be a pointer to these. * set sigreturn to be a pointer to these.
*/ */
memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
sizeof(sigreturn_codes)); sigreturn_codes, sizeof(sigreturn_codes));
memcpy((void *)KERN_RESTART_CODE, syscall_restart_code, memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
sizeof(syscall_restart_code)); syscall_restart_code, sizeof(syscall_restart_code));
flush_icache_range(vectors, vectors + PAGE_SIZE); flush_icache_range(vectors, vectors + PAGE_SIZE);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT); modify_domain(DOMAIN_USER, DOMAIN_CLIENT);

View File

@ -28,20 +28,21 @@
*/ */
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/domain.h>
ENTRY(__get_user_1) ENTRY(__get_user_1)
1: ldrbt r2, [r0] 1: T(ldrb) r2, [r0]
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
ENDPROC(__get_user_1) ENDPROC(__get_user_1)
ENTRY(__get_user_2) ENTRY(__get_user_2)
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
2: ldrbt r2, [r0] 2: T(ldrb) r2, [r0]
3: ldrbt r3, [r0, #1] 3: T(ldrb) r3, [r0, #1]
#else #else
2: ldrbt r2, [r0], #1 2: T(ldrb) r2, [r0], #1
3: ldrbt r3, [r0] 3: T(ldrb) r3, [r0]
#endif #endif
#ifndef __ARMEB__ #ifndef __ARMEB__
orr r2, r2, r3, lsl #8 orr r2, r2, r3, lsl #8
@ -53,7 +54,7 @@ ENTRY(__get_user_2)
ENDPROC(__get_user_2) ENDPROC(__get_user_2)
ENTRY(__get_user_4) ENTRY(__get_user_4)
4: ldrt r2, [r0] 4: T(ldr) r2, [r0]
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
ENDPROC(__get_user_4) ENDPROC(__get_user_4)

View File

@ -28,9 +28,10 @@
*/ */
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/domain.h>
ENTRY(__put_user_1) ENTRY(__put_user_1)
1: strbt r2, [r0] 1: T(strb) r2, [r0]
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
ENDPROC(__put_user_1) ENDPROC(__put_user_1)
@ -39,19 +40,19 @@ ENTRY(__put_user_2)
mov ip, r2, lsr #8 mov ip, r2, lsr #8
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
#ifndef __ARMEB__ #ifndef __ARMEB__
2: strbt r2, [r0] 2: T(strb) r2, [r0]
3: strbt ip, [r0, #1] 3: T(strb) ip, [r0, #1]
#else #else
2: strbt ip, [r0] 2: T(strb) ip, [r0]
3: strbt r2, [r0, #1] 3: T(strb) r2, [r0, #1]
#endif #endif
#else /* !CONFIG_THUMB2_KERNEL */ #else /* !CONFIG_THUMB2_KERNEL */
#ifndef __ARMEB__ #ifndef __ARMEB__
2: strbt r2, [r0], #1 2: T(strb) r2, [r0], #1
3: strbt ip, [r0] 3: T(strb) ip, [r0]
#else #else
2: strbt ip, [r0], #1 2: T(strb) ip, [r0], #1
3: strbt r2, [r0] 3: T(strb) r2, [r0]
#endif #endif
#endif /* CONFIG_THUMB2_KERNEL */ #endif /* CONFIG_THUMB2_KERNEL */
mov r0, #0 mov r0, #0
@ -59,18 +60,18 @@ ENTRY(__put_user_2)
ENDPROC(__put_user_2) ENDPROC(__put_user_2)
ENTRY(__put_user_4) ENTRY(__put_user_4)
4: strt r2, [r0] 4: T(str) r2, [r0]
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
ENDPROC(__put_user_4) ENDPROC(__put_user_4)
ENTRY(__put_user_8) ENTRY(__put_user_8)
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
5: strt r2, [r0] 5: T(str) r2, [r0]
6: strt r3, [r0, #4] 6: T(str) r3, [r0, #4]
#else #else
5: strt r2, [r0], #4 5: T(str) r2, [r0], #4
6: strt r3, [r0] 6: T(str) r3, [r0]
#endif #endif
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr

View File

@ -14,6 +14,7 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/domain.h>
.text .text
@ -31,11 +32,11 @@
rsb ip, ip, #4 rsb ip, ip, #4
cmp ip, #2 cmp ip, #2
ldrb r3, [r1], #1 ldrb r3, [r1], #1
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1 ldrgeb r3, [r1], #1
USER( strgebt r3, [r0], #1) @ May fault USER( T(strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #1 ldrgtb r3, [r1], #1
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
sub r2, r2, ip sub r2, r2, ip
b .Lc2u_dest_aligned b .Lc2u_dest_aligned
@ -58,7 +59,7 @@ ENTRY(__copy_to_user)
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lc2u_0nowords bmi .Lc2u_0nowords
ldr r3, [r1], #4 ldr r3, [r1], #4
USER( strt r3, [r0], #4) @ May fault USER( T(str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
rsb ip, ip, #0 rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT movs ip, ip, lsr #32 - PAGE_SHIFT
@ -87,18 +88,18 @@ USER( strt r3, [r0], #4) @ May fault
stmneia r0!, {r3 - r4} @ Shouldnt fault stmneia r0!, {r3 - r4} @ Shouldnt fault
tst ip, #4 tst ip, #4
ldrne r3, [r1], #4 ldrne r3, [r1], #4
strnet r3, [r0], #4 @ Shouldnt fault T(strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3 ands ip, ip, #3
beq .Lc2u_0fupi beq .Lc2u_0fupi
.Lc2u_0nowords: teq ip, #0 .Lc2u_0nowords: teq ip, #0
beq .Lc2u_finished beq .Lc2u_finished
.Lc2u_nowords: cmp ip, #2 .Lc2u_nowords: cmp ip, #2
ldrb r3, [r1], #1 ldrb r3, [r1], #1
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1 ldrgeb r3, [r1], #1
USER( strgebt r3, [r0], #1) @ May fault USER( T(strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #1 ldrgtb r3, [r1], #1
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished b .Lc2u_finished
.Lc2u_not_enough: .Lc2u_not_enough:
@ -119,7 +120,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
mov r3, r7, pull #8 mov r3, r7, pull #8
ldr r7, [r1], #4 ldr r7, [r1], #4
orr r3, r3, r7, push #24 orr r3, r3, r7, push #24
USER( strt r3, [r0], #4) @ May fault USER( T(str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0 rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT movs ip, ip, lsr #32 - PAGE_SHIFT
@ -154,18 +155,18 @@ USER( strt r3, [r0], #4) @ May fault
movne r3, r7, pull #8 movne r3, r7, pull #8
ldrne r7, [r1], #4 ldrne r7, [r1], #4
orrne r3, r3, r7, push #24 orrne r3, r3, r7, push #24
strnet r3, [r0], #4 @ Shouldnt fault T(strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3 ands ip, ip, #3
beq .Lc2u_1fupi beq .Lc2u_1fupi
.Lc2u_1nowords: mov r3, r7, get_byte_1 .Lc2u_1nowords: mov r3, r7, get_byte_1
teq ip, #0 teq ip, #0
beq .Lc2u_finished beq .Lc2u_finished
cmp ip, #2 cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
movge r3, r7, get_byte_2 movge r3, r7, get_byte_2
USER( strgebt r3, [r0], #1) @ May fault USER( T(strgeb) r3, [r0], #1) @ May fault
movgt r3, r7, get_byte_3 movgt r3, r7, get_byte_3
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished b .Lc2u_finished
.Lc2u_2fupi: subs r2, r2, #4 .Lc2u_2fupi: subs r2, r2, #4
@ -174,7 +175,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
mov r3, r7, pull #16 mov r3, r7, pull #16
ldr r7, [r1], #4 ldr r7, [r1], #4
orr r3, r3, r7, push #16 orr r3, r3, r7, push #16
USER( strt r3, [r0], #4) @ May fault USER( T(str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0 rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT movs ip, ip, lsr #32 - PAGE_SHIFT
@ -209,18 +210,18 @@ USER( strt r3, [r0], #4) @ May fault
movne r3, r7, pull #16 movne r3, r7, pull #16
ldrne r7, [r1], #4 ldrne r7, [r1], #4
orrne r3, r3, r7, push #16 orrne r3, r3, r7, push #16
strnet r3, [r0], #4 @ Shouldnt fault T(strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3 ands ip, ip, #3
beq .Lc2u_2fupi beq .Lc2u_2fupi
.Lc2u_2nowords: mov r3, r7, get_byte_2 .Lc2u_2nowords: mov r3, r7, get_byte_2
teq ip, #0 teq ip, #0
beq .Lc2u_finished beq .Lc2u_finished
cmp ip, #2 cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
movge r3, r7, get_byte_3 movge r3, r7, get_byte_3
USER( strgebt r3, [r0], #1) @ May fault USER( T(strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #0 ldrgtb r3, [r1], #0
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished b .Lc2u_finished
.Lc2u_3fupi: subs r2, r2, #4 .Lc2u_3fupi: subs r2, r2, #4
@ -229,7 +230,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
mov r3, r7, pull #24 mov r3, r7, pull #24
ldr r7, [r1], #4 ldr r7, [r1], #4
orr r3, r3, r7, push #8 orr r3, r3, r7, push #8
USER( strt r3, [r0], #4) @ May fault USER( T(str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0 rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT movs ip, ip, lsr #32 - PAGE_SHIFT
@ -264,18 +265,18 @@ USER( strt r3, [r0], #4) @ May fault
movne r3, r7, pull #24 movne r3, r7, pull #24
ldrne r7, [r1], #4 ldrne r7, [r1], #4
orrne r3, r3, r7, push #8 orrne r3, r3, r7, push #8
strnet r3, [r0], #4 @ Shouldnt fault T(strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3 ands ip, ip, #3
beq .Lc2u_3fupi beq .Lc2u_3fupi
.Lc2u_3nowords: mov r3, r7, get_byte_3 .Lc2u_3nowords: mov r3, r7, get_byte_3
teq ip, #0 teq ip, #0
beq .Lc2u_finished beq .Lc2u_finished
cmp ip, #2 cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1 ldrgeb r3, [r1], #1
USER( strgebt r3, [r0], #1) @ May fault USER( T(strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #0 ldrgtb r3, [r1], #0
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished b .Lc2u_finished
ENDPROC(__copy_to_user) ENDPROC(__copy_to_user)
@ -294,11 +295,11 @@ ENDPROC(__copy_to_user)
.Lcfu_dest_not_aligned: .Lcfu_dest_not_aligned:
rsb ip, ip, #4 rsb ip, ip, #4
cmp ip, #2 cmp ip, #2
USER( ldrbt r3, [r1], #1) @ May fault USER( T(ldrb) r3, [r1], #1) @ May fault
strb r3, [r0], #1 strb r3, [r0], #1
USER( ldrgebt r3, [r1], #1) @ May fault USER( T(ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1 strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #1) @ May fault USER( T(ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1 strgtb r3, [r0], #1
sub r2, r2, ip sub r2, r2, ip
b .Lcfu_dest_aligned b .Lcfu_dest_aligned
@ -321,7 +322,7 @@ ENTRY(__copy_from_user)
.Lcfu_0fupi: subs r2, r2, #4 .Lcfu_0fupi: subs r2, r2, #4
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lcfu_0nowords bmi .Lcfu_0nowords
USER( ldrt r3, [r1], #4) USER( T(ldr) r3, [r1], #4)
str r3, [r0], #4 str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
rsb ip, ip, #0 rsb ip, ip, #0
@ -350,18 +351,18 @@ USER( ldrt r3, [r1], #4)
ldmneia r1!, {r3 - r4} @ Shouldnt fault ldmneia r1!, {r3 - r4} @ Shouldnt fault
stmneia r0!, {r3 - r4} stmneia r0!, {r3 - r4}
tst ip, #4 tst ip, #4
ldrnet r3, [r1], #4 @ Shouldnt fault T(ldrne) r3, [r1], #4 @ Shouldnt fault
strne r3, [r0], #4 strne r3, [r0], #4
ands ip, ip, #3 ands ip, ip, #3
beq .Lcfu_0fupi beq .Lcfu_0fupi
.Lcfu_0nowords: teq ip, #0 .Lcfu_0nowords: teq ip, #0
beq .Lcfu_finished beq .Lcfu_finished
.Lcfu_nowords: cmp ip, #2 .Lcfu_nowords: cmp ip, #2
USER( ldrbt r3, [r1], #1) @ May fault USER( T(ldrb) r3, [r1], #1) @ May fault
strb r3, [r0], #1 strb r3, [r0], #1
USER( ldrgebt r3, [r1], #1) @ May fault USER( T(ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1 strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #1) @ May fault USER( T(ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1 strgtb r3, [r0], #1
b .Lcfu_finished b .Lcfu_finished
@ -374,7 +375,7 @@ USER( ldrgtbt r3, [r1], #1) @ May fault
.Lcfu_src_not_aligned: .Lcfu_src_not_aligned:
bic r1, r1, #3 bic r1, r1, #3
USER( ldrt r7, [r1], #4) @ May fault USER( T(ldr) r7, [r1], #4) @ May fault
cmp ip, #2 cmp ip, #2
bgt .Lcfu_3fupi bgt .Lcfu_3fupi
beq .Lcfu_2fupi beq .Lcfu_2fupi
@ -382,7 +383,7 @@ USER( ldrt r7, [r1], #4) @ May fault
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lcfu_1nowords bmi .Lcfu_1nowords
mov r3, r7, pull #8 mov r3, r7, pull #8
USER( ldrt r7, [r1], #4) @ May fault USER( T(ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #24 orr r3, r3, r7, push #24
str r3, [r0], #4 str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT mov ip, r1, lsl #32 - PAGE_SHIFT
@ -417,7 +418,7 @@ USER( ldrt r7, [r1], #4) @ May fault
stmneia r0!, {r3 - r4} stmneia r0!, {r3 - r4}
tst ip, #4 tst ip, #4
movne r3, r7, pull #8 movne r3, r7, pull #8
USER( ldrnet r7, [r1], #4) @ May fault USER( T(ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #24 orrne r3, r3, r7, push #24
strne r3, [r0], #4 strne r3, [r0], #4
ands ip, ip, #3 ands ip, ip, #3
@ -437,7 +438,7 @@ USER( ldrnet r7, [r1], #4) @ May fault
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lcfu_2nowords bmi .Lcfu_2nowords
mov r3, r7, pull #16 mov r3, r7, pull #16
USER( ldrt r7, [r1], #4) @ May fault USER( T(ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #16 orr r3, r3, r7, push #16
str r3, [r0], #4 str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT mov ip, r1, lsl #32 - PAGE_SHIFT
@ -473,7 +474,7 @@ USER( ldrt r7, [r1], #4) @ May fault
stmneia r0!, {r3 - r4} stmneia r0!, {r3 - r4}
tst ip, #4 tst ip, #4
movne r3, r7, pull #16 movne r3, r7, pull #16
USER( ldrnet r7, [r1], #4) @ May fault USER( T(ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #16 orrne r3, r3, r7, push #16
strne r3, [r0], #4 strne r3, [r0], #4
ands ip, ip, #3 ands ip, ip, #3
@ -485,7 +486,7 @@ USER( ldrnet r7, [r1], #4) @ May fault
strb r3, [r0], #1 strb r3, [r0], #1
movge r3, r7, get_byte_3 movge r3, r7, get_byte_3
strgeb r3, [r0], #1 strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #0) @ May fault USER( T(ldrgtb) r3, [r1], #0) @ May fault
strgtb r3, [r0], #1 strgtb r3, [r0], #1
b .Lcfu_finished b .Lcfu_finished
@ -493,7 +494,7 @@ USER( ldrgtbt r3, [r1], #0) @ May fault
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lcfu_3nowords bmi .Lcfu_3nowords
mov r3, r7, pull #24 mov r3, r7, pull #24
USER( ldrt r7, [r1], #4) @ May fault USER( T(ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #8 orr r3, r3, r7, push #8
str r3, [r0], #4 str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT mov ip, r1, lsl #32 - PAGE_SHIFT
@ -528,7 +529,7 @@ USER( ldrt r7, [r1], #4) @ May fault
stmneia r0!, {r3 - r4} stmneia r0!, {r3 - r4}
tst ip, #4 tst ip, #4
movne r3, r7, pull #24 movne r3, r7, pull #24
USER( ldrnet r7, [r1], #4) @ May fault USER( T(ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #8 orrne r3, r3, r7, push #8
strne r3, [r0], #4 strne r3, [r0], #4
ands ip, ip, #3 ands ip, ip, #3
@ -538,9 +539,9 @@ USER( ldrnet r7, [r1], #4) @ May fault
beq .Lcfu_finished beq .Lcfu_finished
cmp ip, #2 cmp ip, #2
strb r3, [r0], #1 strb r3, [r0], #1
USER( ldrgebt r3, [r1], #1) @ May fault USER( T(ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1 strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #1) @ May fault USER( T(ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1 strgtb r3, [r0], #1
b .Lcfu_finished b .Lcfu_finished
ENDPROC(__copy_from_user) ENDPROC(__copy_from_user)

View File

@ -599,6 +599,14 @@ config CPU_CP15_MPU
help help
Processor has the CP15 register, which has MPU related registers. Processor has the CP15 register, which has MPU related registers.
config CPU_USE_DOMAINS
bool
depends on MMU
default y if !CPU_32v6K
help
This option enables or disables the use of domain switching
via the set_fs() function.
# #
# CPU supports 36-bit I/O # CPU supports 36-bit I/O
# #

View File

@ -24,6 +24,7 @@
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/highmem.h> #include <asm/highmem.h>
#include <asm/traps.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
@ -914,12 +915,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
{ {
struct map_desc map; struct map_desc map;
unsigned long addr; unsigned long addr;
void *vectors;
/* /*
* Allocate the vector page early. * Allocate the vector page early.
*/ */
vectors = early_alloc(PAGE_SIZE); vectors_page = early_alloc(PAGE_SIZE);
for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
pmd_clear(pmd_off_k(addr)); pmd_clear(pmd_off_k(addr));
@ -959,7 +959,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
* location (0xffff0000). If we aren't using high-vectors, also * location (0xffff0000). If we aren't using high-vectors, also
* create a mapping at the low-vectors virtual address. * create a mapping at the low-vectors virtual address.
*/ */
map.pfn = __phys_to_pfn(virt_to_phys(vectors)); map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
map.virtual = 0xffff0000; map.virtual = 0xffff0000;
map.length = PAGE_SIZE; map.length = PAGE_SIZE;
map.type = MT_HIGH_VECTORS; map.type = MT_HIGH_VECTORS;

View File

@ -99,6 +99,10 @@
* 110x 0 1 0 r/w r/o * 110x 0 1 0 r/w r/o
* 11x0 0 1 0 r/w r/o * 11x0 0 1 0 r/w r/o
* 1111 0 1 1 r/w r/w * 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
*/ */
.macro armv6_mt_table pfx .macro armv6_mt_table pfx
\pfx\()_mt_table: \pfx\()_mt_table:
@ -138,8 +142,11 @@
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 bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
#endif
tst r1, #L_PTE_EXEC tst r1, #L_PTE_EXEC
orreq r3, r3, #PTE_EXT_XN orreq r3, r3, #PTE_EXT_XN

View File

@ -148,8 +148,11 @@ 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 tstne r3, #PTE_EXT_APX
bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
#endif
tst r1, #L_PTE_EXEC tst r1, #L_PTE_EXEC
orreq r3, r3, #PTE_EXT_XN orreq r3, r3, #PTE_EXT_XN
@ -273,8 +276,6 @@ __v7_setup:
ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP)
ALT_UP(orr r4, r4, #TTB_FLAGS_UP) ALT_UP(orr r4, r4, #TTB_FLAGS_UP)
mcr p15, 0, r4, c2, c0, 1 @ load TTB1 mcr p15, 0, r4, c2, c0, 1 @ load TTB1
mov r10, #0x1f @ domains 0, 1 = manager
mcr p15, 0, r10, c3, c0, 0 @ load domain access register
/* /*
* Memory region attributes with SCTLR.TRE=1 * Memory region attributes with SCTLR.TRE=1
* *