2008-05-19 14:39:33 +04:00
/ *
2006-11-05 10:15:19 +03: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 14:39:33 +04:00
* Copyright ( C ) 2 0 0 3 - 2 0 0 8 P a u l M u n d t
2006-11-05 10:15:19 +03:00
*
* 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 .
*
* /
! 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-03 01:40:11 +04:00
# include < a s m / d w a r f . h >
2006-11-05 10:15:19 +03:00
# if d e f i n e d ( C O N F I G _ P R E E M P T )
2009-07-29 18:01:24 +04:00
# define p r e e m p t _ s t o p ( ) c l i ; TRACE_IRQS_OFF
2006-11-05 10:15:19 +03: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 18:01:24 +04:00
TRACE_ I R Q S _ O N
2006-11-05 10:15:19 +03:00
sti
2006-12-13 11:40:05 +03:00
mov. l 1 f , r0
2006-11-05 10:15:19 +03:00
jmp @r0
nop
.align 2
2006-12-13 11:40:05 +03:00
1 : .long d o _ e x c e p t i o n _ e r r o r
2006-11-05 10:15:19 +03:00
.align 2
ret_from_exception :
2009-08-03 01:40:11 +04: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 23:05:20 +03:00
CFI_ R E L _ O F F S E T 1 5 , 6 0
2009-08-03 01:40:11 +04:00
CFI_ R E L _ O F F S E T 1 4 , 5 6
2010-01-27 23:05:20 +03: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 10:15:19 +03: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
# ifdef C O N F I G _ P R E E M P T
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 09:42:16 +04:00
cli
2009-08-18 06:35:09 +04:00
TRACE_ I R Q S _ O F F
2006-11-05 10:15:19 +03: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 12:09:53 +04: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 10:15:19 +03:00
bt n o r e s c h e d
2006-12-04 12:17:28 +03:00
mov. l 3 f , r0
2008-09-05 09:42:16 +04:00
jsr @r0 ! call preempt_schedule_irq
2006-12-04 12:17:28 +03:00
nop
2006-11-05 10:15:19 +03:00
bra n e e d _ r e s c h e d
nop
2006-12-04 12:17:28 +03:00
2006-11-05 10:15:19 +03:00
noresched :
bra _ _ r e s t o r e _ a l l
nop
.align 2
1 : .long P R E E M P T _ A C T I V E
2 : .long s c h e d u l e
2008-09-05 09:42:16 +04:00
3 : .long p r e e m p t _ s c h e d u l e _ i r q
2006-11-05 10:15:19 +03: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 10:50:28 +04:00
TRACE_ I R Q S _ O F F
2006-11-05 10:15:19 +03:00
mov. l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
2009-07-06 15:16:33 +04:00
tst #( _ T I F _ W O R K _ M A S K & 0xff ) , r0
2006-11-05 10:15:19 +03: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
2009-10-14 11:05:42 +04:00
tst #_ T I F _ S I G P E N D I N G , r 0
2006-11-05 10:15:19 +03: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
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 18:01:24 +04:00
TRACE_ I R Q S _ O F F
2006-11-05 10:15:19 +03:00
!
mov. l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
2009-07-06 15:16:33 +04:00
tst #( _ T I F _ W O R K _ M A S K & 0xff ) , r0
2006-11-05 10:15:19 +03: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 16:08:40 +04:00
3 : .long r e s u m e _ u s e r s p a c e
2006-11-05 10:15:19 +03: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 15:16:33 +04: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 10:15:19 +03: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 18:01:24 +04:00
TRACE_ I R Q S _ O N
2006-11-05 10:15:19 +03:00
sti
2007-11-10 13:21:34 +03:00
mov r15 , r4
2008-07-30 14:55:30 +04: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 10:15:19 +03:00
jsr @r0
nop
bra r e s u m e _ u s e r s p a c e
nop
.align 2
syscall_trace_entry :
! Yes i t i s t r a c e d .
2007-11-10 13:21:34 +03:00
mov r15 , r4
2008-07-30 14:55:30 +04:00
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
2006-11-05 10:15:19 +03:00
jsr @r11 ! superior (will chomp R[0-7])
nop
2008-07-30 14:55:30 +04:00
mov. l r0 , @(OFF_R0,r15) ! Save return value
2006-11-05 10:15:19 +03: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
! used b y t h e s y s t e m c a l l h a n d l e r d i r e c t l y
! from t h e k e r n e l s t a c k a n y w a y , s o d o n ' t n e e d
! to b e r e l o a d e d h e r e . ) T h i s a l l o w s t h e p a r e n t
! to r e w r i t e s y s t e m c a l l s a n d 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
2006-11-24 07:01:36 +03:00
!
2006-11-05 10:15:19 +03:00
mov. l 2 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
__restore_all :
2009-08-18 06:35:09 +04: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 10:15:19 +03:00
jmp @r0
nop
.align 2
2009-08-18 06:35:09 +04:00
3 : .long r e s t o r e _ a l l
2006-11-05 10:15:19 +03:00
2006-11-24 07:01:36 +03:00
.align 2
syscall_badsys : ! Bad s y s c a l l n u m b e r
2008-05-15 08:30:05 +04:00
get_ c u r r e n t _ t h r e a d _ i n f o r8 , r0
2006-11-24 07:01:36 +03: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 11:40:05 +03: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 14:39:33 +04:00
jsr @r8
nop
bra _ _ r e s t o r e _ a l l
2006-12-13 11:40:05 +03:00
nop
2009-08-03 01:40:11 +04:00
CFI_ E N D P R O C
2006-12-13 11:40:05 +03:00
.align 2
1 : .long d e b u g _ t r a p _ t a b l e
2006-11-24 07:01:36 +03:00
2006-11-05 10:15:19 +03: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
2006-12-13 11:40:05 +03:00
* TRA : ( number o f a r g u m e n t s + A B I r e v i s i o n ) x 4
2006-11-05 10:15:19 +03:00
*
* 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
* according t o :
*
* Trap n u m b e r
2006-12-13 11:40:05 +03: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 .
* 0 x2 0 - 0 x2 f s y s c a l l A B I f o r S H - 2 p a r t s .
* 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 10:15:19 +03: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
.align 2
1 : .long s c h e d u l e _ t a i l
2006-12-13 11:40:05 +03: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 10:15:19 +03:00
ENTRY( s y s t e m _ c a l l )
2009-08-03 01:33:26 +04:00
setup_ f r a m e _ r e g
2006-11-05 10:15:19 +03: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 12:46:46 +03: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 11:40:05 +03:00
/ *
* Check t h e t r a p t y p e
* /
mov #( ( 0x20 < < 2 ) - 1 ) , r9
2006-11-05 10:15:19 +03:00
cmp/ h i r9 , r8
2006-12-13 11:40:05 +03: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 12:46:46 +03:00
nop
2009-07-29 18:01:24 +04:00
TRACE_ I R Q S _ O N
2006-11-05 10:15:19 +03:00
sti
2006-12-04 12:17:28 +03:00
2006-11-05 10:15:19 +03:00
!
2006-11-24 07:01:36 +03:00
get_ c u r r e n t _ t h r e a d _ i n f o r8 , r10
2006-11-05 10:15:19 +03:00
mov. l @(TI_FLAGS,r8), r8
2009-07-06 15:16:33 +04: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 10:15:19 +03:00
tst r10 , r8
2009-07-06 15:16:33 +04: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 10:15:19 +03:00
bf s y s c a l l _ t r a c e _ e n t r y
!
2006-11-24 07:01:36 +03:00
mov. l 2 f , r8 ! N u m b e r o f s y s c a l l s
cmp/ h s r8 , r3
bt s y s c a l l _ b a d s y s
!
2006-11-05 10:15:19 +03:00
syscall_call :
2006-11-24 07:01:36 +03:00
shll2 r3 ! x4
2006-11-05 10:15:19 +03: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 07:01:36 +03:00
add r8 , r3
mov. l @r3, r8
2006-11-05 10:15:19 +03:00
jsr @r8 ! jump to specific syscall handler
nop
mov. l @(OFF_R0,r15), r12 ! save r0
mov. l r0 , @(OFF_R0,r15) ! save the return value
!
syscall_exit :
cli
2009-07-29 18:01:24 +04:00
TRACE_ I R Q S _ O F F
2006-11-05 10:15:19 +03: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 15:16:33 +04: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 10:15:19 +03: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
.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
2 : .long N R _ s y s c a l l s
3 : .long s y s _ c a l l _ t a b l e
2008-07-30 14:55:30 +04: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