2018-12-28 00:32:24 -08:00
/ * SPDX- L i c e n s e - I d e n t i f i e r : G P L - 2 . 0
*
2006-11-05 16:15:19 +09:00
* Copyright ( C ) 1 9 9 9 , 2 0 0 0 , 2 0 0 2 N i i b e Y u t a k a
2008-05-19 19:39:33 +09:00
* Copyright ( C ) 2 0 0 3 - 2 0 0 8 P a u l M u n d t
2006-11-05 16:15:19 +09:00
* /
! NOTE :
! GNU a s ( a s o f 2 . 9 . 1 ) c h a n g e s b f / s i n t o b t / s a n d b r a , w h e n t h e a d d r e s s
! to b e j u m p e d i s t o o f a r , b u t i t c a u s e s i l l e g a l s l o t e x c e p t i o n .
/ *
* entry. S c o n t a i n s t h e s y s t e m - c a l l a n d f a u l t l o w - l e v e l h a n d l i n g r o u t i n e s .
* This a l s o c o n t a i n s t h e t i m e r - i n t e r r u p t h a n d l e r , a s w e l l a s a l l i n t e r r u p t s
* and f a u l t s t h a t c a n r e s u l t i n a t a s k - s w i t c h .
*
* NOTE : This c o d e h a n d l e s s i g n a l - r e c o g n i t i o n , w h i c h h a p p e n s e v e r y t i m e
* after a t i m e r - i n t e r r u p t a n d a f t e r e a c h s y s t e m c a l l .
*
* NOTE : This c o d e u s e s a c o n v e n t i o n t h a t i n s t r u c t i o n s i n t h e d e l a y s l o t
* of a t r a n s f e r - c o n t r o l i n s t r u c t i o n a r e i n d e n t e d b y a n e x t r a s p a c e , t h u s :
*
* jmp @k0 ! control-transfer instruction
* ldc k 1 , s s r ! d e l a y s l o t
*
* Stack l a y o u t i n ' r e t _ f r o m _ s y s c a l l ' :
* ptrace n e e d s t o h a v e a l l r e g s o n t h e s t a c k .
* if t h e o r d e r h e r e i s c h a n g e d , i t n e e d s t o b e
* updated i n p t r a c e . c a n d p t r a c e . h
*
* r0
* . . .
* r1 5 = s t a c k p o i n t e r
* spc
* pr
* ssr
* gbr
* mach
* macl
* syscall #
*
* /
2009-08-02 22:40:11 +01:00
# include < a s m / d w a r f . h >
2006-11-05 16:15:19 +09:00
2019-10-15 21:18:05 +02:00
# if d e f i n e d ( C O N F I G _ P R E E M P T I O N )
2009-07-29 23:01:24 +09:00
# define p r e e m p t _ s t o p ( ) c l i ; TRACE_IRQS_OFF
2006-11-05 16:15:19 +09:00
# else
# define p r e e m p t _ s t o p ( )
# define r e s u m e _ k e r n e l _ _ r e s t o r e _ a l l
# endif
.align 2
ENTRY( e x c e p t i o n _ e r r o r )
!
2009-07-29 23:01:24 +09:00
TRACE_ I R Q S _ O N
2006-11-05 16:15:19 +09:00
sti
2006-12-13 17:40:05 +09:00
mov. l 1 f , r0
2006-11-05 16:15:19 +09:00
jmp @r0
nop
.align 2
2006-12-13 17:40:05 +09:00
1 : .long d o _ e x c e p t i o n _ e r r o r
2006-11-05 16:15:19 +09:00
.align 2
ret_from_exception :
2009-08-02 22:40:11 +01:00
CFI_ S T A R T P R O C s i m p l e
CFI_ D E F _ C F A r14 , 0
CFI_ R E L _ O F F S E T 1 7 , 6 4
2010-01-27 20:05:20 +00:00
CFI_ R E L _ O F F S E T 1 5 , 6 0
2009-08-02 22:40:11 +01:00
CFI_ R E L _ O F F S E T 1 4 , 5 6
2010-01-27 20:05:20 +00:00
CFI_ R E L _ O F F S E T 1 3 , 5 2
CFI_ R E L _ O F F S E T 1 2 , 4 8
CFI_ R E L _ O F F S E T 1 1 , 4 4
CFI_ R E L _ O F F S E T 1 0 , 4 0
CFI_ R E L _ O F F S E T 9 , 3 6
CFI_ R E L _ O F F S E T 8 , 3 2
2006-11-05 16:15:19 +09:00
preempt_ s t o p ( )
ENTRY( r e t _ f r o m _ i r q )
!
mov #O F F _ S R , r 0
mov. l @(r0,r15), r0 ! get status register
shll r0
shll r0 ! k e r n e l s p a c e ?
get_ c u r r e n t _ t h r e a d _ i n f o r8 , r0
bt r e s u m e _ k e r n e l ! Y e s , i t ' s f r o m k e r n e l , g o b a c k s o o n
2019-10-15 21:18:05 +02:00
# ifdef C O N F I G _ P R E E M P T I O N
2006-11-05 16:15:19 +09:00
bra r e s u m e _ u s e r s p a c e
nop
ENTRY( r e s u m e _ k e r n e l )
2008-09-05 14:42:16 +09:00
cli
2009-08-18 11:35:09 +09:00
TRACE_ I R Q S _ O F F
2006-11-05 16:15:19 +09:00
mov. l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
tst r0 , r0
bf n o r e s c h e d
need_resched :
mov. l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_ T I F _ N E E D _ R E S C H E D , r 0 ! n e e d _ r e s c h e d s e t ?
bt n o r e s c h e d
mov #O F F _ S R , r 0
mov. l @(r0,r15), r0 ! get status register
2009-08-24 17:09:53 +09:00
shlr r0
and #( 0xf0 > > 1 ) , r0 ! i n t e r r u p t s o f f ( e x c e p t i o n p a t h ) ?
cmp/ e q #( 0xf0 > > 1 ) , r0
2006-11-05 16:15:19 +09:00
bt n o r e s c h e d
2013-09-17 18:53:09 +00:00
mov. l 1 f , r0
2008-09-05 14:42:16 +09:00
jsr @r0 ! call preempt_schedule_irq
2006-12-04 18:17:28 +09:00
nop
2006-11-05 16:15:19 +09:00
bra n e e d _ r e s c h e d
nop
2006-12-04 18:17:28 +09:00
2006-11-05 16:15:19 +09:00
noresched :
bra _ _ r e s t o r e _ a l l
nop
.align 2
2013-09-17 18:53:09 +00:00
1 : .long p r e e m p t _ s c h e d u l e _ i r q
2006-11-05 16:15:19 +09:00
# endif
ENTRY( r e s u m e _ u s e r s p a c e )
! r8 : current_ t h r e a d _ i n f o
cli
2009-10-14 15:50:28 +09:00
TRACE_ I R Q S _ O F F
2006-11-05 16:15:19 +09:00
mov. l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
2009-07-06 20:16:33 +09:00
tst #( _ T I F _ W O R K _ M A S K & 0xff ) , r0
2006-11-05 16:15:19 +09:00
bt/ s _ _ r e s t o r e _ a l l
tst #_ T I F _ N E E D _ R E S C H E D , r 0
.align 2
work_pending :
! r0 : current_ t h r e a d _ i n f o - > f l a g s
! r8 : current_ t h r e a d _ i n f o
! t : result o f " t s t #_ T I F _ N E E D _ R E S C H E D , r 0 "
bf/ s w o r k _ r e s c h e d
2012-09-18 17:04:37 +09:00
tst #( _ T I F _ S I G P E N D I N G | _ T I F _ N O T I F Y _ R E S U M E ) , r 0
2006-11-05 16:15:19 +09:00
work_notifysig :
bt/ s _ _ r e s t o r e _ a l l
mov r15 , r4
mov r12 , r5 ! s e t a r g 1 ( s a v e _ r0 )
mov r0 , r6
2012-01-10 16:30:37 +09:00
sti
2006-11-05 16:15:19 +09:00
mov. l 2 f , r1
mov. l 3 f , r0
jmp @r1
lds r0 , p r
work_resched :
mov. l 1 f , r1
jsr @r1 ! schedule
nop
cli
2009-07-29 23:01:24 +09:00
TRACE_ I R Q S _ O F F
2006-11-05 16:15:19 +09:00
!
mov. l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
2009-07-06 20:16:33 +09:00
tst #( _ T I F _ W O R K _ M A S K & 0xff ) , r0
2006-11-05 16:15:19 +09:00
bt _ _ r e s t o r e _ a l l
bra w o r k _ p e n d i n g
tst #_ T I F _ N E E D _ R E S C H E D , r 0
.align 2
1 : .long s c h e d u l e
2 : .long d o _ n o t i f y _ r e s u m e
2008-07-17 13:08:40 +01:00
3 : .long r e s u m e _ u s e r s p a c e
2006-11-05 16:15:19 +09:00
.align 2
syscall_exit_work :
! r0 : current_ t h r e a d _ i n f o - > f l a g s
! r8 : current_ t h r e a d _ i n f o
2009-07-06 20:16:33 +09:00
tst #( _ T I F _ W O R K _ S Y S C A L L _ M A S K & 0xff ) , r0
2006-11-05 16:15:19 +09:00
bt/ s w o r k _ p e n d i n g
tst #_ T I F _ N E E D _ R E S C H E D , r 0
2009-07-29 23:01:24 +09:00
TRACE_ I R Q S _ O N
2006-11-05 16:15:19 +09:00
sti
2007-11-10 19:21:34 +09:00
mov r15 , r4
2008-07-30 19:55:30 +09:00
mov. l 8 f , r0 ! d o _ s y s c a l l _ t r a c e _ l e a v e
2006-11-05 16:15:19 +09:00
jsr @r0
nop
bra r e s u m e _ u s e r s p a c e
nop
__restore_all :
2009-08-18 11:35:09 +09:00
mov #O F F _ S R , r 0
mov. l @(r0,r15), r0 ! get status register
shlr2 r0
and #0x3c , r0
cmp/ e q #0x3c , r0
bt 1 f
TRACE_ I R Q S _ O N
bra 2 f
nop
1 :
TRACE_ I R Q S _ O F F
2 :
mov. l 3 f , r0
2006-11-05 16:15:19 +09:00
jmp @r0
nop
.align 2
2009-08-18 11:35:09 +09:00
3 : .long r e s t o r e _ a l l
2006-11-05 16:15:19 +09:00
2006-11-24 13:01:36 +09:00
.align 2
syscall_badsys : ! Bad s y s c a l l n u m b e r
2008-05-15 13:30:05 +09:00
get_ c u r r e n t _ t h r e a d _ i n f o r8 , r0
2006-11-24 13:01:36 +09:00
mov #- E N O S Y S , r 0
bra r e s u m e _ u s e r s p a c e
mov. l r0 , @(OFF_R0,r15) ! Return value
2006-12-13 17:40:05 +09:00
/ *
* The m a i n d e b u g t r a p h a n d l e r .
*
* r8 =TRA ( n o t t h e t r a p n u m b e r ! )
*
* Note : This a s s u m e s t h a t t h e t r a p a v a l u e i s l e f t i n i t s o r i g i n a l
* form ( w i t h o u t t h e s h l r2 s h i f t ) s o t h e c a l c u l a t i o n f o r t h e j u m p
* call t a b l e o f f s e t r e m a i n s a s i m p l e i n p l a c e m a s k .
* /
debug_trap :
mov r8 , r0
and #( 0xf < < 2 ) , r0
mov. l 1 f , r8
add r0 , r8
mov. l @r8, r8
2008-05-19 19:39:33 +09:00
jsr @r8
nop
2018-03-15 20:01:36 -04:00
bra r e t _ f r o m _ e x c e p t i o n
2006-12-13 17:40:05 +09:00
nop
2009-08-02 22:40:11 +01:00
CFI_ E N D P R O C
2006-12-13 17:40:05 +09:00
.align 2
1 : .long d e b u g _ t r a p _ t a b l e
2006-11-24 13:01:36 +09:00
2006-11-05 16:15:19 +09:00
/ *
* Syscall i n t e r f a c e :
*
* Syscall #: R 3
* Arguments #0 t o #3 : R 4 - - R 7
* Arguments #4 t o #6 : R 0 , R 1 , R 2
sh: provide unified syscall trap compatible with all SH models
Historically SH-2 Linux (and originally uClinux) used a syscall
calling convention incompatible with the established SH-3/4 Linux ABI.
This choice was made because the trap range used by the existing ABI,
0x10-0x17, overlaps with the hardware exception/interrupt trap range
reserved by SH-2, and in particular, with the SH-2A divide-by-zero and
division-overflow exceptions.
Despite the documented syscall convention using the low bits of the
trap number to signal the number of arguments the kernel should
expect, no version of the kernel has ever used this information, nor
is it useful; all of the registers need to be saved anyway. Therefore,
it is possible to pick a new trap number, 0x1f, that is both supported
by all existing SH-3/4 kernels and unassigned as a hardware trap in
the SH-2 range. This makes it possible to produce SH-2 application
binaries that are forwards-compatible with running on SH-3/4 kernels
and to treat SH as a unified platform with varying ISA support levels
rather than multiple gratuitously-incompatible platforms.
This patch adjusts the range checking SH-2 and SH-2A kernels make for
the syscall trap to accept the range 0x1f-0x2f rather than just
0x20-0x2f. As a result, trap 0x1f now acts as a syscall for all SH
models.
Signed-off-by: Rich Felker <dalias@libc.org>
2015-12-17 01:04:25 +00:00
* TRA : See f o l l o w i n g t a b l e .
2006-11-05 16:15:19 +09:00
*
2006-12-13 17:40:05 +09:00
* ( TRA> > 2 ) P u r p o s e
* - - - - - - - - - - - - - - -
* 0 x0 0 - 0 x0 f o r i g i n a l S H - 3 / 4 s y s c a l l A B I ( n o t i n g e n e r a l u s e ) .
* 0 x1 0 - 0 x1 f g e n e r a l S H - 3 / 4 s y s c a l l A B I .
sh: provide unified syscall trap compatible with all SH models
Historically SH-2 Linux (and originally uClinux) used a syscall
calling convention incompatible with the established SH-3/4 Linux ABI.
This choice was made because the trap range used by the existing ABI,
0x10-0x17, overlaps with the hardware exception/interrupt trap range
reserved by SH-2, and in particular, with the SH-2A divide-by-zero and
division-overflow exceptions.
Despite the documented syscall convention using the low bits of the
trap number to signal the number of arguments the kernel should
expect, no version of the kernel has ever used this information, nor
is it useful; all of the registers need to be saved anyway. Therefore,
it is possible to pick a new trap number, 0x1f, that is both supported
by all existing SH-3/4 kernels and unassigned as a hardware trap in
the SH-2 range. This makes it possible to produce SH-2 application
binaries that are forwards-compatible with running on SH-3/4 kernels
and to treat SH as a unified platform with varying ISA support levels
rather than multiple gratuitously-incompatible platforms.
This patch adjusts the range checking SH-2 and SH-2A kernels make for
the syscall trap to accept the range 0x1f-0x2f rather than just
0x20-0x2f. As a result, trap 0x1f now acts as a syscall for all SH
models.
Signed-off-by: Rich Felker <dalias@libc.org>
2015-12-17 01:04:25 +00:00
* 0 x1 f u n i f i e d S H - 2 / 3 / 4 s y s c a l l A B I ( p r e f e r r e d ) .
* 0 x2 0 - 0 x2 f o r i g i n a l S H - 2 s y s c a l l A B I .
2006-12-13 17:40:05 +09:00
* 0 x3 0 - 0 x3 f d e b u g t r a p s u s e d b y t h e k e r n e l .
* 0 x4 0 - 0 x f f N o t s u p p o r t e d b y a l l p a r t s , s o l e f t u n h a n d l e d .
2006-11-05 16:15:19 +09:00
*
sh: provide unified syscall trap compatible with all SH models
Historically SH-2 Linux (and originally uClinux) used a syscall
calling convention incompatible with the established SH-3/4 Linux ABI.
This choice was made because the trap range used by the existing ABI,
0x10-0x17, overlaps with the hardware exception/interrupt trap range
reserved by SH-2, and in particular, with the SH-2A divide-by-zero and
division-overflow exceptions.
Despite the documented syscall convention using the low bits of the
trap number to signal the number of arguments the kernel should
expect, no version of the kernel has ever used this information, nor
is it useful; all of the registers need to be saved anyway. Therefore,
it is possible to pick a new trap number, 0x1f, that is both supported
by all existing SH-3/4 kernels and unassigned as a hardware trap in
the SH-2 range. This makes it possible to produce SH-2 application
binaries that are forwards-compatible with running on SH-3/4 kernels
and to treat SH as a unified platform with varying ISA support levels
rather than multiple gratuitously-incompatible platforms.
This patch adjusts the range checking SH-2 and SH-2A kernels make for
the syscall trap to accept the range 0x1f-0x2f rather than just
0x20-0x2f. As a result, trap 0x1f now acts as a syscall for all SH
models.
Signed-off-by: Rich Felker <dalias@libc.org>
2015-12-17 01:04:25 +00:00
* For m a k i n g s y s t e m c a l l s , a n y t r a p n u m b e r i n t h e r a n g e f o r t h e
* given c p u m o d e l m a y b e u s e d , b u t t h e u n i f i e d t r a p n u m b e r 0 x1 f i s
* preferred f o r c o m p a t i b i l i t y w i t h a l l m o d e l s .
*
* The l o w b i t s o f t h e t r a p n u m b e r w e r e o n c e d o c u m e n t e d a s m a t c h i n g
* the n u m b e r o f a r g u m e n t s , b u t t h e y w e r e n e v e r a c t u a l l y u s e d a s s u c h
* by t h e k e r n e l . S H - 2 o r i g i n a l l y u s e d i t s o w n s e p a r a t e t r a p r a n g e
* because s e v e r a l h a r d w a r e e x c e p t i o n s f e l l i n t h e r a n g e u s e d f o r t h e
* SH- 3 / 4 s y s c a l l A B I .
*
* This c o d e a l s o h a n d l e s d e l e g a t i n g o t h e r t r a p s t o t h e B I O S / g d b s t u b .
*
2006-11-05 16:15:19 +09:00
* Note : When w e ' r e f i r s t c a l l e d , t h e T R A v a l u e m u s t b e s h i f t e d
* right 2 b i t s i n o r d e r t o g e t t h e v a l u e t h a t w a s u s e d a s t h e " t r a p a "
* argument.
* /
.align 2
.globl ret_from_fork
ret_from_fork :
mov. l 1 f , r8
jsr @r8
mov r0 , r4
bra s y s c a l l _ e x i t
nop
2012-10-14 01:41:42 -04:00
.align 2
.globl ret_from_kernel_thread
ret_from_kernel_thread :
mov. l 1 f , r8
jsr @r8
mov r0 , r4
mov. l @(OFF_R5,r15), r5 ! fn
jsr @r5
mov. l @(OFF_R4,r15), r4 ! arg
bra s y s c a l l _ e x i t
nop
2006-11-05 16:15:19 +09:00
.align 2
1 : .long s c h e d u l e _ t a i l
2006-12-13 17:40:05 +09:00
/ *
* The p o o r l y n a m e d m a i n t r a p a d e c o d e a n d d i s p a t c h r o u t i n e , f o r
* system c a l l s a n d d e b u g t r a p s t h r o u g h t h e i r r e s p e c t i v e j u m p t a b l e s .
* /
2006-11-05 16:15:19 +09:00
ENTRY( s y s t e m _ c a l l )
2009-08-02 22:33:26 +01:00
setup_ f r a m e _ r e g
2006-11-05 16:15:19 +09:00
# if ! d e f i n e d ( C O N F I G _ C P U _ S H 2 )
mov. l 1 f , r9
mov. l @r9, r8 ! Read from TRA (Trap Address) Register
# endif
2008-12-11 18:46:46 +09:00
mov #O F F _ T R A , r 10
add r15 , r10
mov. l r8 , @r10 ! set TRA value to tra
2006-12-13 17:40:05 +09:00
/ *
* Check t h e t r a p t y p e
* /
mov #( ( 0x20 < < 2 ) - 1 ) , r9
2006-11-05 16:15:19 +09:00
cmp/ h i r9 , r8
2006-12-13 17:40:05 +09:00
bt/ s d e b u g _ t r a p ! i t ' s a d e b u g t r a p . .
2008-12-11 18:46:46 +09:00
nop
2009-07-29 23:01:24 +09:00
TRACE_ I R Q S _ O N
2006-11-05 16:15:19 +09:00
sti
2006-12-04 18:17:28 +09:00
2006-11-05 16:15:19 +09:00
!
2006-11-24 13:01:36 +09:00
get_ c u r r e n t _ t h r e a d _ i n f o r8 , r10
2006-11-05 16:15:19 +09:00
mov. l @(TI_FLAGS,r8), r8
2009-07-06 20:16:33 +09:00
mov #( _ T I F _ W O R K _ S Y S C A L L _ M A S K & 0xff ) , r10
mov #( _ T I F _ W O R K _ S Y S C A L L _ M A S K > > 8 ) , r9
2006-11-05 16:15:19 +09:00
tst r10 , r8
2009-07-06 20:16:33 +09:00
shll8 r9
bf s y s c a l l _ t r a c e _ e n t r y
tst r9 , r8
2006-11-05 16:15:19 +09:00
bf s y s c a l l _ t r a c e _ e n t r y
!
2020-07-23 01:13:19 +02:00
mov. l 6 f , r8 ! N u m b e r o f s y s c a l l s
2006-11-24 13:01:36 +09:00
cmp/ h s r8 , r3
bt s y s c a l l _ b a d s y s
!
2006-11-05 16:15:19 +09:00
syscall_call :
2006-11-24 13:01:36 +09:00
shll2 r3 ! x4
2006-11-05 16:15:19 +09:00
mov. l 3 f , r8 ! L o a d t h e a d d r e s s o f s y s _ c a l l _ t a b l e
2006-11-24 13:01:36 +09:00
add r8 , r3
mov. l @r3, r8
sh: push extra copy of r0-r2 for syscall parameters
When invoking syscall handlers on sh32, the saved userspace registers
are at the top of the stack. This seems to have been intentional, as it
is an easy way to pass r0, r1, ... to the handler as parameters 5, 6,
...
It causes problems, however, because the compiler is allowed to generate
code for a function which clobbers that function's own parameters. For
example, gcc generates the following code for clone:
<SyS_clone>:
mov.l 8c020714 <SyS_clone+0xc>,r1 ! 8c020540 <do_fork>
mov.l r7,@r15
mov r6,r7
jmp @r1
mov #0,r6
nop
.word 0x0540
.word 0x8c02
The `mov.l r7,@r15` clobbers the saved value of r0 passed from
userspace. For most system calls, this might not be a problem, because
we'll be overwriting r0 with the return value anyway. But in the case
of clone, copy_thread will need the original value of r0 if the
CLONE_SETTLS flag was specified.
The first patch in this series fixes this issue for system calls by
pushing to the stack and extra copy of r0-r2 before invoking the
handler. We discard this copy before restoring the userspace registers,
so it is not a problem if they are clobbered.
Exception handlers also receive the userspace register values in a
similar manner, and may hit the same problem. The second patch removes
the do_fpu_error handler, which looks susceptible to this problem and
which, as far as I can tell, has not been used in some time. The third
patch addresses other exception handlers.
This patch (of 3):
The userspace registers are stored at the top of the stack when the
syscall handler is invoked, which allows r0-r2 to act as parameters 5-7.
Parameters passed on the stack may be clobbered by the syscall handler.
The solution is to push an extra copy of the registers which might be
used as syscall parameters to the stack, so that the authoritative set
of saved register values does not get clobbered.
A few system call handlers are also updated to get the userspace
registers using current_pt_regs() instead of from the stack.
Signed-off-by: Bobby Bingham <koorogi@koorogi.info>
Cc: Paul Mundt <paul.mundt@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2014-04-03 14:46:39 -07:00
mov. l @(OFF_R2,r15), r2
mov. l @(OFF_R1,r15), r1
mov. l @(OFF_R0,r15), r0
mov. l r2 , @-r15
mov. l r1 , @-r15
mov. l r0 , @-r15
2006-11-05 16:15:19 +09:00
jsr @r8 ! jump to specific syscall handler
nop
sh: push extra copy of r0-r2 for syscall parameters
When invoking syscall handlers on sh32, the saved userspace registers
are at the top of the stack. This seems to have been intentional, as it
is an easy way to pass r0, r1, ... to the handler as parameters 5, 6,
...
It causes problems, however, because the compiler is allowed to generate
code for a function which clobbers that function's own parameters. For
example, gcc generates the following code for clone:
<SyS_clone>:
mov.l 8c020714 <SyS_clone+0xc>,r1 ! 8c020540 <do_fork>
mov.l r7,@r15
mov r6,r7
jmp @r1
mov #0,r6
nop
.word 0x0540
.word 0x8c02
The `mov.l r7,@r15` clobbers the saved value of r0 passed from
userspace. For most system calls, this might not be a problem, because
we'll be overwriting r0 with the return value anyway. But in the case
of clone, copy_thread will need the original value of r0 if the
CLONE_SETTLS flag was specified.
The first patch in this series fixes this issue for system calls by
pushing to the stack and extra copy of r0-r2 before invoking the
handler. We discard this copy before restoring the userspace registers,
so it is not a problem if they are clobbered.
Exception handlers also receive the userspace register values in a
similar manner, and may hit the same problem. The second patch removes
the do_fpu_error handler, which looks susceptible to this problem and
which, as far as I can tell, has not been used in some time. The third
patch addresses other exception handlers.
This patch (of 3):
The userspace registers are stored at the top of the stack when the
syscall handler is invoked, which allows r0-r2 to act as parameters 5-7.
Parameters passed on the stack may be clobbered by the syscall handler.
The solution is to push an extra copy of the registers which might be
used as syscall parameters to the stack, so that the authoritative set
of saved register values does not get clobbered.
A few system call handlers are also updated to get the userspace
registers using current_pt_regs() instead of from the stack.
Signed-off-by: Bobby Bingham <koorogi@koorogi.info>
Cc: Paul Mundt <paul.mundt@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2014-04-03 14:46:39 -07:00
add #12 , r15
2006-11-05 16:15:19 +09:00
mov. l @(OFF_R0,r15), r12 ! save r0
mov. l r0 , @(OFF_R0,r15) ! save the return value
!
syscall_exit :
cli
2009-07-29 23:01:24 +09:00
TRACE_ I R Q S _ O F F
2006-11-05 16:15:19 +09:00
!
get_ c u r r e n t _ t h r e a d _ i n f o r8 , r0
mov. l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
2009-07-06 20:16:33 +09:00
tst #( _ T I F _ A L L W O R K _ M A S K & 0xff ) , r0
mov #( _ T I F _ A L L W O R K _ M A S K > > 8 ) , r1
bf s y s c a l l _ e x i t _ w o r k
shlr8 r0
tst r0 , r1
2006-11-05 16:15:19 +09:00
bf s y s c a l l _ e x i t _ w o r k
bra _ _ r e s t o r e _ a l l
nop
2020-07-23 01:13:20 +02:00
.align 2
syscall_trace_entry :
! Yes i t i s t r a c e d .
mov r15 , r4
mov. l 7 f , r11 ! C a l l d o _ s y s c a l l _ t r a c e _ e n t e r w h i c h n o t i f i e s
jsr @r11 ! superior (will chomp R[0-7])
nop
2020-07-23 01:13:21 +02:00
cmp/ e q #- 1 , r0
bt s y s c a l l _ e x i t
2020-07-23 01:13:20 +02:00
! Reload R 0 - R 4 f r o m k e r n e l s t a c k , w h e r e t h e
! parent m a y h a v e m o d i f i e d t h e m u s i n g
! ptrace( P O K E U S R ) . ( N o t e t h a t R 0 - R 2 a r e
! reloaded f r o m t h e k e r n e l s t a c k b y s y s c a l l _ c a l l
! below, s o d o n ' t n e e d t o b e r e l o a d e d h e r e . )
! This a l l o w s t h e p a r e n t t o r e w r i t e s y s t e m c a l l s
! and a r g s o n t h e f l y .
mov. l @(OFF_R4,r15), r4 ! arg0
mov. l @(OFF_R5,r15), r5
mov. l @(OFF_R6,r15), r6
mov. l @(OFF_R7,r15), r7 ! arg3
mov. l @(OFF_R3,r15), r3 ! syscall_nr
!
mov. l 6 f , r10 ! N u m b e r o f s y s c a l l s
cmp/ h s r10 , r3
bf s y s c a l l _ c a l l
mov #- E N O S Y S , r 0
bra s y s c a l l _ e x i t
mov. l r0 , @(OFF_R0,r15) ! Return value
2006-11-05 16:15:19 +09:00
.align 2
# if ! d e f i n e d ( C O N F I G _ C P U _ S H 2 )
1 : .long T R A
# endif
2020-07-23 01:13:19 +02:00
6 : .long N R _ s y s c a l l s
2006-11-05 16:15:19 +09:00
3 : .long s y s _ c a l l _ t a b l e
2008-07-30 19:55:30 +09:00
7 : .long d o _ s y s c a l l _ t r a c e _ e n t e r
8 : .long d o _ s y s c a l l _ t r a c e _ l e a v e