2012-05-09 11:05:24 +04:00
/ * - * - mode : asm - * -
*
* linux/ a r c h / m 6 8 k / k e r n e l / e n t r y . S
*
* Copyright ( C ) 1 9 9 1 , 1 9 9 2 L i n u s T o r v a l d s
*
* 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 R E A D M E . l e g a l 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 .
*
* Linux/ m 6 8 k s u p p o r t b y H a m i s h M a c d o n a l d
*
* 6 8 0 6 0 fixes b y J e s p e r S k o v
*
* /
/ *
* 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 .
*
* /
/ *
* 1 2 / 0 3 / 9 6 Jes : Currently w e o n l y s u p p o r t m 6 8 k s i n g l e - c p u s y s t e m s , s o
* all p o i n t e r s t h a t u s e d t o b e ' c u r r e n t ' a r e n o w e n t r y
* number 0 i n t h e ' c u r r e n t _ s e t ' l i s t .
*
* 6 / 0 5 / 0 0 RZ : addedd w r i t e b a c k c o m p l e t i o n a f t e r r e t u r n f r o m s i g h a n d l e r
* for 6 8 0 4 0
* /
# include < l i n u x / l i n k a g e . h >
# include < a s m / e r r n o . h >
# include < a s m / s e t u p . h >
# include < a s m / s e g m e n t . h >
# include < a s m / t r a p s . h >
# include < a s m / u n i s t d . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / e n t r y . h >
.globl system_ c a l l , b u s e r r , t r a p , r e s u m e
.globl sys_call_table
2012-10-22 00:41:46 +04:00
.globl _ _ sys_ f o r k , _ _ s y s _ c l o n e , _ _ s y s _ v f o r k
2013-11-12 00:01:03 +04:00
.globl bad_interrupt
2012-05-09 11:05:24 +04:00
.globl auto_irqhandler_fixup
.globl user_irqvec_fixup
.text
2012-10-22 00:41:46 +04:00
ENTRY( _ _ s y s _ f o r k )
2012-05-09 11:05:24 +04:00
SAVE_ S W I T C H _ S T A C K
2012-10-22 00:41:46 +04:00
jbsr s y s _ f o r k
lea % s p @(24),%sp
2012-05-09 11:05:24 +04:00
rts
2012-10-22 00:41:46 +04:00
ENTRY( _ _ s y s _ c l o n e )
2012-05-09 11:05:24 +04:00
SAVE_ S W I T C H _ S T A C K
pea % s p @(SWITCH_STACK_SIZE)
jbsr m 6 8 k _ c l o n e
2012-10-22 00:41:46 +04:00
lea % s p @(28),%sp
2012-05-09 11:05:24 +04:00
rts
2012-10-22 00:41:46 +04:00
ENTRY( _ _ s y s _ v f o r k )
2012-05-09 11:05:24 +04:00
SAVE_ S W I T C H _ S T A C K
2012-10-22 00:41:46 +04:00
jbsr s y s _ v f o r k
lea % s p @(24),%sp
2012-05-09 11:05:24 +04:00
rts
2019-11-24 22:52:25 +03:00
ENTRY( _ _ s y s _ c l o n e 3 )
SAVE_ S W I T C H _ S T A C K
pea % s p @(SWITCH_STACK_SIZE)
jbsr m 6 8 k _ c l o n e 3
lea % s p @(28),%sp
rts
2012-05-09 11:05:24 +04:00
ENTRY( s y s _ s i g r e t u r n )
SAVE_ S W I T C H _ S T A C K
2016-02-15 09:36:29 +03:00
movel % s p ,% s p @- | switch_stack pointer
pea % s p @(SWITCH_STACK_SIZE+4) | pt_regs pointer
2012-05-09 11:05:24 +04:00
jbsr d o _ s i g r e t u r n
2016-02-15 09:36:29 +03:00
addql #8 ,% s p
2012-05-09 11:05:24 +04:00
RESTORE_ S W I T C H _ S T A C K
rts
ENTRY( s y s _ r t _ s i g r e t u r n )
SAVE_ S W I T C H _ S T A C K
2016-02-15 09:36:29 +03:00
movel % s p ,% s p @- | switch_stack pointer
pea % s p @(SWITCH_STACK_SIZE+4) | pt_regs pointer
2012-05-09 11:05:24 +04:00
jbsr d o _ r t _ s i g r e t u r n
2016-02-15 09:36:29 +03:00
addql #8 ,% s p
2012-05-09 11:05:24 +04:00
RESTORE_ S W I T C H _ S T A C K
rts
ENTRY( b u s e r r )
SAVE_ A L L _ I N T
GET_ C U R R E N T ( % d0 )
movel % s p ,% s p @- | stack frame pointer argument
jbsr b u s e r r _ c
addql #4 ,% s p
jra r e t _ f r o m _ e x c e p t i o n
ENTRY( t r a p )
SAVE_ A L L _ I N T
GET_ C U R R E N T ( % d0 )
movel % s p ,% s p @- | stack frame pointer argument
jbsr t r a p _ c
addql #4 ,% s p
jra r e t _ f r o m _ e x c e p t i o n
| After a f o r k w e j u m p h e r e d i r e c t l y f r o m r e s u m e ,
| so t h a t % d1 c o n t a i n s t h e p r e v i o u s t a s k
| schedule_ t a i l n o w u s e d r e g a r d l e s s o f C O N F I G _ S M P
ENTRY( r e t _ f r o m _ f o r k )
movel % d1 ,% s p @-
jsr s c h e d u l e _ t a i l
addql #4 ,% s p
jra r e t _ f r o m _ e x c e p t i o n
2012-09-16 20:05:09 +04:00
ENTRY( r e t _ f r o m _ k e r n e l _ t h r e a d )
| a3 c o n t a i n s t h e k e r n e l t h r e a d p a y l o a d , d7 - i t s a r g u m e n t
movel % d1 ,% s p @-
jsr s c h e d u l e _ t a i l
movel % d7 ,( % s p )
jsr % a3 @
addql #4 ,% s p
2012-09-16 20:06:34 +04:00
jra r e t _ f r o m _ e x c e p t i o n
2012-05-09 11:05:24 +04:00
# if d e f i n e d ( C O N F I G _ C O L D F I R E ) | | ! d e f i n e d ( C O N F I G _ M M U )
# ifdef T R A P _ D B G _ I N T E R R U P T
.globl dbginterrupt
ENTRY( d b g i n t e r r u p t )
SAVE_ A L L _ I N T
GET_ C U R R E N T ( % d0 )
movel % s p ,% s p @- /* stack frame pointer argument */
jsr d b g i n t e r r u p t _ c
addql #4 ,% s p
jra r e t _ f r o m _ e x c e p t i o n
# endif
ENTRY( r e s c h e d u l e )
/* save top of frame */
pea % s p @
jbsr s e t _ e s p0
addql #4 ,% s p
pea r e t _ f r o m _ e x c e p t i o n
jmp s c h e d u l e
ENTRY( r e t _ f r o m _ u s e r _ s i g n a l )
moveq #_ _ N R _ s i g r e t u r n , % d 0
trap #0
ENTRY( r e t _ f r o m _ u s e r _ r t _ s i g n a l )
movel #_ _ N R _ r t _ s i g r e t u r n , % d 0
trap #0
2011-03-22 06:39:27 +03:00
# else
2012-05-09 11:05:24 +04:00
do_trace_entry :
movel #- E N O S Y S , % s p @ ( P T _ O F F _ D 0 ) | n e e d e d f o r s t r a c e
subql #4 ,% s p
SAVE_ S W I T C H _ S T A C K
jbsr s y s c a l l _ t r a c e
RESTORE_ S W I T C H _ S T A C K
addql #4 ,% s p
movel % s p @(PT_OFF_ORIG_D0),%d0
cmpl #N R _ s y s c a l l s , % d 0
jcs s y s c a l l
badsys :
movel #- E N O S Y S , % s p @ ( P T _ O F F _ D 0 )
jra r e t _ f r o m _ s y s c a l l
do_trace_exit :
subql #4 ,% s p
SAVE_ S W I T C H _ S T A C K
jbsr s y s c a l l _ t r a c e
RESTORE_ S W I T C H _ S T A C K
addql #4 ,% s p
jra . L r e t _ f r o m _ e x c e p t i o n
ENTRY( r e t _ f r o m _ s i g n a l )
movel % c u r p t r @(TASK_STACK),%a1
tstb % a1 @(TINFO_FLAGS+2)
jge 1 f
jbsr s y s c a l l _ t r a c e
1 : RESTORE_ S W I T C H _ S T A C K
addql #4 ,% s p
/* on 68040 complete pending writebacks if any */
# ifdef C O N F I G _ M 6 8 0 4 0
bfextu % s p @(PT_OFF_FORMATVEC){#0,#4},%d0
subql #7 ,% d0 | b u s e r r o r f r a m e ?
jbne 1 f
movel % s p ,% s p @-
jbsr b e r r _ 0 4 0 c l e a n u p
addql #4 ,% s p
1 :
# endif
jra . L r e t _ f r o m _ e x c e p t i o n
ENTRY( s y s t e m _ c a l l )
SAVE_ A L L _ S Y S
GET_ C U R R E N T ( % d1 )
movel % d1 ,% a1
| save t o p o f f r a m e
movel % s p ,% c u r p t r @(TASK_THREAD+THREAD_ESP0)
| syscall t r a c e ?
tstb % a1 @(TINFO_FLAGS+2)
jmi d o _ t r a c e _ e n t r y
cmpl #N R _ s y s c a l l s , % d 0
jcc b a d s y s
syscall :
jbsr @(sys_call_table,%d0:l:4)@(0)
movel % d0 ,% s p @(PT_OFF_D0) | save the return value
ret_from_syscall :
| oriw #0x0700 ,% s r
movel % c u r p t r @(TASK_STACK),%a1
movew % a1 @(TINFO_FLAGS+2),%d0
jne s y s c a l l _ e x i t _ w o r k
1 : RESTORE_ A L L
syscall_exit_work :
btst #5 ,% s p @(PT_OFF_SR) | check if returning to kernel
bnes 1 b | i f s o , s k i p r e s c h e d , s i g n a l s
lslw #1 ,% d0
jcs d o _ t r a c e _ e x i t
jmi d o _ d e l a y e d _ t r a c e
lslw #8 ,% d0
jne d o _ s i g n a l _ r e t u r n
pea r e s u m e _ u s e r s p a c e
jra s c h e d u l e
ENTRY( r e t _ f r o m _ e x c e p t i o n )
.Lret_from_exception :
btst #5 ,% s p @(PT_OFF_SR) | check if returning to kernel
bnes 1 f | i f s o , s k i p r e s c h e d , s i g n a l s
| only a l l o w i n t e r r u p t s w h e n w e a r e r e a l l y t h e l a s t o n e o n t h e
| kernel s t a c k , o t h e r w i s e s t a c k o v e r f l o w c a n o c c u r d u r i n g
| heavy i n t e r r u p t l o a d
andw #A L L O W I N T , % s r
resume_userspace :
movel % c u r p t r @(TASK_STACK),%a1
moveb % a1 @(TINFO_FLAGS+3),%d0
jne e x i t _ w o r k
1 : RESTORE_ A L L
exit_work :
| save t o p o f f r a m e
movel % s p ,% c u r p t r @(TASK_THREAD+THREAD_ESP0)
lslb #1 ,% d0
jne d o _ s i g n a l _ r e t u r n
pea r e s u m e _ u s e r s p a c e
jra s c h e d u l e
do_signal_return :
| andw #A L L O W I N T , % s r
subql #4 ,% s p | d u m m y r e t u r n a d d r e s s
SAVE_ S W I T C H _ S T A C K
pea % s p @(SWITCH_STACK_SIZE)
bsrl d o _ n o t i f y _ r e s u m e
addql #4 ,% s p
RESTORE_ S W I T C H _ S T A C K
addql #4 ,% s p
jbra r e s u m e _ u s e r s p a c e
do_delayed_trace :
bclr #7 ,% s p @(PT_OFF_SR) | clear trace bit in SR
pea 1 | s e n d S I G T R A P
movel % c u r p t r ,% s p @-
pea L S I G T R A P
jbsr s e n d _ s i g
addql #8 ,% s p
addql #4 ,% s p
jbra r e s u m e _ u s e r s p a c e
/* This is the main interrupt handler for autovector interrupts */
ENTRY( a u t o _ i n t h a n d l e r )
SAVE_ A L L _ I N T
GET_ C U R R E N T ( % d0 )
| put e x c e p t i o n # i n d 0
bfextu % s p @(PT_OFF_FORMATVEC){#4,#10},%d0
subw #V E C _ S P U R , % d 0
movel % s p ,% s p @-
movel % d0 ,% s p @- | put vector # on stack
auto_ i r q h a n d l e r _ f i x u p = . + 2
jsr d o _ I R Q | p r o c e s s t h e I R Q
addql #8 ,% s p | p o p p a r a m e t e r s o f f s t a c k
2013-11-12 00:01:03 +04:00
jra r e t _ f r o m _ e x c e p t i o n
2012-05-09 11:05:24 +04:00
/* Handler for user defined interrupt vectors */
ENTRY( u s e r _ i n t h a n d l e r )
SAVE_ A L L _ I N T
GET_ C U R R E N T ( % d0 )
| put e x c e p t i o n # i n d 0
bfextu % s p @(PT_OFF_FORMATVEC){#4,#10},%d0
user_ i r q v e c _ f i x u p = . + 2
subw #V E C _ U S E R , % d 0
movel % s p ,% s p @-
movel % d0 ,% s p @- | put vector # on stack
jsr d o _ I R Q | p r o c e s s t h e I R Q
addql #8 ,% s p | p o p p a r a m e t e r s o f f s t a c k
2013-11-12 00:01:03 +04:00
jra r e t _ f r o m _ e x c e p t i o n
2012-05-09 11:05:24 +04:00
/* Handler for uninitialized and spurious interrupts */
ENTRY( b a d _ i n t h a n d l e r )
SAVE_ A L L _ I N T
GET_ C U R R E N T ( % d0 )
movel % s p ,% s p @-
jsr h a n d l e _ b a d i n t
addql #4 ,% s p
2013-11-12 00:01:03 +04:00
jra r e t _ f r o m _ e x c e p t i o n
2012-05-09 11:05:24 +04:00
resume :
/ *
* Beware - w h e n e n t e r i n g r e s u m e , p r e v ( t h e c u r r e n t t a s k ) i s
* in a0 , n e x t ( t h e n e w t a s k ) i s i n a1 ,s o d o n ' t c h a n g e t h e s e
* registers u n t i l t h e i r c o n t e n t s a r e n o l o n g e r n e e d e d .
* /
/* save sr */
movew % s r ,% a0 @(TASK_THREAD+THREAD_SR)
/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
movec % s f c ,% d0
movew % d0 ,% a0 @(TASK_THREAD+THREAD_FS)
/* save usp */
/* it is better to use a movel here instead of a movew 8*) */
movec % u s p ,% d0
movel % d0 ,% a0 @(TASK_THREAD+THREAD_USP)
/* save non-scratch registers on stack */
SAVE_ S W I T C H _ S T A C K
/* save current kernel stack pointer */
movel % s p ,% a0 @(TASK_THREAD+THREAD_KSP)
/* save floating point context */
# ifndef C O N F I G _ M 6 8 K F P U _ E M U _ O N L Y
# ifdef C O N F I G _ M 6 8 K F P U _ E M U
tstl m 6 8 k _ f p u t y p e
jeq 3 f
# endif
fsave % a0 @(TASK_THREAD+THREAD_FPSTATE)
# if d e f i n e d ( C O N F I G _ M 6 8 0 6 0 )
# if ! d e f i n e d ( C P U _ M 6 8 0 6 0 _ O N L Y )
btst #3 ,m 6 8 k _ c p u t y p e + 3
beqs 1 f
# endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
tstb % a0 @(TASK_THREAD+THREAD_FPSTATE+2)
jeq 3 f
# if ! d e f i n e d ( C P U _ M 6 8 0 6 0 _ O N L Y )
jra 2 f
# endif
# endif / * C O N F I G _ M 6 8 0 6 0 * /
# if ! d e f i n e d ( C P U _ M 6 8 0 6 0 _ O N L Y )
1 : tstb % a0 @(TASK_THREAD+THREAD_FPSTATE)
jeq 3 f
# endif
2 : fmovemx % f p0 - % f p7 ,% a0 @(TASK_THREAD+THREAD_FPREG)
fmoveml % f p c r / % f p s r / % f p i a r ,% a0 @(TASK_THREAD+THREAD_FPCNTL)
3 :
# endif / * C O N F I G _ M 6 8 K F P U _ E M U _ O N L Y * /
/* Return previous task in %d1 */
movel % c u r p t r ,% d1
/* switch to new task (a1 contains new task) */
movel % a1 ,% c u r p t r
/* restore floating point context */
# ifndef C O N F I G _ M 6 8 K F P U _ E M U _ O N L Y
# ifdef C O N F I G _ M 6 8 K F P U _ E M U
tstl m 6 8 k _ f p u t y p e
jeq 4 f
# endif
# if d e f i n e d ( C O N F I G _ M 6 8 0 6 0 )
# if ! d e f i n e d ( C P U _ M 6 8 0 6 0 _ O N L Y )
btst #3 ,m 6 8 k _ c p u t y p e + 3
beqs 1 f
# endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
tstb % a1 @(TASK_THREAD+THREAD_FPSTATE+2)
jeq 3 f
# if ! d e f i n e d ( C P U _ M 6 8 0 6 0 _ O N L Y )
jra 2 f
# endif
# endif / * C O N F I G _ M 6 8 0 6 0 * /
# if ! d e f i n e d ( C P U _ M 6 8 0 6 0 _ O N L Y )
1 : tstb % a1 @(TASK_THREAD+THREAD_FPSTATE)
jeq 3 f
2005-04-17 02:20:36 +04:00
# endif
2012-05-09 11:05:24 +04:00
2 : fmovemx % a1 @(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
fmoveml % a1 @(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
3 : frestore % a1 @(TASK_THREAD+THREAD_FPSTATE)
4 :
# endif / * C O N F I G _ M 6 8 K F P U _ E M U _ O N L Y * /
/* restore the kernel stack pointer */
movel % a1 @(TASK_THREAD+THREAD_KSP),%sp
/* restore non-scratch registers */
RESTORE_ S W I T C H _ S T A C K
/* restore user stack pointer */
movel % a1 @(TASK_THREAD+THREAD_USP),%a0
movel % a0 ,% u s p
/* restore fs (sfc,%dfc) */
movew % a1 @(TASK_THREAD+THREAD_FS),%a0
movec % a0 ,% s f c
movec % a0 ,% d f c
/* restore status register */
movew % a1 @(TASK_THREAD+THREAD_SR),%sr
rts
# endif / * C O N F I G _ M M U & & ! C O N F I G _ C O L D F I R E * /