2005-04-17 02:20:36 +04:00
/ *
* linux/ a r c h / a r m / k e r n e l / i w m m x t . S
*
* XScale i W M M X t ( C o n c a n ) c o n t e x t s w i t c h i n g a n d h a n d l i n g
*
* Initial c o d e :
* Copyright ( c ) 2 0 0 3 , I n t e l C o r p o r a t i o n
*
* Full l a z y s w i t c h i n g s u p p o r t , o p t i m i z a t i o n s a n d m o r e , b y N i c o l a s P i t r e
* Copyright ( c ) 2 0 0 3 - 2 0 0 4 , M o n t a V i s t a S o f t w a r e , I n c .
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify
* it u n d e r t h e t e r m s o f t h e G N U G e n e r a l P u b l i c L i c e n s e v e r s i o n 2 a s
* published b y t h e F r e e S o f t w a r e F o u n d a t i o n .
* /
# include < l i n u x / l i n k a g e . h >
# include < a s m / p t r a c e . h >
# include < a s m / t h r e a d _ i n f o . h >
2005-09-09 23:08:59 +04:00
# include < a s m / a s m - o f f s e t s . h >
2005-04-17 02:20:36 +04:00
# define M M X _ W R 0 ( 0 x00 )
# define M M X _ W R 1 ( 0 x08 )
# define M M X _ W R 2 ( 0 x10 )
# define M M X _ W R 3 ( 0 x18 )
# define M M X _ W R 4 ( 0 x20 )
# define M M X _ W R 5 ( 0 x28 )
# define M M X _ W R 6 ( 0 x30 )
# define M M X _ W R 7 ( 0 x38 )
# define M M X _ W R 8 ( 0 x40 )
# define M M X _ W R 9 ( 0 x48 )
# define M M X _ W R 1 0 ( 0 x50 )
# define M M X _ W R 1 1 ( 0 x58 )
# define M M X _ W R 1 2 ( 0 x60 )
# define M M X _ W R 1 3 ( 0 x68 )
# define M M X _ W R 1 4 ( 0 x70 )
# define M M X _ W R 1 5 ( 0 x78 )
# define M M X _ W C S S F ( 0 x80 )
# define M M X _ W C A S F ( 0 x84 )
# define M M X _ W C G R 0 ( 0 x88 )
# define M M X _ W C G R 1 ( 0 x8 C )
# define M M X _ W C G R 2 ( 0 x90 )
# define M M X _ W C G R 3 ( 0 x94 )
# define M M X _ S I Z E ( 0 x98 )
.text
/ *
* Lazy s w i t c h i n g o f C o n c a n c o p r o c e s s o r c o n t e x t
*
* r1 0 = s t r u c t t h r e a d _ i n f o p o i n t e r
* r9 = r e t _ f r o m _ e x c e p t i o n
* lr = u n d e f i n e d i n s t r e x i t
*
* called f r o m p r e f e t c h e x c e p t i o n h a n d l e r w i t h i n t e r r u p t s d i s a b l e d
* /
ENTRY( i w m m x t _ t a s k _ e n a b l e )
mrc p15 , 0 , r2 , c15 , c1 , 0
tst r2 , #0x3 @ CP0 and CP1 accessible?
movne p c , l r @ if so no business here
orr r2 , r2 , #0x3 @ enable access to CP0 and CP1
mcr p15 , 0 , r2 , c15 , c1 , 0
ldr r3 , =concan_owner
add r0 , r10 , #T I _ I W M M X T _ S T A T E @ g e t t a s k C o n c a n s a v e a r e a
ldr r2 , [ s p , #60 ] @ current task pc value
ldr r1 , [ r3 ] @ get current Concan owner
str r0 , [ r3 ] @ this task now owns Concan regs
sub r2 , r2 , #4 @ adjust pc back
str r2 , [ s p , #60 ]
mrc p15 , 0 , r2 , c2 , c0 , 0
mov r2 , r2 @ cpwait
teq r1 , #0 @ test for last ownership
mov l r , r9 @ normal exit from exception
beq c o n c a n _ l o a d @ no owner, skip save
concan_save :
tmrc r2 , w C o n
@ CUP? wCx
tst r2 , #0x1
beq 1 f
concan_dump :
wstrw w C S S F , [ r1 , #M M X _ W C S S F ]
wstrw w C A S F , [ r1 , #M M X _ W C A S F ]
wstrw w C G R 0 , [ r1 , #M M X _ W C G R 0 ]
wstrw w C G R 1 , [ r1 , #M M X _ W C G R 1 ]
wstrw w C G R 2 , [ r1 , #M M X _ W C G R 2 ]
wstrw w C G R 3 , [ r1 , #M M X _ W C G R 3 ]
1 : @ MUP? wRn
tst r2 , #0x2
beq 2 f
wstrd w R 0 , [ r1 , #M M X _ W R 0 ]
wstrd w R 1 , [ r1 , #M M X _ W R 1 ]
wstrd w R 2 , [ r1 , #M M X _ W R 2 ]
wstrd w R 3 , [ r1 , #M M X _ W R 3 ]
wstrd w R 4 , [ r1 , #M M X _ W R 4 ]
wstrd w R 5 , [ r1 , #M M X _ W R 5 ]
wstrd w R 6 , [ r1 , #M M X _ W R 6 ]
wstrd w R 7 , [ r1 , #M M X _ W R 7 ]
wstrd w R 8 , [ r1 , #M M X _ W R 8 ]
wstrd w R 9 , [ r1 , #M M X _ W R 9 ]
wstrd w R 1 0 , [ r1 , #M M X _ W R 10 ]
wstrd w R 1 1 , [ r1 , #M M X _ W R 11 ]
wstrd w R 1 2 , [ r1 , #M M X _ W R 12 ]
wstrd w R 1 3 , [ r1 , #M M X _ W R 13 ]
wstrd w R 1 4 , [ r1 , #M M X _ W R 14 ]
wstrd w R 1 5 , [ r1 , #M M X _ W R 15 ]
2 : teq r0 , #0 @ anything to load?
moveq p c , l r
concan_load :
@ Load wRn
wldrd w R 0 , [ r0 , #M M X _ W R 0 ]
wldrd w R 1 , [ r0 , #M M X _ W R 1 ]
wldrd w R 2 , [ r0 , #M M X _ W R 2 ]
wldrd w R 3 , [ r0 , #M M X _ W R 3 ]
wldrd w R 4 , [ r0 , #M M X _ W R 4 ]
wldrd w R 5 , [ r0 , #M M X _ W R 5 ]
wldrd w R 6 , [ r0 , #M M X _ W R 6 ]
wldrd w R 7 , [ r0 , #M M X _ W R 7 ]
wldrd w R 8 , [ r0 , #M M X _ W R 8 ]
wldrd w R 9 , [ r0 , #M M X _ W R 9 ]
wldrd w R 1 0 , [ r0 , #M M X _ W R 10 ]
wldrd w R 1 1 , [ r0 , #M M X _ W R 11 ]
wldrd w R 1 2 , [ r0 , #M M X _ W R 12 ]
wldrd w R 1 3 , [ r0 , #M M X _ W R 13 ]
wldrd w R 1 4 , [ r0 , #M M X _ W R 14 ]
wldrd w R 1 5 , [ r0 , #M M X _ W R 15 ]
@ Load wCx
wldrw w C S S F , [ r0 , #M M X _ W C S S F ]
wldrw w C A S F , [ r0 , #M M X _ W C A S F ]
wldrw w C G R 0 , [ r0 , #M M X _ W C G R 0 ]
wldrw w C G R 1 , [ r0 , #M M X _ W C G R 1 ]
wldrw w C G R 2 , [ r0 , #M M X _ W C G R 2 ]
wldrw w C G R 3 , [ r0 , #M M X _ W C G R 3 ]
@ clear CUP/MUP (only if r1 != 0)
teq r1 , #0
mov r2 , #0
moveq p c , l r
tmcr w C o n , r2
mov p c , l r
/ *
* Back u p C o n c a n r e g s t o s a v e a r e a a n d d i s a b l e a c c e s s t o t h e m
* ( mainly f o r g d b o r s l e e p m o d e u s a g e )
*
* r0 = s t r u c t t h r e a d _ i n f o p o i n t e r o f t a r g e t t a s k o r N U L L f o r a n y
* /
ENTRY( i w m m x t _ t a s k _ d i s a b l e )
stmfd s p ! , { r4 , l r }
mrs i p , c p s r
orr r2 , i p , #P S R _ I _ B I T @ d i s a b l e i n t e r r u p t s
msr c p s r _ c , r2
ldr r3 , =concan_owner
add r2 , r0 , #T I _ I W M M X T _ S T A T E @ g e t t a s k C o n c a n s a v e a r e a
ldr r1 , [ r3 ] @ get current Concan owner
teq r1 , #0 @ any current owner?
beq 1 f @ no: quit
teq r0 , #0 @ any owner?
teqne r1 , r2 @ or specified one?
bne 1 f @ no: quit
mrc p15 , 0 , r4 , c15 , c1 , 0
orr r4 , r4 , #0x3 @ enable access to CP0 and CP1
mcr p15 , 0 , r4 , c15 , c1 , 0
mov r0 , #0 @ nothing to load
str r0 , [ r3 ] @ no more current owner
mrc p15 , 0 , r2 , c2 , c0 , 0
mov r2 , r2 @ cpwait
bl c o n c a n _ s a v e
bic r4 , r4 , #0x3 @ disable access to CP0 and CP1
mcr p15 , 0 , r4 , c15 , c1 , 0
mrc p15 , 0 , r2 , c2 , c0 , 0
mov r2 , r2 @ cpwait
1 : msr c p s r _ c , i p @ restore interrupt mode
ldmfd s p ! , { r4 , p c }
/ *
* Copy C o n c a n s t a t e t o g i v e n m e m o r y a d d r e s s
*
* r0 = s t r u c t t h r e a d _ i n f o p o i n t e r o f t a r g e t t a s k
* r1 = m e m o r y a d d r e s s w h e r e t o s t o r e C o n c a n s t a t e
*
* this i s c a l l e d m a i n l y i n t h e c r e a t i o n o f s i g n a l s t a c k f r a m e s
* /
ENTRY( i w m m x t _ t a s k _ c o p y )
mrs i p , c p s r
orr r2 , i p , #P S R _ I _ B I T @ d i s a b l e i n t e r r u p t s
msr c p s r _ c , r2
ldr r3 , =concan_owner
add r2 , r0 , #T I _ I W M M X T _ S T A T E @ g e t t a s k C o n c a n s a v e a r e a
ldr r3 , [ r3 ] @ get current Concan owner
teq r2 , r3 @ does this task own it...
beq 1 f
@ current Concan values are in the task save area
msr c p s r _ c , i p @ restore interrupt mode
mov r0 , r1
mov r1 , r2
mov r2 , #M M X _ S I Z E
b m e m c p y
1 : @ this task owns Concan regs -- grab a copy from there
mov r0 , #0 @ nothing to load
mov r2 , #3 @ save all regs
mov r3 , l r @ preserve return address
bl c o n c a n _ d u m p
msr c p s r _ c , i p @ restore interrupt mode
mov p c , r3
/ *
* Restore C o n c a n s t a t e f r o m g i v e n m e m o r y a d d r e s s
*
* r0 = s t r u c t t h r e a d _ i n f o p o i n t e r o f t a r g e t t a s k
* r1 = m e m o r y a d d r e s s w h e r e t o g e t C o n c a n s t a t e f r o m
*
* this i s u s e d t o r e s t o r e C o n c a n s t a t e w h e n u n w i n d i n g a s i g n a l s t a c k f r a m e
* /
ENTRY( i w m m x t _ t a s k _ r e s t o r e )
mrs i p , c p s r
orr r2 , i p , #P S R _ I _ B I T @ d i s a b l e i n t e r r u p t s
msr c p s r _ c , r2
ldr r3 , =concan_owner
add r2 , r0 , #T I _ I W M M X T _ S T A T E @ g e t t a s k C o n c a n s a v e a r e a
ldr r3 , [ r3 ] @ get current Concan owner
bic r2 , r2 , #0x7 @ 64-bit alignment
teq r2 , r3 @ does this task own it...
beq 1 f
@ this task doesn't own Concan regs -- use its save area
msr c p s r _ c , i p @ restore interrupt mode
mov r0 , r2
mov r2 , #M M X _ S I Z E
b m e m c p y
1 : @ this task owns Concan regs -- load them directly
mov r0 , r1
mov r1 , #0 @ don't clear CUP/MUP
mov r3 , l r @ preserve return address
bl c o n c a n _ l o a d
msr c p s r _ c , i p @ restore interrupt mode
mov p c , r3
/ *
* Concan h a n d l i n g o n t a s k s w i t c h
*
2006-07-01 22:56:48 +04:00
* r0 = n e x t t h r e a d _ i n f o p o i n t e r
2005-04-17 02:20:36 +04:00
*
2006-07-01 22:56:48 +04:00
* Called o n l y f r o m t h e i w m m x t n o t i f i e r w i t h t a s k p r e e m p t i o n d i s a b l e d .
2005-04-17 02:20:36 +04:00
* /
ENTRY( i w m m x t _ t a s k _ s w i t c h )
2006-07-01 22:56:48 +04:00
mrc p15 , 0 , r1 , c15 , c1 , 0
tst r1 , #0x3 @ CP0 and CP1 accessible?
2005-04-17 02:20:36 +04:00
bne 1 f @ yes: block them for next task
2006-07-01 22:56:48 +04:00
ldr r2 , =concan_owner
add r3 , r0 , #T I _ I W M M X T _ S T A T E @ g e t n e x t t a s k C o n c a n s a v e a r e a
ldr r2 , [ r2 ] @ get current Concan owner
teq r2 , r3 @ next task owns it?
2005-04-17 02:20:36 +04:00
movne p c , l r @ no: leave Concan disabled
2006-07-01 22:56:48 +04:00
1 : eor r1 , r1 , #3 @ flip Concan access
mcr p15 , 0 , r1 , c15 , c1 , 0
2005-04-17 02:20:36 +04:00
2006-07-01 22:56:48 +04:00
mrc p15 , 0 , r1 , c2 , c0 , 0
sub p c , l r , r1 , l s r #32 @ cpwait and return
2005-04-17 02:20:36 +04:00
/ *
* Remove C o n c a n o w n e r s h i p o f g i v e n t a s k
*
* r0 = s t r u c t t h r e a d _ i n f o p o i n t e r
* /
ENTRY( i w m m x t _ t a s k _ r e l e a s e )
mrs r2 , c p s r
orr i p , r2 , #P S R _ I _ B I T @ d i s a b l e i n t e r r u p t s
msr c p s r _ c , i p
ldr r3 , =concan_owner
add r0 , r0 , #T I _ I W M M X T _ S T A T E @ g e t t a s k C o n c a n s a v e a r e a
ldr r1 , [ r3 ] @ get current Concan owner
eors r0 , r0 , r1 @ if equal...
streq r0 , [ r3 ] @ then clear ownership
msr c p s r _ c , r2 @ restore interrupts
mov p c , l r
.data
concan_owner :
.word 0