2015-05-11 02:32:13 +09:00
/ *
*
* linux/ a r c h / h83 0 0 / k e r n e l / e n t r y . S
*
* Yoshinori S a t o < y s a t o @users.sourceforge.jp>
* David M c C u l l o u g h < d a v i d m @snapgear.com>
*
* /
/ *
* entry. S
* include e x c e p t i o n / i n t e r r u p t g a t e w a y
* system c a l l e n t r y
* /
# include < l i n u x / s y s . h >
# include < a s m / u n i s t d . 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 / l i n k a g e . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / t h r e a d _ i n f o . h >
# include < a s m / e r r n o . h >
# if d e f i n e d ( C O N F I G _ C P U _ H 8 3 0 0 H )
# define U S E R R E T 8
INTERRUPTS = 6 4
.h8300h
.macro SHLL2 reg
shll. l \ r e g
shll. l \ r e g
.endm
.macro SHLR2 reg
shlr. l \ r e g
shlr. l \ r e g
.endm
.macro SAVEREGS
mov. l e r0 ,@-sp
mov. l e r1 ,@-sp
mov. l e r2 ,@-sp
mov. l e r3 ,@-sp
.endm
.macro RESTOREREGS
mov. l @sp+,er3
mov. l @sp+,er2
.endm
.macro SAVEEXR
.endm
.macro RESTOREEXR
.endm
# endif
# if d e f i n e d ( C O N F I G _ C P U _ H 8 S )
# define U S E R R E T 1 0
# define U S E R E X R 8
INTERRUPTS = 1 2 8
.h8300s
.macro SHLL2 reg
shll. l #2 ,\ r e g
.endm
.macro SHLR2 reg
shlr. l #2 ,\ r e g
.endm
.macro SAVEREGS
stm. l e r0 - e r3 ,@-sp
.endm
.macro RESTOREREGS
ldm. l @sp+,er2-er3
.endm
.macro SAVEEXR
mov. w @(USEREXR:16,er0),r1
mov. w r1 ,@(LEXR-LER3:16,sp) /* copy EXR */
.endm
.macro RESTOREEXR
mov. w @(LEXR-LER1:16,sp),r1 /* restore EXR */
mov. b r1 l ,r1 h
mov. w r1 ,@(USEREXR:16,er0)
.endm
# endif
/* CPU context save/restore macros. */
.macro SAVE_ALL
mov. l e r0 ,@-sp
stc c c r ,r0 l / * c h e c k k e r n e l m o d e * /
btst #4 ,r0 l
bne 5 f
/* user mode */
mov. l s p ,@_sw_usp
mov. l @sp,er0 /* restore saved er0 */
orc #0x10 ,c c r / * s w i t c h k e r n e l s t a c k * /
mov. l @_sw_ksp,sp
sub. l #( L R E T - L O R I G ) , s p / * a l l o c a t e L O R I G - L R E T * /
SAVEREGS
mov. l @_sw_usp,er0
mov. l @(USERRET:16,er0),er1 /* copy the RET addr */
mov. l e r1 ,@(LRET-LER3:16,sp)
SAVEEXR
mov. l @(LORIG-LER3:16,sp),er0
mov. l e r0 ,@(LER0-LER3:16,sp) /* copy ER0 */
mov. w e 1 ,r1 / * e 1 h i g h b y t e = c c r * /
and #0xef ,r1 h / * m a s k m o d e ? f l a g * /
bra 6 f
5 :
/* kernel mode */
mov. l @sp,er0 /* restore saved er0 */
subs #2 ,s p / * s e t d u m m y c c r * /
subs #4 ,s p / * s e t d u m m p s p * /
SAVEREGS
mov. w @(LRET-LER3:16,sp),r1 /* copy old ccr */
6 :
mov. b r1 h ,r1 l
mov. b #0 ,r1 h
mov. w r1 ,@(LCCR-LER3:16,sp) /* set ccr */
mov. l @_sw_usp,er2
mov. l e r2 ,@(LSP-LER3:16,sp) /* set usp */
mov. l e r6 ,@-sp /* syscall arg #6 */
mov. l e r5 ,@-sp /* syscall arg #5 */
mov. l e r4 ,@-sp /* syscall arg #4 */
.endm /* r1 = ccr */
.macro RESTORE_ALL
mov. l @sp+,er4
mov. l @sp+,er5
mov. l @sp+,er6
RESTOREREGS
mov. w @(LCCR-LER1:16,sp),r0 /* check kernel mode */
btst #4 ,r0 l
bne 7 f
orc #0xc0 ,c c r
mov. l @(LSP-LER1:16,sp),er0
mov. l @(LER0-LER1:16,sp),er1 /* restore ER0 */
mov. l e r1 ,@er0
RESTOREEXR
mov. w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */
mov. b r1 l ,r1 h
mov. b @(LRET+1-LER1:16,sp),r1l
mov. w r1 ,e 1
mov. w @(LRET+2-LER1:16,sp),r1
mov. l e r1 ,@(USERRET:16,er0)
mov. l @sp+,er1
add. l #( L R E T - L E R 1 ) ,s p / * r e m o v e L O R I G - L R E T * /
mov. l s p ,@_sw_ksp
andc #0xef ,c c r / * s w i t c h t o u s e r m o d e * /
mov. l e r0 ,s p
bra 8 f
7 :
mov. l @sp+,er1
add. l #10 ,s p
8 :
mov. l @sp+,er0
adds #4 ,s p / * r e m o v e t h e s w c r e a t e d L V E C * /
rte
.endm
.globl _system_call
.globl ret_from_exception
.globl ret_from_fork
.globl ret_from_kernel_thread
.globl ret_from_interrupt
.globl _interrupt_redirect_table
.globl _ sw_ k s p ,_ s w _ u s p
.globl _resume
.globl _interrupt_entry
.globl _trace_break
.globl _nmi
# if d e f i n e d ( C O N F I G _ R O M K E R N E L )
.section .int_redirect , " ax"
_interrupt_redirect_table :
# if d e f i n e d ( C O N F I G _ C P U _ H 8 3 0 0 H )
.rept 7
.long 0
.endr
# endif
# if d e f i n e d ( C O N F I G _ C P U _ H 8 S )
.rept 5
.long 0
.endr
jmp @_trace_break
.long 0
# endif
jsr @_interrupt_entry /* NMI */
jmp @_system_call /* TRAPA #0 (System call) */
.long 0
2016-01-20 23:27:30 +09:00
# if d e f i n e d ( C O N F I G _ K G D B )
jmp @_kgdb_trap
# else
2015-05-11 02:32:13 +09:00
.long 0
2016-01-20 23:27:30 +09:00
# endif
2015-05-11 02:32:13 +09:00
jmp @_trace_break /* TRAPA #3 (breakpoint) */
.rept INTERRUPTS- 1 2
jsr @_interrupt_entry
.endr
# endif
# if d e f i n e d ( C O N F I G _ R A M K E R N E L )
.globl _interrupt_redirect_table
.section .bss
_interrupt_redirect_table :
.space 4
# endif
.section .text
.align 2
_interrupt_entry :
SAVE_ A L L
/* r1l is saved ccr */
mov. l s p ,e r0
add. l #L V E C , e r 0
btst #4 ,r1 l
bne 1 f
/* user LVEC */
mov. l @_sw_usp,er0
adds #4 ,e r0
1 :
mov. l @er0,er0 /* LVEC address */
# if d e f i n e d ( C O N F I G _ R O M K E R N E L )
sub. l #_ i n t e r r u p t _ r e d i r e c t _ t a b l e , e r 0
# endif
# if d e f i n e d ( C O N F I G _ R A M K E R N E L )
mov. l @_interrupt_redirect_table,er1
sub. l e r1 ,e r0
# endif
SHLR2 e r0
dec. l #1 ,e r0
mov. l s p ,e r1
subs #4 ,e r1 / * a d j u s t r e t _ p c * /
# if d e f i n e d ( C O N F I G _ C P U _ H 8 S )
orc #7 ,e x r
# endif
jsr @do_IRQ
jmp @ret_from_interrupt
_system_call :
subs #4 ,s p / * d u m m y L V E C * /
SAVE_ A L L
/* er0: syscall nr */
andc #0xbf ,c c r
mov. l e r0 ,e r4
/* save top of frame */
mov. l s p ,e r0
jsr @set_esp0
2016-01-15 23:51:51 +09:00
andc #0x3f ,c c r
2015-05-11 02:32:13 +09:00
mov. l s p ,e r2
and. w #0xe000 ,r2
mov. l @(TI_FLAGS:16,er2),er2
and. w #_ T I F _ W O R K _ S Y S C A L L _ M A S K , r 2
beq 1 f
mov. l s p ,e r0
jsr @do_syscall_trace_enter
1 :
cmp. l #_ _ N R _ s y s c a l l s , e r 4
bcc b a d s y s
SHLL2 e r4
mov. l #_ s y s _ c a l l _ t a b l e , e r 0
add. l e r4 ,e r0
mov. l @er0,er4
beq r e t _ f r o m _ e x c e p t i o n : 1 6
mov. l @(LER1:16,sp),er0
mov. l @(LER2:16,sp),er1
mov. l @(LER3:16,sp),er2
jsr @er4
mov. l e r0 ,@(LER0:16,sp) /* save the return value */
mov. l s p ,e r2
and. w #0xe000 ,r2
mov. l @(TI_FLAGS:16,er2),er2
and. w #_ T I F _ W O R K _ S Y S C A L L _ M A S K , r 2
beq 2 f
mov. l s p ,e r0
jsr @do_syscall_trace_leave
2 :
orc #0xc0 ,c c r
bra r e s u m e _ u s e r s p a c e
badsys :
mov. l #- E N O S Y S , e r 0
mov. l e r0 ,@(LER0:16,sp)
bra r e s u m e _ u s e r s p a c e
# if ! d e f i n e d ( C O N F I G _ P R E E M P T )
# define r e s u m e _ k e r n e l r e s t o r e _ a l l
# endif
ret_from_exception :
# if d e f i n e d ( C O N F I G _ P R E E M P T )
orc #0xc0 ,c c r
# endif
ret_from_interrupt :
mov. b @(LCCR+1:16,sp),r0l
btst #4 ,r0 l
bne r e s u m e _ k e r n e l : 1 6 / * r e t u r n f r o m k e r n e l * /
resume_userspace :
andc #0xbf ,c c r
mov. l s p ,e r4
and. w #0xe000 ,r4 / * e r4 < - c u r r e n t t h r e a d i n f o * /
mov. l @(TI_FLAGS:16,er4),er1
and. l #_ T I F _ W O R K _ M A S K , e r 1
beq r e s t o r e _ a l l : 8
work_pending :
btst #T I F _ N E E D _ R E S C H E D , r 1 l
bne w o r k _ r e s c h e d : 8
/* work notifysig */
mov. l s p ,e r0
subs #4 ,e r0 / * e r0 : p t _ r e g s * /
jsr @do_notify_resume
bra r e s u m e _ u s e r s p a c e : 8
work_resched :
mov. l s p ,e r0
jsr @set_esp0
jsr @schedule
bra r e s u m e _ u s e r s p a c e : 8
restore_all :
RESTORE_ A L L / * D o e s R T E * /
# if d e f i n e d ( C O N F I G _ P R E E M P T )
resume_kernel :
mov. l @(TI_PRE_COUNT:16,er4),er0
bne r e s t o r e _ a l l : 8
need_resched :
mov. l @(TI_FLAGS:16,er4),er0
btst #T I F _ N E E D _ R E S C H E D , r 0 l
beq r e s t o r e _ a l l : 8
mov. b @(LCCR+1:16,sp),r0l /* Interrupt Enabled? */
bmi r e s t o r e _ a l l : 8
mov. l s p ,e r0
jsr @set_esp0
jsr @preempt_schedule_irq
bra n e e d _ r e s c h e d : 8
# endif
ret_from_fork :
mov. l e r2 ,e r0
jsr @schedule_tail
jmp @ret_from_exception
ret_from_kernel_thread :
mov. l e r2 ,e r0
jsr @schedule_tail
mov. l @(LER4:16,sp),er0
mov. l @(LER5:16,sp),er1
jsr @er1
jmp @ret_from_exception
_resume :
/ *
* Beware - w h e n e n t e r i n g r e s u m e , o f f s e t o f t s s i s i n d1 ,
* prev ( t h e c u r r e n t t a s k ) i s i n a0 , n e x t ( t h e n e w t a s k )
* is i n a1 a n d d2 . b i s n o n - z e r o i f t h e m m s t r u c t u r e i s
* shared b e t w e e n t h e t a s k s , 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 */
sub. w r3 ,r3
stc c c r ,r3 l
mov. w r3 ,@(THREAD_CCR+2:16,er0)
/* disable interrupts */
orc #0xc0 ,c c r
mov. l @_sw_usp,er3
mov. l e r3 ,@(THREAD_USP:16,er0)
mov. l s p ,@(THREAD_KSP:16,er0)
/* Skip address space switching if they are the same. */
/* FIXME: what did we hack out of here, this does nothing! */
mov. l @(THREAD_USP:16,er1),er0
mov. l e r0 ,@_sw_usp
mov. l @(THREAD_KSP:16,er1),sp
/* restore status register */
mov. w @(THREAD_CCR+2:16,er1),r3
ldc r3 l ,c c r
rts
_trace_break :
subs #4 ,s p
SAVE_ A L L
sub. l e r1 ,e r1
dec. l #1 ,e r1
mov. l e r1 ,@(LORIG,sp)
mov. l s p ,e r0
jsr @set_esp0
mov. l @_sw_usp,er0
mov. l @er0,er1
mov. w @(-2:16,er1),r2
cmp. w #0x5730 ,r2
beq 1 f
subs #2 ,e r1
mov. l e r1 ,@er0
1 :
and. w #0xff ,e 1
mov. l e r1 ,e r0
jsr @trace_trap
jmp @ret_from_exception
_nmi :
subs #4 , s p
mov. l e r0 , @-sp
mov. l @_interrupt_redirect_table, er0
add. l #8 * 4 , e r0
mov. l e r0 , @(4,sp)
mov. l @sp+, er0
jmp @_interrupt_entry
2016-01-20 23:27:30 +09:00
# if d e f i n e d ( C O N F I G _ K G D B )
_kgdb_trap :
subs #4 ,s p
SAVE_ A L L
mov. l s p ,e r0
add. l #L R E T , e r 0
mov. l e r0 ,@(LSP,sp)
jsr @set_esp0
mov. l s p ,e r0
subs #4 ,e r0
jsr @h8300_kgdb_trap
jmp @ret_from_exception
# endif
2015-05-11 02:32:13 +09:00
.section .bss
_sw_ksp :
.space 4
_sw_usp :
.space 4
.end