2005-06-23 22:01:20 -07:00
/ *
* arch/ x t e n s a / l i b / u s e r c o p y . S
*
* Copy t o / f r o m u s e r s p a c e ( d e r i v e d f r o m a r c h / x t e n s a / l i b / h a l / m e m c o p y . S )
*
* DO N O T C O M B I N E t h i s f u n c t i o n w i t h < a r c h / x t e n s a / l i b / h a l / m e m c o p y . S > .
* It n e e d s t o r e m a i n s e p a r a t e a n d d i s t i n c t . T h e h a l f i l e s a r e p a r t
2006-10-03 22:21:02 +02:00
* of t h e X t e n s a l i n k - t i m e H A L , a n d t h o s e f i l e s m a y d i f f e r p e r
2005-06-23 22:01:20 -07:00
* processor c o n f i g u r a t i o n . P a t c h i n g t h e k e r n e l f o r a n o t h e r
* processor c o n f i g u r a t i o n i n c l u d e s r e p l a c i n g t h e h a l f i l e s , a n d w e
2006-10-03 22:21:02 +02:00
* could l o s e t h e s p e c i a l f u n c t i o n a l i t y f o r a c c e s s i n g u s e r - s p a c e
2005-06-23 22:01:20 -07:00
* memory d u r i n g s u c h a p a t c h . W e s a c r i f i c e a l i t t l e c o d e s p a c e h e r e
* in f a v o r t o s i m p l i f y c o d e m a i n t e n a n c e .
*
* This f i l e i s s u b j e c t t o t h e t e r m s a n d c o n d i t i o n s o f t h e G N U G e n e r a l
* Public L i c e n s e . S e e t h e f i l e " C O P Y I N G " i n t h e m a i n d i r e c t o r y o f
* this a r c h i v e f o r m o r e d e t a i l s .
*
* Copyright ( C ) 2 0 0 2 T e n s i l i c a I n c .
* /
/ *
* size_ t _ _ x t e n s a _ c o p y _ u s e r ( v o i d * d s t , c o n s t v o i d * s r c , s i z e _ t l e n ) ;
*
* The r e t u r n e d v a l u e i s t h e n u m b e r o f b y t e s n o t c o p i e d . I m p l i e s z e r o
* is s u c c e s s .
*
* The g e n e r a l c a s e a l g o r i t h m i s a s f o l l o w s :
* If t h e d e s t i n a t i o n a n d s o u r c e a r e b o t h a l i g n e d ,
* do 1 6 B c h u n k s w i t h a l o o p , a n d t h e n f i n i s h u p w i t h
* 8 B, 4 B , 2 B , a n d 1 B c o p i e s c o n d i t i o n a l o n t h e l e n g t h .
* If d e s t i n a t i o n i s a l i g n e d a n d s o u r c e u n a l i g n e d ,
* do t h e s a m e , b u t u s e S R C t o a l i g n t h e s o u r c e d a t a .
* If d e s t i n a t i o n i s u n a l i g n e d , a l i g n i t b y c o n d i t i o n a l l y
* copying 1 B a n d 2 B a n d t h e n r e t e s t .
* This c o d e t r i e s t o u s e f a l l - t h r o u g h b r a c h e s f o r t h e c o m m o n
* case o f a l i g n e d d e s t i n a t i o n s ( e x c e p t f o r t h e b r a n c h e s t o
* the a l i g n m e n t l a b e l ) .
*
* Register u s e :
* a0 / r e t u r n a d d r e s s
* a1 / s t a c k p o i n t e r
* a2 / r e t u r n v a l u e
* a3 / s r c
* a4 / l e n g t h
* a5 / d s t
* a6 / t m p
* a7 / t m p
* a8 / t m p
* a9 / t m p
* a1 0 / t m p
* a1 1 / o r i g i n a l l e n g t h
* /
2008-11-06 06:40:46 -08:00
# include < v a r i a n t / c o r e . h >
2005-06-23 22:01:20 -07:00
# ifdef _ _ X T E N S A _ E B _ _
# define A L I G N ( R , W 0 , W 1 ) s r c R , W 0 , W 1
# define S S A 8 ( R ) s s a8 b R
# else
# define A L I G N ( R , W 0 , W 1 ) s r c R , W 1 , W 0
# define S S A 8 ( R ) s s a8 l R
# endif
/* Load or store instructions that may cause exceptions use the EX macro. */
# define E X ( i n s n ,r e g 1 ,r e g 2 ,o f f s e t ,h a n d l e r ) \
9 : insn r e g 1 , r e g 2 , o f f s e t ; \
.section _ _ ex_ t a b l e , " a " ; \
.word 9 b, h a n d l e r ; \
.previous
.text
.align 4
.global __xtensa_copy_user
.type _ _ xtensa_ c o p y _ u s e r ,@function
__xtensa_copy_user :
entry s p , 1 6 # m i n i m a l s t a c k f r a m e
# a2 / d s t , a3 / s r c , a4 / l e n
mov a5 , a2 # c o p y d s t s o t h a t a 2 i s r e t u r n v a l u e
mov a11 , a4 # p r e s e r v e o r i g i n a l l e n f o r e r r o r c a s e
.Lcommon :
bbsi. l a2 , 0 , . L d s t 1 m o d2 # i f d s t i s 1 m o d 2
bbsi. l a2 , 1 , . L d s t 2 m o d4 # i f d s t i s 2 m o d 4
.Ldstaligned : # return h e r e f r o m . L d s t u n a l i g n e d w h e n d s t i s a l i g n e d
srli a7 , a4 , 4 # n u m b e r o f l o o p i t e r a t i o n s w i t h 16 B
# per i t e r a t i o n
movi a8 , 3 # i f s o u r c e i s a l s o a l i g n e d ,
bnone a3 , a8 , . L a l i g n e d # t h e n u s e w o r d c o p y
SSA8 ( a3 ) # s e t s h i f t a m o u n t f r o m b y t e o f f s e t
bnez a4 , . L s r c u n a l i g n e d
movi a2 , 0 # r e t u r n s u c c e s s f o r l e n = = 0
retw
/ *
* Destination i s u n a l i g n e d
* /
.Ldst1mod2 : # dst i s o n l y b y t e a l i g n e d
bltui a4 , 7 , . L b y t e c o p y # d o s h o r t c o p i e s b y t e b y b y t e
# copy 1 b y t e
EX( l 8 u i , a6 , a3 , 0 , l _ f i x u p )
addi a3 , a3 , 1
EX( s8 i , a6 , a5 , 0 , s _ f i x u p )
addi a5 , a5 , 1
addi a4 , a4 , - 1
bbci. l a5 , 1 , . L d s t a l i g n e d # i f d s t i s n o w a l i g n e d , t h e n
# return t o m a i n a l g o r i t h m
.Ldst2mod4 : # dst 1 6 - b i t a l i g n e d
# copy 2 b y t e s
bltui a4 , 6 , . L b y t e c o p y # d o s h o r t c o p i e s b y t e b y b y t e
EX( l 8 u i , a6 , a3 , 0 , l _ f i x u p )
EX( l 8 u i , a7 , a3 , 1 , l _ f i x u p )
addi a3 , a3 , 2
EX( s8 i , a6 , a5 , 0 , s _ f i x u p )
EX( s8 i , a7 , a5 , 1 , s _ f i x u p )
addi a5 , a5 , 2
addi a4 , a4 , - 2
j . L d s t a l i g n e d # d s t i s n o w a l i g n e d , r e t u r n t o m a i n a l g o r i t h m
/ *
* Byte b y b y t e c o p y
* /
.align 4
.byte 0 # 1 mod 4 a l i g n m e n t f o r L O O P N E Z
# ( 0 mod 4 a l i g n m e n t f o r L B E G )
.Lbytecopy :
# if X C H A L _ H A V E _ L O O P S
loopnez a4 , . L b y t e c o p y d o n e
# else / * ! X C H A L _ H A V E _ L O O P S * /
beqz a4 , . L b y t e c o p y d o n e
add a7 , a3 , a4 # a 7 = e n d a d d r e s s f o r s o u r c e
# endif / * ! X C H A L _ H A V E _ L O O P S * /
.Lnextbyte :
EX( l 8 u i , a6 , a3 , 0 , l _ f i x u p )
addi a3 , a3 , 1
EX( s8 i , a6 , a5 , 0 , s _ f i x u p )
addi a5 , a5 , 1
# if ! X C H A L _ H A V E _ L O O P S
blt a3 , a7 , . L n e x t b y t e
# endif / * ! X C H A L _ H A V E _ L O O P S * /
.Lbytecopydone :
movi a2 , 0 # r e t u r n s u c c e s s f o r l e n b y t e s c o p i e d
retw
/ *
* Destination a n d s o u r c e a r e w o r d - a l i g n e d .
* /
# copy 1 6 b y t e s p e r i t e r a t i o n f o r w o r d - a l i g n e d d s t a n d w o r d - a l i g n e d s r c
.align 4 # 1 mod 4 a l i g n m e n t f o r L O O P N E Z
.byte 0 # ( 0 mod 4 a l i g n m e n t f o r L B E G )
.Laligned :
# if X C H A L _ H A V E _ L O O P S
loopnez a7 , . L o o p1 d o n e
# else / * ! X C H A L _ H A V E _ L O O P S * /
beqz a7 , . L o o p1 d o n e
slli a8 , a7 , 4
add a8 , a8 , a3 # a 8 = e n d o f l a s t 1 6 B s o u r c e c h u n k
# endif / * ! X C H A L _ H A V E _ L O O P S * /
.Loop1 :
EX( l 3 2 i , a6 , a3 , 0 , l _ f i x u p )
EX( l 3 2 i , a7 , a3 , 4 , l _ f i x u p )
EX( s32 i , a6 , a5 , 0 , s _ f i x u p )
EX( l 3 2 i , a6 , a3 , 8 , l _ f i x u p )
EX( s32 i , a7 , a5 , 4 , s _ f i x u p )
EX( l 3 2 i , a7 , a3 , 1 2 , l _ f i x u p )
EX( s32 i , a6 , a5 , 8 , s _ f i x u p )
addi a3 , a3 , 1 6
EX( s32 i , a7 , a5 , 1 2 , s _ f i x u p )
addi a5 , a5 , 1 6
# if ! X C H A L _ H A V E _ L O O P S
blt a3 , a8 , . L o o p1
# endif / * ! X C H A L _ H A V E _ L O O P S * /
.Loop1done :
bbci. l a4 , 3 , . L 2
# copy 8 b y t e s
EX( l 3 2 i , a6 , a3 , 0 , l _ f i x u p )
EX( l 3 2 i , a7 , a3 , 4 , l _ f i x u p )
addi a3 , a3 , 8
EX( s32 i , a6 , a5 , 0 , s _ f i x u p )
EX( s32 i , a7 , a5 , 4 , s _ f i x u p )
addi a5 , a5 , 8
.L2 :
bbci. l a4 , 2 , . L 3
# copy 4 b y t e s
EX( l 3 2 i , a6 , a3 , 0 , l _ f i x u p )
addi a3 , a3 , 4
EX( s32 i , a6 , a5 , 0 , s _ f i x u p )
addi a5 , a5 , 4
.L3 :
bbci. l a4 , 1 , . L 4
# copy 2 b y t e s
EX( l 1 6 u i , a6 , a3 , 0 , l _ f i x u p )
addi a3 , a3 , 2
EX( s16 i , a6 , a5 , 0 , s _ f i x u p )
addi a5 , a5 , 2
.L4 :
bbci. l a4 , 0 , . L 5
# copy 1 b y t e
EX( l 8 u i , a6 , a3 , 0 , l _ f i x u p )
EX( s8 i , a6 , a5 , 0 , s _ f i x u p )
.L5 :
movi a2 , 0 # r e t u r n s u c c e s s f o r l e n b y t e s c o p i e d
retw
/ *
* Destination i s a l i g n e d , S o u r c e i s u n a l i g n e d
* /
.align 4
.byte 0 # 1 mod 4 a l i g n e m e n t f o r L O O P N E Z
# ( 0 mod 4 a l i g n m e n t f o r L B E G )
.Lsrcunaligned :
# copy 1 6 b y t e s p e r i t e r a t i o n f o r w o r d - a l i g n e d d s t a n d u n a l i g n e d s r c
and a10 , a3 , a8 # s a v e u n a l i g n m e n t o f f s e t f o r b e l o w
sub a3 , a3 , a10 # a l i g n a 3 ( t o a v o i d s i m w a r n i n g s o n l y ; not needed for hardware)
EX( l 3 2 i , a6 , a3 , 0 , l _ f i x u p ) # l o a d f i r s t w o r d
# if X C H A L _ H A V E _ L O O P S
loopnez a7 , . L o o p2 d o n e
# else / * ! X C H A L _ H A V E _ L O O P S * /
beqz a7 , . L o o p2 d o n e
slli a10 , a7 , 4
add a10 , a10 , a3 # a 10 = e n d o f l a s t 1 6 B s o u r c e c h u n k
# endif / * ! X C H A L _ H A V E _ L O O P S * /
.Loop2 :
EX( l 3 2 i , a7 , a3 , 4 , l _ f i x u p )
EX( l 3 2 i , a8 , a3 , 8 , l _ f i x u p )
ALIGN( a6 , a6 , a7 )
EX( s32 i , a6 , a5 , 0 , s _ f i x u p )
EX( l 3 2 i , a9 , a3 , 1 2 , l _ f i x u p )
ALIGN( a7 , a7 , a8 )
EX( s32 i , a7 , a5 , 4 , s _ f i x u p )
EX( l 3 2 i , a6 , a3 , 1 6 , l _ f i x u p )
ALIGN( a8 , a8 , a9 )
EX( s32 i , a8 , a5 , 8 , s _ f i x u p )
addi a3 , a3 , 1 6
ALIGN( a9 , a9 , a6 )
EX( s32 i , a9 , a5 , 1 2 , s _ f i x u p )
addi a5 , a5 , 1 6
# if ! X C H A L _ H A V E _ L O O P S
blt a3 , a10 , . L o o p2
# endif / * ! X C H A L _ H A V E _ L O O P S * /
.Loop2done :
bbci. l a4 , 3 , . L 1 2
# copy 8 b y t e s
EX( l 3 2 i , a7 , a3 , 4 , l _ f i x u p )
EX( l 3 2 i , a8 , a3 , 8 , l _ f i x u p )
ALIGN( a6 , a6 , a7 )
EX( s32 i , a6 , a5 , 0 , s _ f i x u p )
addi a3 , a3 , 8
ALIGN( a7 , a7 , a8 )
EX( s32 i , a7 , a5 , 4 , s _ f i x u p )
addi a5 , a5 , 8
mov a6 , a8
.L12 :
bbci. l a4 , 2 , . L 1 3
# copy 4 b y t e s
EX( l 3 2 i , a7 , a3 , 4 , l _ f i x u p )
addi a3 , a3 , 4
ALIGN( a6 , a6 , a7 )
EX( s32 i , a6 , a5 , 0 , s _ f i x u p )
addi a5 , a5 , 4
mov a6 , a7
.L13 :
add a3 , a3 , a10 # r e a d j u s t a 3 w i t h c o r r e c t m i s a l i g n m e n t
bbci. l a4 , 1 , . L 1 4
# copy 2 b y t e s
EX( l 8 u i , a6 , a3 , 0 , l _ f i x u p )
EX( l 8 u i , a7 , a3 , 1 , l _ f i x u p )
addi a3 , a3 , 2
EX( s8 i , a6 , a5 , 0 , s _ f i x u p )
EX( s8 i , a7 , a5 , 1 , s _ f i x u p )
addi a5 , a5 , 2
.L14 :
bbci. l a4 , 0 , . L 1 5
# copy 1 b y t e
EX( l 8 u i , a6 , a3 , 0 , l _ f i x u p )
EX( s8 i , a6 , a5 , 0 , s _ f i x u p )
.L15 :
movi a2 , 0 # r e t u r n s u c c e s s f o r l e n b y t e s c o p i e d
retw
.section .fixup , " ax"
.align 4
/ * a2 = o r i g i n a l d s t ; a5 = current dst; a11= original len
* bytes_ c o p i e d = a5 - a2
* retval = b y t e s _ n o t _ c o p i e d = o r i g i n a l l e n - b y t e s _ c o p i e d
* retval = a11 - ( a5 - a2 )
*
* Clearing t h e r e m a i n i n g p i e c e s o f k e r n e l m e m o r y p l u g s s e c u r i t y
* holes. T h i s f u n c t i o n a l i t y i s t h e e q u i v a l e n t o f t h e * _ z e r o i n g
* functions t h a t s o m e a r c h i t e c t u r e s p r o v i d e .
* /
.Lmemset :
.word memset
s_fixup :
sub a2 , a5 , a2 / * a2 < - - b y t e s c o p i e d * /
sub a2 , a11 , a2 / * a2 < - - b y t e s n o t c o p i e d * /
retw
l_fixup :
sub a2 , a5 , a2 / * a2 < - - b y t e s c o p i e d * /
sub a2 , a11 , a2 / * a2 < - - b y t e s n o t c o p i e d = = r e t u r n v a l u e * /
/* void *memset(void *s, int c, size_t n); */
mov a6 , a5 / * s * /
movi a7 , 0 / * c * /
mov a8 , a2 / * n * /
l3 2 r a4 , . L m e m s e t
callx4 a4
/* Ignore memset return value in a6. */
/* a2 still contains bytes not copied. */
retw