2005-04-26 15:21:02 +01:00
# include < l i n u x / i n i t . h >
2005-04-16 15:20:36 -07:00
# include < l i n u x / l i n k a g e . h >
# include < a s m / a s s e m b l e r . h >
2005-09-09 21:08:59 +02:00
# include < a s m / a s m - o f f s e t s . h >
2005-04-16 15:20:36 -07:00
# include < a s m / e r r n o . h >
2005-04-26 15:21:02 +01:00
# include < a s m / t h r e a d _ i n f o . h >
2005-04-16 15:20:36 -07:00
@ Bad Abort numbers
@ -----------------
@
# define B A D _ P R E F E T C H 0
# define B A D _ D A T A 1
# define B A D _ A D D R E X C P T N 2
# define B A D _ I R Q 3
# define B A D _ U N D E F I N S T R 4
@
2005-04-26 15:18:59 +01:00
@ Most of the stack format comes from struct pt_regs, but with
@ the addition of 8 bytes for storing syscall args 5 and 6.
2006-01-14 16:18:08 +00:00
@ This _must_ remain a multiple of 8 for EABI.
2005-04-16 15:20:36 -07:00
@
# define S _ O F F 8
2005-04-26 15:18:59 +01:00
/ *
* The S W I c o d e r e l i e s o n t h e f a c t t h a t R 0 i s a t t h e b o t t o m o f t h e s t a c k
* ( due t o s l o w / f a s t r e s t o r e u s e r r e g s ) .
* /
# if S _ R 0 ! = 0
# error " P l e a s e f i x "
# endif
2005-04-26 15:21:02 +01:00
.macro zero_fp
# ifdef C O N F I G _ F R A M E _ P O I N T E R
mov f p , #0
# endif
.endm
2005-05-31 18:02:00 +01:00
.macro alignment_ t r a p , r t e m p
2005-04-16 15:20:36 -07:00
# ifdef C O N F I G _ A L I G N M E N T _ T R A P
2005-05-31 18:02:00 +01:00
ldr \ r t e m p , . L C c r a l i g n
ldr \ r t e m p , [ \ r t e m p ]
2005-04-16 15:20:36 -07:00
mcr p15 , 0 , \ r t e m p , c1 , c0
# endif
.endm
2009-07-24 12:32:54 +01:00
@
@ Store/load the USER SP and LR registers by switching to the SYS
@ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not
@ available. Should only be called from SVC mode
@
.macro store_ u s e r _ s p _ l r , r d , r t e m p , o f f s e t = 0
mrs \ r t e m p , c p s r
eor \ r t e m p , \ r t e m p , #( S V C _ M O D E ^ S Y S T E M _ M O D E )
msr c p s r _ c , \ r t e m p @ switch to the SYS mode
str s p , [ \ r d , #\ o f f s e t ] @ s a v e s p _ u s r
str l r , [ \ r d , #\ o f f s e t + 4 ] @ save lr_usr
eor \ r t e m p , \ r t e m p , #( S V C _ M O D E ^ S Y S T E M _ M O D E )
msr c p s r _ c , \ r t e m p @ switch back to the SVC mode
.endm
.macro load_ u s e r _ s p _ l r , r d , r t e m p , o f f s e t = 0
mrs \ r t e m p , c p s r
eor \ r t e m p , \ r t e m p , #( S V C _ M O D E ^ S Y S T E M _ M O D E )
msr c p s r _ c , \ r t e m p @ switch to the SYS mode
ldr s p , [ \ r d , #\ o f f s e t ] @ l o a d s p _ u s r
ldr l r , [ \ r d , #\ o f f s e t + 4 ] @ load lr_usr
eor \ r t e m p , \ r t e m p , #( S V C _ M O D E ^ S Y S T E M _ M O D E )
msr c p s r _ c , \ r t e m p @ switch back to the SVC mode
.endm
# ifndef C O N F I G _ T H U M B 2 _ K E R N E L
.macro svc_ e x i t , r p s r
msr s p s r _ c x s f , \ r p s r
2011-01-17 15:35:37 +00:00
# if d e f i n e d ( C O N F I G _ C P U _ V 6 )
2009-09-18 23:27:05 +01:00
ldr r0 , [ s p ]
strex r1 , r2 , [ s p ] @ clear the exclusive monitor
ldmib s p , { r1 - p c } ^ @ load r1 - pc, cpsr
2011-01-17 15:35:37 +00:00
# elif d e f i n e d ( C O N F I G _ C P U _ 3 2 v6 K )
clrex @ clear the exclusive monitor
ldmia s p , { r0 - p c } ^ @ load r0 - pc, cpsr
2009-09-25 16:28:02 -04:00
# else
ldmia s p , { r0 - p c } ^ @ load r0 - pc, cpsr
2009-09-18 23:27:05 +01:00
# endif
2009-07-24 12:32:54 +01:00
.endm
.macro restore_ u s e r _ r e g s , f a s t = 0 , o f f s e t = 0
ldr r1 , [ s p , #\ o f f s e t + S _ P S R ] @ g e t c a l l i n g c p s r
ldr l r , [ s p , #\ o f f s e t + S _ P C ] ! @ g e t p c
msr s p s r _ c x s f , r1 @ save in spsr_svc
2011-01-17 15:35:37 +00:00
# if d e f i n e d ( C O N F I G _ C P U _ V 6 )
2009-09-18 23:27:05 +01:00
strex r1 , r2 , [ s p ] @ clear the exclusive monitor
2011-01-17 15:35:37 +00:00
# elif d e f i n e d ( C O N F I G _ C P U _ 3 2 v6 K )
clrex @ clear the exclusive monitor
2009-09-18 23:27:05 +01:00
# endif
2009-07-24 12:32:54 +01:00
.if \ fast
ldmdb s p , { r1 - l r } ^ @ get calling r1 - lr
.else
ldmdb s p , { r0 - l r } ^ @ get calling r0 - lr
.endif
2010-03-15 16:04:14 +01:00
mov r0 , r0 @ ARMv5T and earlier require a nop
@ after ldm {}^
2009-07-24 12:32:54 +01:00
add s p , s p , #S _ F R A M E _ S I Z E - S _ P C
movs p c , l r @ return & move spsr_svc into cpsr
.endm
.macro get_ t h r e a d _ i n f o , r d
mov \ r d , s p , l s r #13
mov \ r d , \ r d , l s l #13
.endm
2009-10-12 17:31:20 +01:00
@
@ 32-bit wide "mov pc, reg"
@
.macro movw_ p c , r e g
mov p c , \ r e g
.endm
2009-07-24 12:32:54 +01:00
# else / * C O N F I G _ T H U M B 2 _ K E R N E L * /
.macro svc_ e x i t , r p s r
2011-03-18 17:32:44 +00:00
ldr l r , [ s p , #S _ S P ] @ t o p o f t h e s t a c k
ldrd r0 , r1 , [ s p , #S _ L R ] @ c a l l i n g l r a n d p c
2009-09-18 23:27:05 +01:00
clrex @ clear the exclusive monitor
2011-03-18 17:32:44 +00:00
stmdb l r ! , { r0 , r1 , \ r p s r } @ calling lr and rfe context
2009-07-24 12:32:54 +01:00
ldmia s p , { r0 - r12 }
2011-03-18 17:32:44 +00:00
mov s p , l r
ldr l r , [ s p ] , #4
2009-07-24 12:32:54 +01:00
rfeia s p !
.endm
.macro restore_ u s e r _ r e g s , f a s t = 0 , o f f s e t = 0
2009-09-18 23:27:05 +01:00
clrex @ clear the exclusive monitor
2009-07-24 12:32:54 +01:00
mov r2 , s p
load_ u s e r _ s p _ l r r2 , r3 , \ o f f s e t + S _ S P @ calling sp, lr
ldr r1 , [ s p , #\ o f f s e t + S _ P S R ] @ g e t c a l l i n g c p s r
ldr l r , [ s p , #\ o f f s e t + S _ P C ] @ g e t p c
add s p , s p , #\ o f f s e t + S _ S P
msr s p s r _ c x s f , r1 @ save in spsr_svc
.if \ fast
ldmdb s p , { r1 - r12 } @ get calling r1 - r12
.else
ldmdb s p , { r0 - r12 } @ get calling r0 - r12
.endif
add s p , s p , #S _ F R A M E _ S I Z E - S _ S P
movs p c , l r @ return & move spsr_svc into cpsr
.endm
.macro get_ t h r e a d _ i n f o , r d
mov \ r d , s p
lsr \ r d , \ r d , #13
mov \ r d , \ r d , l s l #13
.endm
2009-10-12 17:31:20 +01:00
@
@ 32-bit wide "mov pc, reg"
@
.macro movw_ p c , r e g
mov p c , \ r e g
nop
.endm
2009-07-24 12:32:54 +01:00
# endif / * ! C O N F I G _ T H U M B 2 _ K E R N E L * /
2005-04-16 15:20:36 -07:00
/ *
* These a r e t h e r e g i s t e r s u s e d i n t h e s y s c a l l h a n d l e r , a n d a l l o w u s t o
* have i n t h e o r y u p t o 7 a r g u m e n t s t o a f u n c t i o n - r0 t o r6 .
*
* r7 i s r e s e r v e d f o r t h e s y s t e m c a l l n u m b e r f o r t h u m b m o d e .
*
* Note t h a t t b l = = w h y i s i n t e n t i o n a l .
*
* We m u s t s e t a t l e a s t " t s k " a n d " w h y " w h e n c a l l i n g r e t _ w i t h _ r e s c h e d u l e .
* /
scno . r e q r7 @ syscall number
tbl . r e q r8 @ syscall table pointer
why . r e q r8 @ Linux syscall (!= 0)
tsk . r e q r9 @ current thread_info