2011-02-06 18:48:39 +03:00
# include < l i n u x / l i n k a g e . h >
2011-02-11 14:32:19 +03:00
# include < l i n u x / t h r e a d s . h >
2011-02-06 18:48:39 +03:00
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / g l u e - c a c h e . h >
# include < a s m / g l u e - p r o c . h >
# include < a s m / s y s t e m . h >
.text
/ *
* Save C P U s t a t e f o r a s u s p e n d
* r1 = v : p o f f s e t
* r3 = v i r t u a l r e t u r n f u n c t i o n
* Note : sp i s d e c r e m e n t e d t o a l l o c a t e s p a c e f o r C P U s t a t e o n s t a c k
* r0 - r3 ,r9 ,r10 ,l r c o r r u p t e d
* /
ENTRY( c p u _ s u s p e n d )
mov r9 , l r
# ifdef M U L T I _ C P U
ldr r10 , =processor
mov r2 , s p @ current virtual SP
ldr r0 , [ r10 , #C P U _ S L E E P _ S I Z E ] @ s i z e o f C P U s l e e p s t a t e
ldr i p , [ r10 , #C P U _ D O _ R E S U M E ] @ v i r t u a l r e s u m e f u n c t i o n
sub s p , s p , r0 @ allocate CPU state on stack
mov r0 , s p @ save pointer
add i p , i p , r1 @ convert resume fn to phys
stmfd s p ! , { r1 , r2 , r3 , i p } @ save v:p, virt SP, retfn, phys resume fn
ldr r3 , =sleep_save_sp
add r2 , s p , r1 @ convert SP to phys
2011-02-11 14:32:19 +03:00
# ifdef C O N F I G _ S M P
ALT_ S M P ( m r c p15 , 0 , l r , c0 , c0 , 5 )
ALT_ U P ( m o v l r , #0 )
and l r , l r , #15
str r2 , [ r3 , l r , l s l #2 ] @ save phys SP
# else
2011-02-06 18:48:39 +03:00
str r2 , [ r3 ] @ save phys SP
2011-02-11 14:32:19 +03:00
# endif
2011-02-06 18:48:39 +03:00
mov l r , p c
ldr p c , [ r10 , #C P U _ D O _ S U S P E N D ] @ s a v e C P U s t a t e
# else
mov r2 , s p @ current virtual SP
ldr r0 , =cpu_suspend_size
sub s p , s p , r0 @ allocate CPU state on stack
mov r0 , s p @ save pointer
stmfd s p ! , { r1 , r2 , r3 } @ save v:p, virt SP, return fn
ldr r3 , =sleep_save_sp
add r2 , s p , r1 @ convert SP to phys
2011-02-11 14:32:19 +03:00
# ifdef C O N F I G _ S M P
ALT_ S M P ( m r c p15 , 0 , l r , c0 , c0 , 5 )
ALT_ U P ( m o v l r , #0 )
and l r , l r , #15
str r2 , [ r3 , l r , l s l #2 ] @ save phys SP
# else
2011-02-06 18:48:39 +03:00
str r2 , [ r3 ] @ save phys SP
2011-02-11 14:32:19 +03:00
# endif
2011-02-06 18:48:39 +03:00
bl c p u _ d o _ s u s p e n d
# endif
@ flush data cache
# ifdef M U L T I _ C A C H E
ldr r10 , =cpu_cache
mov l r , r9
ldr p c , [ r10 , #C A C H E _ F L U S H _ K E R N _ A L L ]
# else
mov l r , r9
b _ _ c p u c _ f l u s h _ k e r n _ a l l
# endif
ENDPROC( c p u _ s u s p e n d )
.ltorg
/ *
* r0 = c o n t r o l r e g i s t e r v a l u e
* r1 = v : p o f f s e t ( p r e s e r v e d b y c p u _ d o _ r e s u m e )
* r2 = p h y s p a g e t a b l e b a s e
* r3 = L 1 s e c t i o n f l a g s
* /
ENTRY( c p u _ r e s u m e _ m m u )
adr r4 , c p u _ r e s u m e _ t u r n _ m m u _ o n
mov r4 , r4 , l s r #20
orr r3 , r3 , r4 , l s l #20
ldr r5 , [ r2 , r4 , l s l #2 ] @ save old mapping
str r3 , [ r2 , r4 , l s l #2 ] @ setup 1:1 mapping for mmu code
sub r2 , r2 , r1
ldr r3 , =cpu_resume_after_mmu
bic r1 , r0 , #C R _ C @ e n s u r e D - c a c h e i s d i s a b l e d
b c p u _ r e s u m e _ t u r n _ m m u _ o n
ENDPROC( c p u _ r e s u m e _ m m u )
.ltorg
.align 5
cpu_resume_turn_mmu_on :
mcr p15 , 0 , r1 , c1 , c0 , 0 @ turn on MMU, I-cache, etc
mrc p15 , 0 , r1 , c0 , c0 , 0 @ read id reg
mov r1 , r1
mov r1 , r1
mov p c , r3 @ jump to virtual address
ENDPROC( c p u _ r e s u m e _ t u r n _ m m u _ o n )
cpu_resume_after_mmu :
str r5 , [ r2 , r4 , l s l #2 ] @ restore old mapping
mcr p15 , 0 , r0 , c1 , c0 , 0 @ turn on D-cache
mov p c , l r
ENDPROC( c p u _ r e s u m e _ a f t e r _ m m u )
/ *
* Note : Yes, p a r t o f t h e f o l l o w i n g c o d e i s l o c a t e d i n t o t h e . d a t a s e c t i o n .
* This i s t o a l l o w s l e e p _ s a v e _ s p t o b e a c c e s s e d w i t h a r e l a t i v e l o a d
* while w e c a n ' t r e l y o n a n y M M U t r a n s l a t i o n . W e c o u l d h a v e p u t
* sleep_ s a v e _ s p i n t h e . t e x t s e c t i o n a s w e l l , b u t s o m e s e t u p s m i g h t
* insist o n i t t o b e t r u l y r e a d - o n l y .
* /
.data
.align
ENTRY( c p u _ r e s u m e )
2011-02-11 14:32:19 +03:00
# ifdef C O N F I G _ S M P
adr r0 , s l e e p _ s a v e _ s p
ALT_ S M P ( m r c p15 , 0 , r1 , c0 , c0 , 5 )
ALT_ U P ( m o v r1 , #0 )
and r1 , r1 , #15
ldr r0 , [ r0 , r1 , l s l #2 ] @ stack phys addr
# else
2011-02-06 18:48:39 +03:00
ldr r0 , s l e e p _ s a v e _ s p @ stack phys addr
2011-02-11 14:32:19 +03:00
# endif
2011-03-22 21:09:14 +03:00
setmode P S R _ I _ B I T | P S R _ F _ B I T | S V C _ M O D E , r1 @ set SVC, irqs off
2011-02-06 18:48:39 +03:00
# ifdef M U L T I _ C P U
2011-03-22 21:09:14 +03:00
@ load v:p, stack, return fn, resume fn
ARM( l d m i a r0 ! , { r1 , s p , l r , p c } )
THUMB( l d m i a r0 ! , { r1 , r2 , r3 , r4 } )
THUMB( m o v s p , r2 )
THUMB( m o v l r , r3 )
THUMB( b x r4 )
2011-02-06 18:48:39 +03:00
# else
2011-03-22 21:09:14 +03:00
@ load v:p, stack, return fn
ARM( l d m i a r0 ! , { r1 , s p , l r } )
THUMB( l d m i a r0 ! , { r1 , r2 , l r } )
THUMB( m o v s p , r2 )
2011-02-06 18:48:39 +03:00
b c p u _ d o _ r e s u m e
# endif
ENDPROC( c p u _ r e s u m e )
sleep_save_sp :
2011-02-11 14:32:19 +03:00
.rept CONFIG_NR_CPUS
.long 0 @ preserve stack phys ptr here
.endr