Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
c2172ce2
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
c2172ce2
编写于
9月 11, 2015
作者:
R
Russell King
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'uaccess' into fixes
上级
a4a5a737
0b61f2c0
变更
31
隐藏空白更改
内联
并排
Showing
31 changed file
with
398 addition
and
139 deletion
+398
-139
arch/arm/Kconfig
arch/arm/Kconfig
+15
-0
arch/arm/include/asm/assembler.h
arch/arm/include/asm/assembler.h
+42
-0
arch/arm/include/asm/domain.h
arch/arm/include/asm/domain.h
+46
-11
arch/arm/include/asm/futex.h
arch/arm/include/asm/futex.h
+17
-2
arch/arm/include/asm/pgtable-2level-hwdef.h
arch/arm/include/asm/pgtable-2level-hwdef.h
+1
-0
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/thread_info.h
+0
-4
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/uaccess.h
+80
-5
arch/arm/kernel/armksyms.c
arch/arm/kernel/armksyms.c
+3
-3
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-armv.S
+24
-8
arch/arm/kernel/entry-common.S
arch/arm/kernel/entry-common.S
+2
-0
arch/arm/kernel/entry-header.S
arch/arm/kernel/entry-header.S
+47
-65
arch/arm/kernel/head.S
arch/arm/kernel/head.S
+1
-4
arch/arm/kernel/process.c
arch/arm/kernel/process.c
+42
-9
arch/arm/kernel/swp_emulate.c
arch/arm/kernel/swp_emulate.c
+3
-0
arch/arm/kernel/traps.c
arch/arm/kernel/traps.c
+0
-1
arch/arm/lib/clear_user.S
arch/arm/lib/clear_user.S
+3
-3
arch/arm/lib/copy_from_user.S
arch/arm/lib/copy_from_user.S
+3
-3
arch/arm/lib/copy_to_user.S
arch/arm/lib/copy_to_user.S
+3
-3
arch/arm/lib/csumpartialcopyuser.S
arch/arm/lib/csumpartialcopyuser.S
+14
-0
arch/arm/lib/uaccess_with_memcpy.c
arch/arm/lib/uaccess_with_memcpy.c
+2
-2
arch/arm/mm/abort-ev4.S
arch/arm/mm/abort-ev4.S
+1
-0
arch/arm/mm/abort-ev5t.S
arch/arm/mm/abort-ev5t.S
+3
-1
arch/arm/mm/abort-ev5tj.S
arch/arm/mm/abort-ev5tj.S
+3
-1
arch/arm/mm/abort-ev6.S
arch/arm/mm/abort-ev6.S
+5
-3
arch/arm/mm/abort-ev7.S
arch/arm/mm/abort-ev7.S
+1
-0
arch/arm/mm/abort-lv4t.S
arch/arm/mm/abort-lv4t.S
+2
-0
arch/arm/mm/abort-macro.S
arch/arm/mm/abort-macro.S
+6
-8
arch/arm/mm/mmu.c
arch/arm/mm/mmu.c
+2
-2
arch/arm/mm/pgd.c
arch/arm/mm/pgd.c
+10
-0
arch/arm/nwfpe/entry.S
arch/arm/nwfpe/entry.S
+2
-1
arch/arm/xen/hypercall.S
arch/arm/xen/hypercall.S
+15
-0
未找到文件。
arch/arm/Kconfig
浏览文件 @
c2172ce2
...
...
@@ -1700,6 +1700,21 @@ config HIGHPTE
consumed by page tables. Setting this option will allow
user-space 2nd level page tables to reside in high memory.
config CPU_SW_DOMAIN_PAN
bool "Enable use of CPU domains to implement privileged no-access"
depends on MMU && !ARM_LPAE
default y
help
Increase kernel security by ensuring that normal kernel accesses
are unable to access userspace addresses. This can help prevent
use-after-free bugs becoming an exploitable privilege escalation
by ensuring that magic values (such as LIST_POISON) will always
fault when dereferenced.
CPUs with low-vector mappings use a best-efforts implementation.
Their lower 1MB needs to remain accessible for the vectors, but
the remainder of userspace will become appropriately inaccessible.
config HW_PERF_EVENTS
bool "Enable hardware performance counter support for perf events"
depends on PERF_EVENTS
...
...
arch/arm/include/asm/assembler.h
浏览文件 @
c2172ce2
...
...
@@ -445,6 +445,48 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
#endif
.
endm
.
macro
uaccess_disable
,
tmp
,
isb
=
1
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
/*
* Whenever we re-enter userspace, the domains should always be
* set appropriately.
*/
mov
\
tmp
,
#
DACR_UACCESS_DISABLE
mcr
p15
,
0
,
\
tmp
,
c3
,
c0
,
0
@
Set
domain
register
.
if
\
isb
instr_sync
.
endif
#endif
.
endm
.
macro
uaccess_enable
,
tmp
,
isb
=
1
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
/*
* Whenever we re-enter userspace, the domains should always be
* set appropriately.
*/
mov
\
tmp
,
#
DACR_UACCESS_ENABLE
mcr
p15
,
0
,
\
tmp
,
c3
,
c0
,
0
.
if
\
isb
instr_sync
.
endif
#endif
.
endm
.
macro
uaccess_save
,
tmp
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
mrc
p15
,
0
,
\
tmp
,
c3
,
c0
,
0
str
\
tmp
,
[
sp
,
#
S_FRAME_SIZE
]
#endif
.
endm
.
macro
uaccess_restore
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
ldr
r0
,
[
sp
,
#
S_FRAME_SIZE
]
mcr
p15
,
0
,
r0
,
c3
,
c0
,
0
#endif
.
endm
.
irp
c
,,
eq
,
ne
,
cs
,
cc
,
mi
,
pl
,
vs
,
vc
,
hi
,
ls
,
ge
,
lt
,
gt
,
le
,
hs
,
lo
.
macro
ret
\
c
,
reg
#if __LINUX_ARM_ARCH__ < 6
...
...
arch/arm/include/asm/domain.h
浏览文件 @
c2172ce2
...
...
@@ -12,6 +12,7 @@
#ifndef __ASSEMBLY__
#include <asm/barrier.h>
#include <asm/thread_info.h>
#endif
/*
...
...
@@ -34,15 +35,14 @@
*/
#ifndef CONFIG_IO_36
#define DOMAIN_KERNEL 0
#define DOMAIN_TABLE 0
#define DOMAIN_USER 1
#define DOMAIN_IO 2
#else
#define DOMAIN_KERNEL 2
#define DOMAIN_TABLE 2
#define DOMAIN_USER 1
#define DOMAIN_IO 0
#endif
#define DOMAIN_VECTORS 3
/*
* Domain types
...
...
@@ -55,30 +55,65 @@
#define DOMAIN_MANAGER 1
#endif
#define domain_val(dom,type) ((type) << (2*(dom)))
#define domain_mask(dom) ((3) << (2 * (dom)))
#define domain_val(dom,type) ((type) << (2 * (dom)))
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
#define DACR_INIT \
(domain_val(DOMAIN_USER, DOMAIN_NOACCESS) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT) | \
domain_val(DOMAIN_VECTORS, DOMAIN_CLIENT))
#else
#define DACR_INIT \
(domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT) | \
domain_val(DOMAIN_VECTORS, DOMAIN_CLIENT))
#endif
#define __DACR_DEFAULT \
domain_val(DOMAIN_KERNEL, DOMAIN_CLIENT) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT) | \
domain_val(DOMAIN_VECTORS, DOMAIN_CLIENT)
#define DACR_UACCESS_DISABLE \
(__DACR_DEFAULT | domain_val(DOMAIN_USER, DOMAIN_NOACCESS))
#define DACR_UACCESS_ENABLE \
(__DACR_DEFAULT | domain_val(DOMAIN_USER, DOMAIN_CLIENT))
#ifndef __ASSEMBLY__
#ifdef CONFIG_CPU_USE_DOMAINS
static
inline
unsigned
int
get_domain
(
void
)
{
unsigned
int
domain
;
asm
(
"mrc p15, 0, %0, c3, c0 @ get domain"
:
"=r"
(
domain
)
:
"m"
(
current_thread_info
()
->
cpu_domain
));
return
domain
;
}
static
inline
void
set_domain
(
unsigned
val
)
{
asm
volatile
(
"mcr p15, 0, %0, c3, c0 @ set domain"
:
:
"r"
(
val
));
:
:
"r"
(
val
)
:
"memory"
);
isb
();
}
#ifdef CONFIG_CPU_USE_DOMAINS
#define modify_domain(dom,type) \
do { \
struct thread_info *thread = current_thread_info(); \
unsigned int domain = thread->cpu_domain; \
domain &= ~domain_val(dom, DOMAIN_MANAGER); \
thread->cpu_domain = domain | domain_val(dom, type); \
set_domain(thread->cpu_domain); \
unsigned int domain = get_domain(); \
domain &= ~domain_mask(dom); \
domain = domain | domain_val(dom, type); \
set_domain(domain); \
} while (0)
#else
static
inline
void
set_domain
(
unsigned
val
)
{
}
static
inline
void
modify_domain
(
unsigned
dom
,
unsigned
type
)
{
}
#endif
...
...
arch/arm/include/asm/futex.h
浏览文件 @
c2172ce2
...
...
@@ -22,8 +22,11 @@
#ifdef CONFIG_SMP
#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
({ \
unsigned int __ua_flags; \
smp_mb(); \
prefetchw(uaddr); \
__ua_flags = uaccess_save_and_enable(); \
__asm__ __volatile__( \
"1: ldrex %1, [%3]\n" \
" " insn "\n" \
...
...
@@ -34,12 +37,15 @@
__futex_atomic_ex_table("%5") \
: "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \
: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
: "cc", "memory")
: "cc", "memory"); \
uaccess_restore(__ua_flags); \
})
static
inline
int
futex_atomic_cmpxchg_inatomic
(
u32
*
uval
,
u32
__user
*
uaddr
,
u32
oldval
,
u32
newval
)
{
unsigned
int
__ua_flags
;
int
ret
;
u32
val
;
...
...
@@ -49,6 +55,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
smp_mb
();
/* Prefetching cannot fault */
prefetchw
(
uaddr
);
__ua_flags
=
uaccess_save_and_enable
();
__asm__
__volatile__
(
"@futex_atomic_cmpxchg_inatomic
\n
"
"1: ldrex %1, [%4]
\n
"
" teq %1, %2
\n
"
...
...
@@ -61,6 +68,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
:
"=&r"
(
ret
),
"=&r"
(
val
)
:
"r"
(
oldval
),
"r"
(
newval
),
"r"
(
uaddr
),
"Ir"
(
-
EFAULT
)
:
"cc"
,
"memory"
);
uaccess_restore
(
__ua_flags
);
smp_mb
();
*
uval
=
val
;
...
...
@@ -73,6 +81,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
#include <asm/domain.h>
#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
({ \
unsigned int __ua_flags = uaccess_save_and_enable(); \
__asm__ __volatile__( \
"1: " TUSER(ldr) " %1, [%3]\n" \
" " insn "\n" \
...
...
@@ -81,12 +91,15 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
__futex_atomic_ex_table("%5") \
: "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \
: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
: "cc", "memory")
: "cc", "memory"); \
uaccess_restore(__ua_flags); \
})
static
inline
int
futex_atomic_cmpxchg_inatomic
(
u32
*
uval
,
u32
__user
*
uaddr
,
u32
oldval
,
u32
newval
)
{
unsigned
int
__ua_flags
;
int
ret
=
0
;
u32
val
;
...
...
@@ -94,6 +107,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
return
-
EFAULT
;
preempt_disable
();
__ua_flags
=
uaccess_save_and_enable
();
__asm__
__volatile__
(
"@futex_atomic_cmpxchg_inatomic
\n
"
"1: "
TUSER
(
ldr
)
" %1, [%4]
\n
"
" teq %1, %2
\n
"
...
...
@@ -103,6 +117,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
:
"+r"
(
ret
),
"=&r"
(
val
)
:
"r"
(
oldval
),
"r"
(
newval
),
"r"
(
uaddr
),
"Ir"
(
-
EFAULT
)
:
"cc"
,
"memory"
);
uaccess_restore
(
__ua_flags
);
*
uval
=
val
;
preempt_enable
();
...
...
arch/arm/include/asm/pgtable-2level-hwdef.h
浏览文件 @
c2172ce2
...
...
@@ -23,6 +23,7 @@
#define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2)
/* v7 */
#define PMD_BIT4 (_AT(pmdval_t, 1) << 4)
#define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5)
#define PMD_DOMAIN_MASK PMD_DOMAIN(0x0f)
#define PMD_PROTECTION (_AT(pmdval_t, 1) << 9)
/* v5 */
/*
* - section
...
...
arch/arm/include/asm/thread_info.h
浏览文件 @
c2172ce2
...
...
@@ -25,7 +25,6 @@
struct
task_struct
;
#include <asm/types.h>
#include <asm/domain.h>
typedef
unsigned
long
mm_segment_t
;
...
...
@@ -74,9 +73,6 @@ struct thread_info {
.flags = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
.cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT), \
}
#define init_thread_info (init_thread_union.thread_info)
...
...
arch/arm/include/asm/uaccess.h
浏览文件 @
c2172ce2
...
...
@@ -49,6 +49,35 @@ struct exception_table_entry
extern
int
fixup_exception
(
struct
pt_regs
*
regs
);
/*
* These two functions allow hooking accesses to userspace to increase
* system integrity by ensuring that the kernel can not inadvertantly
* perform such accesses (eg, via list poison values) which could then
* be exploited for priviledge escalation.
*/
static
inline
unsigned
int
uaccess_save_and_enable
(
void
)
{
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
unsigned
int
old_domain
=
get_domain
();
/* Set the current domain access to permit user accesses */
set_domain
((
old_domain
&
~
domain_mask
(
DOMAIN_USER
))
|
domain_val
(
DOMAIN_USER
,
DOMAIN_CLIENT
));
return
old_domain
;
#else
return
0
;
#endif
}
static
inline
void
uaccess_restore
(
unsigned
int
flags
)
{
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
/* Restore the user access mask */
set_domain
(
flags
);
#endif
}
/*
* These two are intentionally not defined anywhere - if the kernel
* code generates any references to them, that's a bug.
...
...
@@ -165,6 +194,7 @@ extern int __get_user_64t_4(void *);
register typeof(x) __r2 asm("r2"); \
register unsigned long __l asm("r1") = __limit; \
register int __e asm("r0"); \
unsigned int __ua_flags = uaccess_save_and_enable(); \
switch (sizeof(*(__p))) { \
case 1: \
if (sizeof((x)) >= 8) \
...
...
@@ -192,6 +222,7 @@ extern int __get_user_64t_4(void *);
break; \
default: __e = __get_user_bad(); break; \
} \
uaccess_restore(__ua_flags); \
x = (typeof(*(p))) __r2; \
__e; \
})
...
...
@@ -224,6 +255,7 @@ extern int __put_user_8(void *, unsigned long long);
register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
register unsigned long __l asm("r1") = __limit; \
register int __e asm("r0"); \
unsigned int __ua_flags = uaccess_save_and_enable(); \
switch (sizeof(*(__p))) { \
case 1: \
__put_user_x(__r2, __p, __e, __l, 1); \
...
...
@@ -239,6 +271,7 @@ extern int __put_user_8(void *, unsigned long long);
break; \
default: __e = __put_user_bad(); break; \
} \
uaccess_restore(__ua_flags); \
__e; \
})
...
...
@@ -300,14 +333,17 @@ static inline void set_fs(mm_segment_t fs)
do { \
unsigned long __gu_addr = (unsigned long)(ptr); \
unsigned long __gu_val; \
unsigned int __ua_flags; \
__chk_user_ptr(ptr); \
might_fault(); \
__ua_flags = uaccess_save_and_enable(); \
switch (sizeof(*(ptr))) { \
case 1: __get_user_asm_byte(__gu_val, __gu_addr, err); break; \
case 2: __get_user_asm_half(__gu_val, __gu_addr, err); break; \
case 4: __get_user_asm_word(__gu_val, __gu_addr, err); break; \
default: (__gu_val) = __get_user_bad(); \
} \
uaccess_restore(__ua_flags); \
(x) = (__typeof__(*(ptr)))__gu_val; \
} while (0)
...
...
@@ -381,9 +417,11 @@ do { \
#define __put_user_err(x, ptr, err) \
do { \
unsigned long __pu_addr = (unsigned long)(ptr); \
unsigned int __ua_flags; \
__typeof__(*(ptr)) __pu_val = (x); \
__chk_user_ptr(ptr); \
might_fault(); \
__ua_flags = uaccess_save_and_enable(); \
switch (sizeof(*(ptr))) { \
case 1: __put_user_asm_byte(__pu_val, __pu_addr, err); break; \
case 2: __put_user_asm_half(__pu_val, __pu_addr, err); break; \
...
...
@@ -391,6 +429,7 @@ do { \
case 8: __put_user_asm_dword(__pu_val, __pu_addr, err); break; \
default: __put_user_bad(); \
} \
uaccess_restore(__ua_flags); \
} while (0)
#define __put_user_asm_byte(x, __pu_addr, err) \
...
...
@@ -474,11 +513,46 @@ do { \
#ifdef CONFIG_MMU
extern
unsigned
long
__must_check
__copy_from_user
(
void
*
to
,
const
void
__user
*
from
,
unsigned
long
n
);
extern
unsigned
long
__must_check
__copy_to_user
(
void
__user
*
to
,
const
void
*
from
,
unsigned
long
n
);
extern
unsigned
long
__must_check
__copy_to_user_std
(
void
__user
*
to
,
const
void
*
from
,
unsigned
long
n
);
extern
unsigned
long
__must_check
__clear_user
(
void
__user
*
addr
,
unsigned
long
n
);
extern
unsigned
long
__must_check
__clear_user_std
(
void
__user
*
addr
,
unsigned
long
n
);
extern
unsigned
long
__must_check
arm_copy_from_user
(
void
*
to
,
const
void
__user
*
from
,
unsigned
long
n
);
static
inline
unsigned
long
__must_check
__copy_from_user
(
void
*
to
,
const
void
__user
*
from
,
unsigned
long
n
)
{
unsigned
int
__ua_flags
=
uaccess_save_and_enable
();
n
=
arm_copy_from_user
(
to
,
from
,
n
);
uaccess_restore
(
__ua_flags
);
return
n
;
}
extern
unsigned
long
__must_check
arm_copy_to_user
(
void
__user
*
to
,
const
void
*
from
,
unsigned
long
n
);
extern
unsigned
long
__must_check
__copy_to_user_std
(
void
__user
*
to
,
const
void
*
from
,
unsigned
long
n
);
static
inline
unsigned
long
__must_check
__copy_to_user
(
void
__user
*
to
,
const
void
*
from
,
unsigned
long
n
)
{
unsigned
int
__ua_flags
=
uaccess_save_and_enable
();
n
=
arm_copy_to_user
(
to
,
from
,
n
);
uaccess_restore
(
__ua_flags
);
return
n
;
}
extern
unsigned
long
__must_check
arm_clear_user
(
void
__user
*
addr
,
unsigned
long
n
);
extern
unsigned
long
__must_check
__clear_user_std
(
void
__user
*
addr
,
unsigned
long
n
);
static
inline
unsigned
long
__must_check
__clear_user
(
void
__user
*
addr
,
unsigned
long
n
)
{
unsigned
int
__ua_flags
=
uaccess_save_and_enable
();
n
=
arm_clear_user
(
addr
,
n
);
uaccess_restore
(
__ua_flags
);
return
n
;
}
#else
#define __copy_from_user(to, from, n) (memcpy(to, (void __force *)from, n), 0)
#define __copy_to_user(to, from, n) (memcpy((void __force *)to, from, n), 0)
...
...
@@ -511,6 +585,7 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo
return
n
;
}
/* These are from lib/ code, and use __get_user() and friends */
extern
long
strncpy_from_user
(
char
*
dest
,
const
char
__user
*
src
,
long
count
);
extern
__must_check
long
strlen_user
(
const
char
__user
*
str
);
...
...
arch/arm/kernel/armksyms.c
浏览文件 @
c2172ce2
...
...
@@ -97,9 +97,9 @@ EXPORT_SYMBOL(mmiocpy);
#ifdef CONFIG_MMU
EXPORT_SYMBOL
(
copy_page
);
EXPORT_SYMBOL
(
_
_copy_from_user
);
EXPORT_SYMBOL
(
_
_copy_to_user
);
EXPORT_SYMBOL
(
_
_clear_user
);
EXPORT_SYMBOL
(
arm
_copy_from_user
);
EXPORT_SYMBOL
(
arm
_copy_to_user
);
EXPORT_SYMBOL
(
arm
_clear_user
);
EXPORT_SYMBOL
(
__get_user_1
);
EXPORT_SYMBOL
(
__get_user_2
);
...
...
arch/arm/kernel/entry-armv.S
浏览文件 @
c2172ce2
...
...
@@ -149,10 +149,10 @@ ENDPROC(__und_invalid)
#define SPFIX(code...)
#endif
.
macro
svc_entry
,
stack_hole
=
0
,
trace
=
1
.
macro
svc_entry
,
stack_hole
=
0
,
trace
=
1
,
uaccess
=
1
UNWIND
(.
fnstart
)
UNWIND
(.
save
{
r0
-
pc
}
)
sub
sp
,
sp
,
#(
S_FRAME_SIZE
+
\
stack_hole
-
4
)
sub
sp
,
sp
,
#(
S_FRAME_SIZE
+
8
+
\
stack_hole
-
4
)
#ifdef CONFIG_THUMB2_KERNEL
SPFIX
(
str
r0
,
[
sp
]
)
@
temporarily
saved
SPFIX
(
mov
r0
,
sp
)
...
...
@@ -167,7 +167,7 @@ ENDPROC(__und_invalid)
ldmia
r0
,
{
r3
-
r5
}
add
r7
,
sp
,
#
S_SP
-
4
@
here
for
interlock
avoidance
mov
r6
,
#-
1
@
""
""
""
""
add
r2
,
sp
,
#(
S_FRAME_SIZE
+
\
stack_hole
-
4
)
add
r2
,
sp
,
#(
S_FRAME_SIZE
+
8
+
\
stack_hole
-
4
)
SPFIX
(
addeq
r2
,
r2
,
#
4
)
str
r3
,
[
sp
,
#-
4
]!
@
save
the
"real"
r0
copied
@
from
the
exception
stack
...
...
@@ -185,6 +185,11 @@ ENDPROC(__und_invalid)
@
stmia
r7
,
{
r2
-
r6
}
uaccess_save
r0
.
if
\
uaccess
uaccess_disable
r0
.
endif
.
if
\
trace
#ifdef CONFIG_TRACE_IRQFLAGS
bl
trace_hardirqs_off
...
...
@@ -194,7 +199,7 @@ ENDPROC(__und_invalid)
.
align
5
__dabt_svc
:
svc_entry
svc_entry
uaccess
=
0
mov
r2
,
sp
dabt_helper
THUMB
(
ldr
r5
,
[
sp
,
#
S_PSR
]
)
@
potentially
updated
CPSR
...
...
@@ -368,7 +373,7 @@ ENDPROC(__fiq_abt)
#error "sizeof(struct pt_regs) must be a multiple of 8"
#endif
.
macro
usr_entry
,
trace
=
1
.
macro
usr_entry
,
trace
=
1
,
uaccess
=
1
UNWIND
(.
fnstart
)
UNWIND
(.
cantunwind
)
@
don
't unwind the user space
sub
sp
,
sp
,
#
S_FRAME_SIZE
...
...
@@ -400,6 +405,10 @@ ENDPROC(__fiq_abt)
ARM
(
stmdb
r0
,
{
sp
,
lr
}^
)
THUMB
(
store_user_sp_lr
r0
,
r1
,
S_SP
-
S_PC
)
.
if
\
uaccess
uaccess_disable
ip
.
endif
@
Enable
the
alignment
trap
while
in
kernel
mode
ATRAP
(
teq
r8
,
r7
)
ATRAP
(
mcrne
p15
,
0
,
r8
,
c1
,
c0
,
0
)
...
...
@@ -435,7 +444,7 @@ ENDPROC(__fiq_abt)
.
align
5
__dabt_usr
:
usr_entry
usr_entry
uaccess
=
0
kuser_cmpxchg_check
mov
r2
,
sp
dabt_helper
...
...
@@ -458,7 +467,7 @@ ENDPROC(__irq_usr)
.
align
5
__und_usr
:
usr_entry
usr_entry
uaccess
=
0
mov
r2
,
r4
mov
r3
,
r5
...
...
@@ -484,6 +493,8 @@ __und_usr:
1
:
ldrt
r0
,
[
r4
]
ARM_BE8
(
rev
r0
,
r0
)
@
little
endian
instruction
uaccess_disable
ip
@
r0
=
32
-
bit
ARM
instruction
which
caused
the
exception
@
r2
=
PC
value
for
the
following
instruction
(
:
=
regs
->
ARM_pc
)
@
r4
=
PC
value
for
the
faulting
instruction
...
...
@@ -518,9 +529,10 @@ __und_usr_thumb:
2
:
ldrht
r5
,
[
r4
]
ARM_BE8
(
rev16
r5
,
r5
)
@
little
endian
instruction
cmp
r5
,
#
0xe800
@
32
bit
instruction
if
xx
!=
0
blo
__und_usr_fault_16
@
16
bit
undefined
instruction
blo
__und_usr_fault_16
_pan
@
16
bit
undefined
instruction
3
:
ldrht
r0
,
[
r2
]
ARM_BE8
(
rev16
r0
,
r0
)
@
little
endian
instruction
uaccess_disable
ip
add
r2
,
r2
,
#
2
@
r2
is
PC
+
2
,
make
it
PC
+
4
str
r2
,
[
sp
,
#
S_PC
]
@
it
's a 2x16bit instr, update
orr
r0
,
r0
,
r5
,
lsl
#
16
...
...
@@ -715,6 +727,8 @@ ENDPROC(no_fp)
__und_usr_fault_32
:
mov
r1
,
#
4
b
1
f
__und_usr_fault_16_pan
:
uaccess_disable
ip
__und_usr_fault_16
:
mov
r1
,
#
2
1
:
mov
r0
,
sp
...
...
@@ -770,6 +784,8 @@ ENTRY(__switch_to)
ldr
r4
,
[
r2
,
#
TI_TP_VALUE
]
ldr
r5
,
[
r2
,
#
TI_TP_VALUE
+
4
]
#ifdef CONFIG_CPU_USE_DOMAINS
mrc
p15
,
0
,
r6
,
c3
,
c0
,
0
@
Get
domain
register
str
r6
,
[
r1
,
#
TI_CPU_DOMAIN
]
@
Save
old
domain
register
ldr
r6
,
[
r2
,
#
TI_CPU_DOMAIN
]
#endif
switch_tls
r1
,
r4
,
r5
,
r3
,
r7
...
...
arch/arm/kernel/entry-common.S
浏览文件 @
c2172ce2
...
...
@@ -174,6 +174,8 @@ ENTRY(vector_swi)
USER
(
ldr
scno
,
[
lr
,
#-
4
]
)
@
get
SWI
instruction
#endif
uaccess_disable
tbl
adr
tbl
,
sys_call_table
@
load
syscall
table
pointer
#if defined(CONFIG_OABI_COMPAT)
...
...
arch/arm/kernel/entry-header.S
浏览文件 @
c2172ce2
...
...
@@ -196,7 +196,7 @@
msr
cpsr_c
,
\
rtemp
@
switch
back
to
the
SVC
mode
.
endm
#ifndef CONFIG_THUMB2_KERNEL
.
macro
svc_exit
,
rpsr
,
irq
=
0
.
if
\
irq
!=
0
@
IRQs
already
off
...
...
@@ -215,6 +215,10 @@
blne
trace_hardirqs_off
#endif
.
endif
uaccess_restore
#ifndef CONFIG_THUMB2_KERNEL
@
ARM
mode
SVC
restore
msr
spsr_cxsf
,
\
rpsr
#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
@
We
must
avoid
clrex
due
to
Cortex
-
A15
erratum
#
830321
...
...
@@ -222,6 +226,20 @@
strex
r1
,
r2
,
[
r0
]
@
clear
the
exclusive
monitor
#endif
ldmia
sp
,
{
r0
-
pc
}^
@
load
r0
-
pc
,
cpsr
#else
@
Thumb
mode
SVC
restore
ldr
lr
,
[
sp
,
#
S_SP
]
@
top
of
the
stack
ldrd
r0
,
r1
,
[
sp
,
#
S_LR
]
@
calling
lr
and
pc
@
We
must
avoid
clrex
due
to
Cortex
-
A15
erratum
#
830321
strex
r2
,
r1
,
[
sp
,
#
S_LR
]
@
clear
the
exclusive
monitor
stmdb
lr
!,
{
r0
,
r1
,
\
rpsr
}
@
calling
lr
and
rfe
context
ldmia
sp
,
{
r0
-
r12
}
mov
sp
,
lr
ldr
lr
,
[
sp
],
#
4
rfeia
sp
!
#endif
.
endm
@
...
...
@@ -241,6 +259,9 @@
@
on
the
stack
remains
correct
)
.
@
.
macro
svc_exit_via_fiq
uaccess_restore
#ifndef CONFIG_THUMB2_KERNEL
@
ARM
mode
restore
mov
r0
,
sp
ldmib
r0
,
{
r1
-
r14
}
@
abort
is
deadly
from
here
onward
(
it
will
@
clobber
state
restored
below
)
...
...
@@ -250,9 +271,27 @@
msr
spsr_cxsf
,
r9
ldr
r0
,
[
r0
,
#
S_R0
]
ldmia
r8
,
{
pc
}^
#else
@
Thumb
mode
restore
add
r0
,
sp
,
#
S_R2
ldr
lr
,
[
sp
,
#
S_LR
]
ldr
sp
,
[
sp
,
#
S_SP
]
@
abort
is
deadly
from
here
onward
(
it
will
@
clobber
state
restored
below
)
ldmia
r0
,
{
r2
-
r12
}
mov
r1
,
#
FIQ_MODE
| PSR_I_BIT |
PSR_F_BIT
msr
cpsr_c
,
r1
sub
r0
,
#
S_R2
add
r8
,
r0
,
#
S_PC
ldmia
r0
,
{
r0
-
r1
}
rfeia
r8
#endif
.
endm
.
macro
restore_user_regs
,
fast
=
0
,
offset
=
0
uaccess_enable
r1
,
isb
=
0
#ifndef CONFIG_THUMB2_KERNEL
@
ARM
mode
restore
mov
r2
,
sp
ldr
r1
,
[
r2
,
#
\
offset
+
S_PSR
]
@
get
calling
cpsr
ldr
lr
,
[
r2
,
#
\
offset
+
S_PC
]!
@
get
pc
...
...
@@ -270,72 +309,16 @@
@
after
ldm
{}^
add
sp
,
sp
,
#
\
offset
+
S_FRAME_SIZE
movs
pc
,
lr
@
return
&
move
spsr_svc
into
cpsr
.
endm
#else /* CONFIG_THUMB2_KERNEL */
.
macro
svc_exit
,
rpsr
,
irq
=
0
.
if
\
irq
!=
0
@
IRQs
already
off
#ifdef CONFIG_TRACE_IRQFLAGS
@
The
parent
context
IRQs
must
have
been
enabled
to
get
here
in
@
the
first
place
,
so
there
's no point checking the PSR I bit.
bl
trace_hardirqs_on
#endif
.
else
@
IRQs
off
again
before
pulling
preserved
data
off
the
stack
disable_irq_notrace
#ifdef CONFIG_TRACE_IRQFLAGS
tst
\
rpsr
,
#
PSR_I_BIT
bleq
trace_hardirqs_on
tst
\
rpsr
,
#
PSR_I_BIT
blne
trace_hardirqs_off
#endif
.
endif
ldr
lr
,
[
sp
,
#
S_SP
]
@
top
of
the
stack
ldrd
r0
,
r1
,
[
sp
,
#
S_LR
]
@
calling
lr
and
pc
@
We
must
avoid
clrex
due
to
Cortex
-
A15
erratum
#
830321
strex
r2
,
r1
,
[
sp
,
#
S_LR
]
@
clear
the
exclusive
monitor
stmdb
lr
!,
{
r0
,
r1
,
\
rpsr
}
@
calling
lr
and
rfe
context
ldmia
sp
,
{
r0
-
r12
}
mov
sp
,
lr
ldr
lr
,
[
sp
],
#
4
rfeia
sp
!
.
endm
@
@
svc_exit_via_fiq
-
like
svc_exit
but
switches
to
FIQ
mode
before
exit
@
@
For
full
details
see
non
-
Thumb
implementation
above
.
@
.
macro
svc_exit_via_fiq
add
r0
,
sp
,
#
S_R2
ldr
lr
,
[
sp
,
#
S_LR
]
ldr
sp
,
[
sp
,
#
S_SP
]
@
abort
is
deadly
from
here
onward
(
it
will
@
clobber
state
restored
below
)
ldmia
r0
,
{
r2
-
r12
}
mov
r1
,
#
FIQ_MODE
| PSR_I_BIT |
PSR_F_BIT
msr
cpsr_c
,
r1
sub
r0
,
#
S_R2
add
r8
,
r0
,
#
S_PC
ldmia
r0
,
{
r0
-
r1
}
rfeia
r8
.
endm
#ifdef CONFIG_CPU_V7M
/
*
*
Note
we
don
't need to do clrex here as clearing the local monitor is
*
part
of
each
exception
entry
and
exit
sequence
.
*/
.
macro
restore_user_regs
,
fast
=
0
,
offset
=
0
#elif defined(CONFIG_CPU_V7M)
@
V7M
restore
.
@
Note
that
we
don
't need to do clrex here as clearing the local
@
monitor
is
part
of
the
exception
entry
and
exit
sequence
.
.
if
\
offset
add
sp
,
#
\
offset
.
endif
v7m_exception_slow_exit
ret_r0
=
\
fast
.
endm
#else /* ifdef CONFIG_CPU_V7M */
.
macro
restore_user_regs
,
fast
=
0
,
offset
=
0
#else
@
Thumb
mode
restore
mov
r2
,
sp
load_user_sp_lr
r2
,
r3
,
\
offset
+
S_SP
@
calling
sp
,
lr
ldr
r1
,
[
sp
,
#
\
offset
+
S_PSR
]
@
get
calling
cpsr
...
...
@@ -353,9 +336,8 @@
.
endif
add
sp
,
sp
,
#
S_FRAME_SIZE
-
S_SP
movs
pc
,
lr
@
return
&
move
spsr_svc
into
cpsr
.
endm
#endif /* ifdef CONFIG_CPU_V7M / else */
#endif /* !CONFIG_THUMB2_KERNEL */
.
endm
/*
*
Context
tracking
subsystem
.
Used
to
instrument
transitions
...
...
arch/arm/kernel/head.S
浏览文件 @
c2172ce2
...
...
@@ -464,10 +464,7 @@ __enable_mmu:
#ifdef CONFIG_ARM_LPAE
mcrr
p15
,
0
,
r4
,
r5
,
c2
@
load
TTBR0
#else
mov
r5
,
#(
domain_val
(
DOMAIN_USER
,
DOMAIN_MANAGER
)
|
\
domain_val
(
DOMAIN_KERNEL
,
DOMAIN_MANAGER
)
|
\
domain_val
(
DOMAIN_TABLE
,
DOMAIN_MANAGER
)
|
\
domain_val
(
DOMAIN_IO
,
DOMAIN_CLIENT
))
mov
r5
,
#
DACR_INIT
mcr
p15
,
0
,
r5
,
c3
,
c0
,
0
@
load
domain
access
register
mcr
p15
,
0
,
r4
,
c2
,
c0
,
0
@
load
page
table
pointer
#endif
...
...
arch/arm/kernel/process.c
浏览文件 @
c2172ce2
...
...
@@ -129,12 +129,36 @@ void __show_regs(struct pt_regs *regs)
buf
[
4
]
=
'\0'
;
#ifndef CONFIG_CPU_V7M
printk
(
"Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s
\n
"
,
buf
,
interrupts_enabled
(
regs
)
?
"n"
:
"ff"
,
fast_interrupts_enabled
(
regs
)
?
"n"
:
"ff"
,
processor_modes
[
processor_mode
(
regs
)],
isa_modes
[
isa_mode
(
regs
)],
get_fs
()
==
get_ds
()
?
"kernel"
:
"user"
);
{
unsigned
int
domain
=
get_domain
();
const
char
*
segment
;
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
/*
* Get the domain register for the parent context. In user
* mode, we don't save the DACR, so lets use what it should
* be. For other modes, we place it after the pt_regs struct.
*/
if
(
user_mode
(
regs
))
domain
=
DACR_UACCESS_ENABLE
;
else
domain
=
*
(
unsigned
int
*
)(
regs
+
1
);
#endif
if
((
domain
&
domain_mask
(
DOMAIN_USER
))
==
domain_val
(
DOMAIN_USER
,
DOMAIN_NOACCESS
))
segment
=
"none"
;
else
if
(
get_fs
()
==
get_ds
())
segment
=
"kernel"
;
else
segment
=
"user"
;
printk
(
"Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s
\n
"
,
buf
,
interrupts_enabled
(
regs
)
?
"n"
:
"ff"
,
fast_interrupts_enabled
(
regs
)
?
"n"
:
"ff"
,
processor_modes
[
processor_mode
(
regs
)],
isa_modes
[
isa_mode
(
regs
)],
segment
);
}
#else
printk
(
"xPSR: %08lx
\n
"
,
regs
->
ARM_cpsr
);
#endif
...
...
@@ -146,10 +170,9 @@ void __show_regs(struct pt_regs *regs)
buf
[
0
]
=
'\0'
;
#ifdef CONFIG_CPU_CP15_MMU
{
unsigned
int
transbase
,
dac
;
unsigned
int
transbase
,
dac
=
get_domain
()
;
asm
(
"mrc p15, 0, %0, c2, c0
\n\t
"
"mrc p15, 0, %1, c3, c0
\n
"
:
"=r"
(
transbase
),
"=r"
(
dac
));
:
"=r"
(
transbase
));
snprintf
(
buf
,
sizeof
(
buf
),
" Table: %08x DAC: %08x"
,
transbase
,
dac
);
}
...
...
@@ -210,6 +233,16 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
memset
(
&
thread
->
cpu_context
,
0
,
sizeof
(
struct
cpu_context_save
));
#ifdef CONFIG_CPU_USE_DOMAINS
/*
* Copy the initial value of the domain access control register
* from the current thread: thread->addr_limit will have been
* copied from the current thread via setup_thread_stack() in
* kernel/fork.c
*/
thread
->
cpu_domain
=
get_domain
();
#endif
if
(
likely
(
!
(
p
->
flags
&
PF_KTHREAD
)))
{
*
childregs
=
*
current_pt_regs
();
childregs
->
ARM_r0
=
0
;
...
...
arch/arm/kernel/swp_emulate.c
浏览文件 @
c2172ce2
...
...
@@ -141,11 +141,14 @@ static int emulate_swpX(unsigned int address, unsigned int *data,
while
(
1
)
{
unsigned
long
temp
;
unsigned
int
__ua_flags
;
__ua_flags
=
uaccess_save_and_enable
();
if
(
type
==
TYPE_SWPB
)
__user_swpb_asm
(
*
data
,
address
,
res
,
temp
);
else
__user_swp_asm
(
*
data
,
address
,
res
,
temp
);
uaccess_restore
(
__ua_flags
);
if
(
likely
(
res
!=
-
EAGAIN
)
||
signal_pending
(
current
))
break
;
...
...
arch/arm/kernel/traps.c
浏览文件 @
c2172ce2
...
...
@@ -870,7 +870,6 @@ void __init early_trap_init(void *vectors_base)
kuser_init
(
vectors_base
);
flush_icache_range
(
vectors
,
vectors
+
PAGE_SIZE
*
2
);
modify_domain
(
DOMAIN_USER
,
DOMAIN_CLIENT
);
#else
/* ifndef CONFIG_CPU_V7M */
/*
* on V7-M there is no need to copy the vector table to a dedicated
...
...
arch/arm/lib/clear_user.S
浏览文件 @
c2172ce2
...
...
@@ -12,14 +12,14 @@
.
text
/*
Prototype
:
int
_
_clear_user
(
void
*
addr
,
size_t
sz
)
/*
Prototype
:
unsigned
long
arm
_clear_user
(
void
*
addr
,
size_t
sz
)
*
Purpose
:
clear
some
user
memory
*
Params
:
addr
-
user
memory
address
to
clear
*
:
sz
-
number
of
bytes
to
clear
*
Returns
:
number
of
bytes
NOT
cleared
*/
ENTRY
(
__clear_user_std
)
WEAK
(
_
_clear_user
)
WEAK
(
arm
_clear_user
)
stmfd
sp
!,
{
r1
,
lr
}
mov
r2
,
#
0
cmp
r1
,
#
4
...
...
@@ -44,7 +44,7 @@ WEAK(__clear_user)
USER
(
strnebt
r2
,
[
r0
])
mov
r0
,
#
0
ldmfd
sp
!,
{
r1
,
pc
}
ENDPROC
(
_
_clear_user
)
ENDPROC
(
arm
_clear_user
)
ENDPROC
(
__clear_user_std
)
.
pushsection
.
text
.
fixup
,
"ax"
...
...
arch/arm/lib/copy_from_user.S
浏览文件 @
c2172ce2
...
...
@@ -17,7 +17,7 @@
/*
*
Prototype
:
*
*
size_t
_
_copy_from_user
(
void
*
to
,
const
void
*
from
,
size_t
n
)
*
size_t
arm
_copy_from_user
(
void
*
to
,
const
void
*
from
,
size_t
n
)
*
*
Purpose
:
*
...
...
@@ -89,11 +89,11 @@
.
text
ENTRY
(
_
_copy_from_user
)
ENTRY
(
arm
_copy_from_user
)
#include "copy_template.S"
ENDPROC
(
_
_copy_from_user
)
ENDPROC
(
arm
_copy_from_user
)
.
pushsection
.
fixup
,
"ax"
.
align
0
...
...
arch/arm/lib/copy_to_user.S
浏览文件 @
c2172ce2
...
...
@@ -17,7 +17,7 @@
/*
*
Prototype
:
*
*
size_t
_
_copy_to_user
(
void
*
to
,
const
void
*
from
,
size_t
n
)
*
size_t
arm
_copy_to_user
(
void
*
to
,
const
void
*
from
,
size_t
n
)
*
*
Purpose
:
*
...
...
@@ -93,11 +93,11 @@
.
text
ENTRY
(
__copy_to_user_std
)
WEAK
(
_
_copy_to_user
)
WEAK
(
arm
_copy_to_user
)
#include "copy_template.S"
ENDPROC
(
_
_copy_to_user
)
ENDPROC
(
arm
_copy_to_user
)
ENDPROC
(
__copy_to_user_std
)
.
pushsection
.
text
.
fixup
,
"ax"
...
...
arch/arm/lib/csumpartialcopyuser.S
浏览文件 @
c2172ce2
...
...
@@ -17,6 +17,19 @@
.
text
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
.
macro
save_regs
mrc
p15
,
0
,
ip
,
c3
,
c0
,
0
stmfd
sp
!,
{
r1
,
r2
,
r4
-
r8
,
ip
,
lr
}
uaccess_enable
ip
.
endm
.
macro
load_regs
ldmfd
sp
!,
{
r1
,
r2
,
r4
-
r8
,
ip
,
lr
}
mcr
p15
,
0
,
ip
,
c3
,
c0
,
0
ret
lr
.
endm
#else
.
macro
save_regs
stmfd
sp
!,
{
r1
,
r2
,
r4
-
r8
,
lr
}
.
endm
...
...
@@ -24,6 +37,7 @@
.
macro
load_regs
ldmfd
sp
!,
{
r1
,
r2
,
r4
-
r8
,
pc
}
.
endm
#endif
.
macro
load1b
,
reg1
ldrusr
\
reg1
,
r0
,
1
...
...
arch/arm/lib/uaccess_with_memcpy.c
浏览文件 @
c2172ce2
...
...
@@ -136,7 +136,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
}
unsigned
long
_
_copy_to_user
(
void
__user
*
to
,
const
void
*
from
,
unsigned
long
n
)
arm
_copy_to_user
(
void
__user
*
to
,
const
void
*
from
,
unsigned
long
n
)
{
/*
* This test is stubbed out of the main function above to keep
...
...
@@ -190,7 +190,7 @@ __clear_user_memset(void __user *addr, unsigned long n)
return
n
;
}
unsigned
long
_
_clear_user
(
void
__user
*
addr
,
unsigned
long
n
)
unsigned
long
arm
_clear_user
(
void
__user
*
addr
,
unsigned
long
n
)
{
/* See rational for this in __copy_to_user() above. */
if
(
n
<
64
)
...
...
arch/arm/mm/abort-ev4.S
浏览文件 @
c2172ce2
...
...
@@ -19,6 +19,7 @@ ENTRY(v4_early_abort)
mrc
p15
,
0
,
r1
,
c5
,
c0
,
0
@
get
FSR
mrc
p15
,
0
,
r0
,
c6
,
c0
,
0
@
get
FAR
ldr
r3
,
[
r4
]
@
read
aborted
ARM
instruction
uaccess_disable
ip
@
disable
userspace
access
bic
r1
,
r1
,
#
1
<<
11
|
1
<<
10
@
clear
bits
11
and
10
of
FSR
tst
r3
,
#
1
<<
20
@
L
=
1
->
write
?
orreq
r1
,
r1
,
#
1
<<
11
@
yes
.
...
...
arch/arm/mm/abort-ev5t.S
浏览文件 @
c2172ce2
...
...
@@ -21,8 +21,10 @@ ENTRY(v5t_early_abort)
mrc
p15
,
0
,
r0
,
c6
,
c0
,
0
@
get
FAR
do_thumb_abort
fsr
=
r1
,
pc
=
r4
,
psr
=
r5
,
tmp
=
r3
ldreq
r3
,
[
r4
]
@
read
aborted
ARM
instruction
uaccess_disable
ip
@
disable
user
access
bic
r1
,
r1
,
#
1
<<
11
@
clear
bits
11
of
FSR
do_ldrd_abort
tmp
=
ip
,
insn
=
r3
teq_ldrd
tmp
=
ip
,
insn
=
r3
@
insn
was
LDRD
?
beq
do_DataAbort
@
yes
tst
r3
,
#
1
<<
20
@
check
write
orreq
r1
,
r1
,
#
1
<<
11
b
do_DataAbort
arch/arm/mm/abort-ev5tj.S
浏览文件 @
c2172ce2
...
...
@@ -24,7 +24,9 @@ ENTRY(v5tj_early_abort)
bne
do_DataAbort
do_thumb_abort
fsr
=
r1
,
pc
=
r4
,
psr
=
r5
,
tmp
=
r3
ldreq
r3
,
[
r4
]
@
read
aborted
ARM
instruction
do_ldrd_abort
tmp
=
ip
,
insn
=
r3
uaccess_disable
ip
@
disable
userspace
access
teq_ldrd
tmp
=
ip
,
insn
=
r3
@
insn
was
LDRD
?
beq
do_DataAbort
@
yes
tst
r3
,
#
1
<<
20
@
L
=
0
->
write
orreq
r1
,
r1
,
#
1
<<
11
@
yes
.
b
do_DataAbort
arch/arm/mm/abort-ev6.S
浏览文件 @
c2172ce2
...
...
@@ -26,16 +26,18 @@ ENTRY(v6_early_abort)
ldr
ip
,
=
0x4107b36
mrc
p15
,
0
,
r3
,
c0
,
c0
,
0
@
get
processor
id
teq
ip
,
r3
,
lsr
#
4
@
r0
ARM1136
?
bne
do_DataAbort
bne
1
f
tst
r5
,
#
PSR_J_BIT
@
Java
?
tsteq
r5
,
#
PSR_T_BIT
@
Thumb
?
bne
do_DataAbort
bne
1
f
bic
r1
,
r1
,
#
1
<<
11
@
clear
bit
11
of
FSR
ldr
r3
,
[
r4
]
@
read
aborted
ARM
instruction
ARM_BE8
(
rev
r3
,
r3
)
do_ldrd_abort
tmp
=
ip
,
insn
=
r3
teq_ldrd
tmp
=
ip
,
insn
=
r3
@
insn
was
LDRD
?
beq
1
f
@
yes
tst
r3
,
#
1
<<
20
@
L
=
0
->
write
orreq
r1
,
r1
,
#
1
<<
11
@
yes
.
#endif
1
:
uaccess_disable
ip
@
disable
userspace
access
b
do_DataAbort
arch/arm/mm/abort-ev7.S
浏览文件 @
c2172ce2
...
...
@@ -15,6 +15,7 @@
ENTRY
(
v7_early_abort
)
mrc
p15
,
0
,
r1
,
c5
,
c0
,
0
@
get
FSR
mrc
p15
,
0
,
r0
,
c6
,
c0
,
0
@
get
FAR
uaccess_disable
ip
@
disable
userspace
access
/
*
*
V6
code
adjusts
the
returned
DFSR
.
...
...
arch/arm/mm/abort-lv4t.S
浏览文件 @
c2172ce2
...
...
@@ -26,6 +26,7 @@ ENTRY(v4t_late_abort)
#endif
bne
.
data_thumb_abort
ldr
r8
,
[
r4
]
@
read
arm
instruction
uaccess_disable
ip
@
disable
userspace
access
tst
r8
,
#
1
<<
20
@
L
=
1
->
write
?
orreq
r1
,
r1
,
#
1
<<
11
@
yes
.
and
r7
,
r8
,
#
15
<<
24
...
...
@@ -155,6 +156,7 @@ ENTRY(v4t_late_abort)
.
data_thumb_abort
:
ldrh
r8
,
[
r4
]
@
read
instruction
uaccess_disable
ip
@
disable
userspace
access
tst
r8
,
#
1
<<
11
@
L
=
1
->
write
?
orreq
r1
,
r1
,
#
1
<<
8
@
yes
and
r7
,
r8
,
#
15
<<
12
...
...
arch/arm/mm/abort-macro.S
浏览文件 @
c2172ce2
...
...
@@ -13,6 +13,7 @@
tst
\
psr
,
#
PSR_T_BIT
beq
not_thumb
ldrh
\
tmp
,
[
\
pc
]
@
Read
aborted
Thumb
instruction
uaccess_disable
ip
@
disable
userspace
access
and
\
tmp
,
\
tmp
,
#
0xfe00
@
Mask
opcode
field
cmp
\
tmp
,
#
0x5600
@
Is
it
ldrsb
?
orreq
\
tmp
,
\
tmp
,
#
1
<<
11
@
Set
L
-
bit
if
yes
...
...
@@ -29,12 +30,9 @@ not_thumb:
*
[
7
:
4
]
==
1101
*
[
20
]
==
0
*/
.
macro
do_ldrd_abort
,
tmp
,
insn
tst
\
insn
,
#
0x0e100000
@
[
27
:
25
,
20
]
==
0
bne
not_ldrd
and
\
tmp
,
\
insn
,
#
0x000000f0
@
[
7
:
4
]
==
1101
cmp
\
tmp
,
#
0x000000d0
beq
do_DataAbort
not_ldrd
:
.
macro
teq_ldrd
,
tmp
,
insn
mov
\
tmp
,
#
0x0e100000
orr
\
tmp
,
#
0x000000f0
and
\
tmp
,
\
insn
,
\
tmp
teq
\
tmp
,
#
0x000000d0
.
endm
arch/arm/mm/mmu.c
浏览文件 @
c2172ce2
...
...
@@ -291,13 +291,13 @@ static struct mem_type mem_types[] = {
.
prot_pte
=
L_PTE_PRESENT
|
L_PTE_YOUNG
|
L_PTE_DIRTY
|
L_PTE_RDONLY
,
.
prot_l1
=
PMD_TYPE_TABLE
,
.
domain
=
DOMAIN_
USER
,
.
domain
=
DOMAIN_
VECTORS
,
},
[
MT_HIGH_VECTORS
]
=
{
.
prot_pte
=
L_PTE_PRESENT
|
L_PTE_YOUNG
|
L_PTE_DIRTY
|
L_PTE_USER
|
L_PTE_RDONLY
,
.
prot_l1
=
PMD_TYPE_TABLE
,
.
domain
=
DOMAIN_
USER
,
.
domain
=
DOMAIN_
VECTORS
,
},
[
MT_MEMORY_RWX
]
=
{
.
prot_pte
=
L_PTE_PRESENT
|
L_PTE_YOUNG
|
L_PTE_DIRTY
,
...
...
arch/arm/mm/pgd.c
浏览文件 @
c2172ce2
...
...
@@ -84,6 +84,16 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
if
(
!
new_pte
)
goto
no_pte
;
#ifndef CONFIG_ARM_LPAE
/*
* Modify the PTE pointer to have the correct domain. This
* needs to be the vectors domain to avoid the low vectors
* being unmapped.
*/
pmd_val
(
*
new_pmd
)
&=
~
PMD_DOMAIN_MASK
;
pmd_val
(
*
new_pmd
)
|=
PMD_DOMAIN
(
DOMAIN_VECTORS
);
#endif
init_pud
=
pud_offset
(
init_pgd
,
0
);
init_pmd
=
pmd_offset
(
init_pud
,
0
);
init_pte
=
pte_offset_map
(
init_pmd
,
0
);
...
...
arch/arm/nwfpe/entry.S
浏览文件 @
c2172ce2
...
...
@@ -95,9 +95,10 @@ emulate:
reteq
r4
@
no
,
return
failure
next
:
uaccess_enable
r3
.
Lx1
:
ldrt
r6
,
[
r5
],
#
4
@
get
the
next
instruction
and
@
increment
PC
uaccess_disable
r3
and
r2
,
r6
,
#
0x0F000000
@
test
for
FP
insns
teq
r2
,
#
0x0C000000
teqne
r2
,
#
0x0D000000
...
...
arch/arm/xen/hypercall.S
浏览文件 @
c2172ce2
...
...
@@ -98,8 +98,23 @@ ENTRY(privcmd_call)
mov
r1
,
r2
mov
r2
,
r3
ldr
r3
,
[
sp
,
#
8
]
/
*
*
Privcmd
calls
are
issued
by
the
userspace
.
We
need
to
allow
the
*
kernel
to
access
the
userspace
memory
before
issuing
the
hypercall
.
*/
uaccess_enable
r4
/
*
r4
is
loaded
now
as
we
use
it
as
scratch
register
before
*/
ldr
r4
,
[
sp
,
#
4
]
__HVC
(
XEN_IMM
)
/
*
*
Disable
userspace
access
from
kernel
.
This
is
fine
to
do
it
*
unconditionally
as
no
set_fs
(
KERNEL_DS
)/
set_fs
(
get_ds
())
is
*
called
before
.
*/
uaccess_disable
r4
ldm
sp
!,
{
r4
}
ret
lr
ENDPROC
(
privcmd_call
)
;
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录