2009-05-26 16:30:23 +02:00
/ *
* Copyright ( C ) 2 0 0 9 M i c h a l S i m e k < m o n s t r @monstr.eu>
* Copyright ( C ) 2 0 0 9 P e t a L o g i x
* Copyright ( C ) 2 0 0 7 L y n u x W o r k s , I n c .
*
* 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 P u b l i c
* License. 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 t h i s a r c h i v e
* for m o r e d e t a i l s .
* /
# include < l i n u x / e r r n o . h >
# include < l i n u x / l i n k a g e . h >
2011-06-10 10:49:08 +02:00
# include < a s m / p a g e . h >
2009-05-26 16:30:23 +02:00
/ *
* int _ _ s t r n c p y _ u s e r ( c h a r * t o , c h a r * f r o m , i n t l e n ) ;
*
* Returns :
* - EFAULT f o r a n e x c e p t i o n
* len i f w e h i t t h e b u f f e r l i m i t
* bytes c o p i e d
* /
.text
.globl _ _ strncpy_ u s e r ;
2010-03-23 08:09:32 +01:00
.type _ _ strncpy_ u s e r , @function
2009-05-26 16:30:23 +02:00
.align 4 ;
__strncpy_user :
/ *
* r5 - t o
* r6 - f r o m
* r7 - l e n
* r3 - t e m p c o u n t
* r4 - t e m p v a l
* /
2011-10-02 13:07:02 +02:00
beqid r7 ,3 f
2009-05-26 16:30:23 +02:00
addik r3 ,r7 ,0 / * t e m p _ c o u n t = l e n * /
1 :
lbu r4 ,r6 ,r0
2013-01-16 18:53:22 +01:00
beqid r4 ,2 f
2009-05-26 16:30:23 +02:00
sb r4 ,r5 ,r0
addik r5 ,r5 ,1
addik r6 ,r6 ,1 / * d e l a y s l o t * /
2013-01-16 18:53:22 +01:00
addik r3 ,r3 ,- 1
bnei r3 ,1 b / * b r e a k o n l e n * /
2009-05-26 16:30:23 +02:00
2 :
rsubk r3 ,r3 ,r7 / * t e m p _ c o u n t = l e n - t e m p _ c o u n t * /
3 :
rtsd r15 ,8
nop
2010-03-23 08:09:32 +01:00
.size _ _ strncpy_ u s e r , . - _ _ s t r n c p y _ u s e r
2009-05-26 16:30:23 +02:00
.section .fixup , " ax"
.align 2
4 :
brid 3 b
addik r3 ,r0 , - E F A U L T
.section _ _ ex_ t a b l e , " a "
.word 1 b,4 b
/ *
* int _ _ s t r n l e n _ u s e r ( c h a r _ _ u s e r * s t r , i n t m a x l e n ) ;
*
* Returns :
* 0 on e r r o r
* maxlen + 1 i f n o N U L b y t e f o u n d w i t h i n m a x l e n b y t e s
* size o f t h e s t r i n g ( i n c l u d i n g N U L b y t e )
* /
.text
.globl _ _ strnlen_ u s e r ;
2010-03-23 08:09:32 +01:00
.type _ _ strnlen_ u s e r , @function
2009-05-26 16:30:23 +02:00
.align 4 ;
__strnlen_user :
2011-10-02 13:07:02 +02:00
beqid r6 ,3 f
2009-05-26 16:30:23 +02:00
addik r3 ,r6 ,0
1 :
lbu r4 ,r5 ,r0
beqid r4 ,2 f / * b r e a k o n N U L * /
addik r3 ,r3 ,- 1 / * d e l a y s l o t * /
bneid r3 ,1 b
addik r5 ,r5 ,1 / * d e l a y s l o t * /
addik r3 ,r3 ,- 1 / * f o r b r e a k o n l e n * /
2 :
rsubk r3 ,r3 ,r6
3 :
rtsd r15 ,8
nop
2010-03-23 08:09:32 +01:00
.size _ _ strnlen_ u s e r , . - _ _ s t r n l e n _ u s e r
2009-05-26 16:30:23 +02:00
.section .fixup , " ax"
4 :
brid 3 b
addk r3 ,r0 ,r0
.section _ _ ex_ t a b l e ," a "
.word 1 b,4 b
2011-06-10 10:49:08 +02:00
/* Loop unrolling for __copy_tofrom_user */
# define C O P Y ( o f f s e t ) \
1 : lwi r4 , r6 , 0 x00 0 0 + o f f s e t ; \
2 : lwi r19 , r6 , 0 x00 0 4 + o f f s e t ; \
3 : lwi r20 , r6 , 0 x00 0 8 + o f f s e t ; \
4 : lwi r21 , r6 , 0 x00 0 C + o f f s e t ; \
5 : lwi r22 , r6 , 0 x00 1 0 + o f f s e t ; \
6 : lwi r23 , r6 , 0 x00 1 4 + o f f s e t ; \
7 : lwi r24 , r6 , 0 x00 1 8 + o f f s e t ; \
8 : lwi r25 , r6 , 0 x00 1 C + o f f s e t ; \
9 : swi r4 , r5 , 0 x00 0 0 + o f f s e t ; \
10 : swi r19 , r5 , 0 x00 0 4 + o f f s e t ; \
11 : swi r20 , r5 , 0 x00 0 8 + o f f s e t ; \
12 : swi r21 , r5 , 0 x00 0 C + o f f s e t ; \
13 : swi r22 , r5 , 0 x00 1 0 + o f f s e t ; \
14 : swi r23 , r5 , 0 x00 1 4 + o f f s e t ; \
15 : swi r24 , r5 , 0 x00 1 8 + o f f s e t ; \
16 : swi r25 , r5 , 0 x00 1 C + o f f s e t ; \
.section _ _ ex_ t a b l e ," a " ; \
2012-03-30 08:21:38 +02:00
.word 1 b, 3 3 f ; \
.word 2 b, 3 3 f ; \
.word 3 b, 3 3 f ; \
.word 4 b, 3 3 f ; \
.word 5 b, 3 3 f ; \
.word 6 b, 3 3 f ; \
.word 7 b, 3 3 f ; \
.word 8 b, 3 3 f ; \
.word 9 b, 3 3 f ; \
.word 1 0 b, 3 3 f ; \
.word 1 1 b, 3 3 f ; \
.word 1 2 b, 3 3 f ; \
.word 1 3 b, 3 3 f ; \
.word 1 4 b, 3 3 f ; \
.word 1 5 b, 3 3 f ; \
.word 1 6 b, 3 3 f ; \
2011-06-10 10:49:08 +02:00
.text
# define C O P Y _ 8 0 ( o f f s e t ) \
COPY( 0 x00 + o f f s e t ) ;\
COPY( 0 x20 + o f f s e t ) ;\
COPY( 0 x40 + o f f s e t ) ;\
COPY( 0 x60 + o f f s e t ) ;
2009-05-26 16:30:23 +02:00
/ *
* int _ _ c o p y _ t o f r o m _ u s e r ( c h a r * t o , c h a r * f r o m , i n t l e n )
* Return :
* 0 on s u c c e s s
* number o f n o t c o p i e d b y t e s o n e r r o r
* /
.text
.globl _ _ copy_ t o f r o m _ u s e r ;
2010-03-23 08:09:32 +01:00
.type _ _ copy_ t o f r o m _ u s e r , @function
2009-05-26 16:30:23 +02:00
.align 4 ;
__copy_tofrom_user :
/ *
* r5 - t o
* r6 - f r o m
* r7 , r3 - c o u n t
* r4 - t e m p v a l
* /
2011-06-10 11:03:44 +02:00
beqid r7 , 0 f / * z e r o s i z e i s n o t l i k e l y * /
2010-03-22 20:31:26 +01:00
or r3 , r5 , r6 / * f i n d i f i s a n y t o / f r o m u n a l i g n e d * /
2011-06-10 11:08:57 +02:00
or r3 , r3 , r7 / * f i n d i f c o u n t i s u n a l i g n e d * /
andi r3 , r3 , 0 x3 / * m a s k l a s t 3 b i t s * /
bneid r3 , b u 1 / * i f r3 i s n o t z e r o t h e n b y t e c o p y i n g * /
2010-03-22 20:31:26 +01:00
or r3 , r0 , r0
2011-06-10 10:49:08 +02:00
rsubi r3 , r7 , P A G E _ S I Z E / * d e t e c t P A G E _ S I Z E * /
beqid r3 , p a g e ;
or r3 , r0 , r0
2011-06-10 11:07:55 +02:00
w1 : lw r4 , r6 , r3 / * a t l e a s t o n e 4 b y t e c o p y * /
w2 : sw r4 , r5 , r3
2010-03-22 20:31:26 +01:00
addik r7 , r7 , - 4
2011-06-10 11:07:55 +02:00
bneid r7 , w1
2010-03-22 20:31:26 +01:00
addik r3 , r3 , 4
addik r3 , r7 , 0
rtsd r15 , 8
nop
2011-06-10 11:05:45 +02:00
.section _ _ ex_ t a b l e ," a "
2011-06-10 11:07:55 +02:00
.word w1 , 0 f ;
.word w2 , 0 f ;
2011-06-10 11:05:45 +02:00
.text
2011-06-10 10:49:08 +02:00
.align 4 /* Alignment is important to keep icache happy */
page : /* Create room on stack and save registers for storign values */
2012-03-30 08:21:38 +02:00
addik r1 , r1 , - 4 0
swi r5 , r1 , 0
swi r6 , r1 , 4
swi r7 , r1 , 8
swi r19 , r1 , 1 2
swi r20 , r1 , 1 6
swi r21 , r1 , 2 0
swi r22 , r1 , 2 4
swi r23 , r1 , 2 8
swi r24 , r1 , 3 2
swi r25 , r1 , 3 6
2011-06-10 10:49:08 +02:00
loop : /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
/* Loop unrolling to get performance boost */
COPY_ 8 0 ( 0 x00 0 ) ;
COPY_ 8 0 ( 0 x08 0 ) ;
COPY_ 8 0 ( 0 x10 0 ) ;
COPY_ 8 0 ( 0 x18 0 ) ;
/* copy loop */
2012-03-30 08:21:38 +02:00
addik r6 , r6 , 0 x20 0
addik r7 , r7 , - 0 x20 0
bneid r7 , l o o p
addik r5 , r5 , 0 x20 0
2011-06-10 10:49:08 +02:00
/* Restore register content */
2012-03-30 08:21:38 +02:00
lwi r5 , r1 , 0
lwi r6 , r1 , 4
lwi r7 , r1 , 8
lwi r19 , r1 , 1 2
lwi r20 , r1 , 1 6
lwi r21 , r1 , 2 0
lwi r22 , r1 , 2 4
lwi r23 , r1 , 2 8
lwi r24 , r1 , 3 2
lwi r25 , r1 , 3 6
addik r1 , r1 , 4 0
2011-06-10 10:49:08 +02:00
/* return back */
2012-03-30 08:21:38 +02:00
addik r3 , r0 , 0
rtsd r15 , 8
nop
/* Fault case - return temp count */
33 :
2011-06-10 10:49:08 +02:00
addik r3 , r7 , 0
2012-03-30 08:21:38 +02:00
/* Restore register content */
lwi r5 , r1 , 0
lwi r6 , r1 , 4
lwi r7 , r1 , 8
lwi r19 , r1 , 1 2
lwi r20 , r1 , 1 6
lwi r21 , r1 , 2 0
lwi r22 , r1 , 2 4
lwi r23 , r1 , 2 8
lwi r24 , r1 , 3 2
lwi r25 , r1 , 3 6
addik r1 , r1 , 4 0
/* return back */
2011-06-10 10:49:08 +02:00
rtsd r15 , 8
nop
.align 4 /* Alignment is important to keep icache happy */
2011-06-10 11:07:55 +02:00
bu1 : lbu r4 ,r6 ,r3
bu2 : sb r4 ,r5 ,r3
2010-03-22 20:31:26 +01:00
addik r7 ,r7 ,- 1
2011-06-10 11:07:55 +02:00
bneid r7 ,b u 1
2010-03-22 20:31:26 +01:00
addik r3 ,r3 ,1 / * d e l a y s l o t * /
2011-06-10 11:03:44 +02:00
0 :
2010-03-22 20:31:26 +01:00
addik r3 ,r7 ,0
2009-05-26 16:30:23 +02:00
rtsd r15 ,8
nop
2010-03-23 08:09:32 +01:00
.size _ _ copy_ t o f r o m _ u s e r , . - _ _ c o p y _ t o f r o m _ u s e r
2009-05-26 16:30:23 +02:00
.section _ _ ex_ t a b l e ," a "
2011-06-10 11:07:55 +02:00
.word bu1 , 0 b ;
.word bu2 , 0 b ;
2011-06-10 11:05:45 +02:00
.text