2005-06-24 09:01:16 +04:00
/ *
* arch/ x t e n s a / k e r n e l / e n t r y . S
*
* Low- l e v e l e x c e p t i o n h a n d l i n g
*
* 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 .
*
2007-08-22 21:14:51 +04:00
* Copyright ( C ) 2 0 0 4 - 2 0 0 7 b y T e n s i l i c a I n c .
2005-06-24 09:01:16 +04:00
*
* Chris Z a n k e l < c h r i s @zankel.net>
*
* /
# include < l i n u x / l i n k a g e . h >
2005-09-09 22:57:26 +04:00
# include < a s m / a s m - o f f s e t s . h >
2005-06-24 09:01:16 +04:00
# include < a s m / p r o c e s s o r . h >
# include < a s m / t h r e a d _ i n f o . h >
# include < a s m / u a c c e s s . h >
# include < a s m / u n i s t d . h >
# include < a s m / p t r a c e . h >
# include < a s m / c u r r e n t . h >
# include < a s m / p g t a b l e . h >
# include < a s m / p a g e . h >
# include < a s m / s i g n a l . h >
2006-12-10 13:18:48 +03:00
# include < a s m / t l b f l u s h . h >
2008-11-06 17:40:46 +03:00
# include < v a r i a n t / t i e - a s m . h >
2005-06-24 09:01:16 +04:00
/* Unimplemented features. */
# undef K E R N E L _ S T A C K _ O V E R F L O W _ C H E C K
# undef P R E E M P T I B L E _ K E R N E L
# undef A L L O C A _ E X C E P T I O N _ I N _ I R A M
/ * Not w e l l t e s t e d .
*
* - fast_ c o p r o c e s s o r
* /
/ *
* Macro t o f i n d f i r s t b i t s e t i n W I N D O W B A S E f r o m t h e l e f t + 1
*
* 1 0 0 . . . .0 - > 1
* 0 1 0 . . . .0 - > 2
* 0 0 0 . . . .1 - > WSBITS
* /
.macro ffs_ws bit m a s k
# if X C H A L _ H A V E _ N S A
nsau \ b i t , \ m a s k # 32 - W S B I T S . . . 3 1 ( 3 2 i f f 0 )
addi \ b i t , \ b i t , W S B I T S - 3 2 + 1 # u p p e s t b i t s e t - > r e t u r n 1
# else
movi \ b i t , W S B I T S
# if W S B I T S > 1 6
_ bltui \ m a s k , 0 x10 0 0 0 , 9 9 f
addi \ b i t , \ b i t , - 1 6
extui \ m a s k , \ m a s k , 1 6 , 1 6
# endif
# if W S B I T S > 8
99 : _ bltui \ m a s k , 0 x10 0 , 9 9 f
addi \ b i t , \ b i t , - 8
srli \ m a s k , \ m a s k , 8
# endif
99 : _ bltui \ m a s k , 0 x10 , 9 9 f
addi \ b i t , \ b i t , - 4
srli \ m a s k , \ m a s k , 4
99 : _ bltui \ m a s k , 0 x4 , 9 9 f
addi \ b i t , \ b i t , - 2
srli \ m a s k , \ m a s k , 2
99 : _ bltui \ m a s k , 0 x2 , 9 9 f
addi \ b i t , \ b i t , - 1
99 :
# endif
.endm
/* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- */
/ *
* First- l e v e l e x c e p t i o n h a n d l e r f o r u s e r e x c e p t i o n s .
* Save s o m e s p e c i a l r e g i s t e r s , e x t r a s t a t e s a n d a l l r e g i s t e r s i n t h e A R
* register f i l e t h a t w e r e i n u s e i n t h e u s e r t a s k , a n d j u m p t o t h e c o m m o n
* exception c o d e .
* We s a v e S A R ( u s e d t o c a l c u l a t e W M A S K ) , a n d W B a n d W S ( w e d o n ' t h a v e t o
* save t h e m f o r k e r n e l e x c e p t i o n s ) .
*
* Entry c o n d i t i o n f o r u s e r _ e x c e p t i o n :
*
* a0 : trashed, o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ A R E G 0 )
* a1 : a1
* a2 : new s t a c k p o i n t e r , o r i g i n a l v a l u e i n d e p c
* a3 : dispatch t a b l e
* depc : a2 , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ D E P C )
* excsave1 : a3
*
* PT_ D E P C > = V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S : d o u b l e e x c e p t i o n , D E P C
* < VALID_DOUBLE_EXCEPTION_ADDRESS : regular e x c e p t i o n
*
* Entry c o n d i t i o n f o r _ u s e r _ e x c e p t i o n :
*
* a0 - a3 a n d d e p c h a v e b e e n s a v e d t o P T _ A R E G 0 . . . P T _ A R E G 3 a n d P T _ D E P C
* excsave h a s b e e n r e s t o r e d , a n d
* stack p o i n t e r ( a1 ) h a s b e e n s e t .
*
* Note : _ user_ e x c e p t i o n m i g h t b e a t a n o d d a d r e s s . D o n ' t u s e c a l l 0 . . c a l l 1 2
* /
ENTRY( u s e r _ e x c e p t i o n )
/* Save a2, a3, and depc, restore excsave_1 and set SP. */
xsr a3 , E X C S A V E _ 1
rsr a0 , D E P C
s3 2 i a1 , a2 , P T _ A R E G 1
s3 2 i a0 , a2 , P T _ A R E G 2
s3 2 i a3 , a2 , P T _ A R E G 3
mov a1 , a2
.globl _user_exception
_user_exception :
/* Save SAR and turn off single stepping */
movi a2 , 0
rsr a3 , S A R
2007-06-01 04:49:32 +04:00
xsr a2 , I C O U N T L E V E L
2005-06-24 09:01:16 +04:00
s3 2 i a3 , a1 , P T _ S A R
2007-06-01 04:49:32 +04:00
s3 2 i a2 , a1 , P T _ I C O U N T L E V E L
2005-06-24 09:01:16 +04:00
/* Rotate ws so that the current windowbase is at bit0. */
/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
rsr a2 , W I N D O W B A S E
rsr a3 , W I N D O W S T A R T
ssr a2
s3 2 i a2 , a1 , P T _ W I N D O W B A S E
s3 2 i a3 , a1 , P T _ W I N D O W S T A R T
slli a2 , a3 , 3 2 - W S B I T S
src a2 , a3 , a2
srli a2 , a2 , 3 2 - W S B I T S
s3 2 i a2 , a1 , P T _ W M A S K # n e e d e d f o r r e s t o r i n g r e g i s t e r s
/* Save only live registers. */
_ bbsi. l a2 , 1 , 1 f
s3 2 i a4 , a1 , P T _ A R E G 4
s3 2 i a5 , a1 , P T _ A R E G 5
s3 2 i a6 , a1 , P T _ A R E G 6
s3 2 i a7 , a1 , P T _ A R E G 7
_ bbsi. l a2 , 2 , 1 f
s3 2 i a8 , a1 , P T _ A R E G 8
s3 2 i a9 , a1 , P T _ A R E G 9
s3 2 i a10 , a1 , P T _ A R E G 1 0
s3 2 i a11 , a1 , P T _ A R E G 1 1
_ bbsi. l a2 , 3 , 1 f
s3 2 i a12 , a1 , P T _ A R E G 1 2
s3 2 i a13 , a1 , P T _ A R E G 1 3
s3 2 i a14 , a1 , P T _ A R E G 1 4
s3 2 i a15 , a1 , P T _ A R E G 1 5
_ bnei a2 , 1 , 1 f # o n l y o n e v a l i d f r a m e ?
/* Only one valid frame, skip saving regs. */
j 2 f
/ * Save t h e r e m a i n i n g r e g i s t e r s .
* We h a v e t o s a v e a l l r e g i s t e r s u p t o t h e f i r s t ' 1 ' f r o m
* the r i g h t , e x c e p t t h e c u r r e n t f r a m e ( b i t 0 ) .
* Assume a2 i s : 0 0 1 0 0 1 0 0 0 1 1 0 0 0 1
2007-08-22 21:14:51 +04:00
* All r e g i s t e r f r a m e s s t a r t i n g f r o m t h e t o p f i e l d t o t h e m a r k e d ' 1 '
2005-06-24 09:01:16 +04:00
* must b e s a v e d .
* /
1 : addi a3 , a2 , - 1 # e l i m i n a t e ' 1 ' i n b i t 0 : y y y y x x w w0
neg a3 , a3 # y y y y x x w w 0 - > Y Y Y Y X X W W 1 + 1
and a3 , a3 , a2 # m a x . o n l y o n e b i t i s s e t
/* Find number of frames to save */
ffs_ w s a0 , a3 # n u m b e r o f f r a m e s t o t h e ' 1 ' f r o m l e f t
/ * Store i n f o r m a t i o n i n t o W M A S K :
* bits 0 . . 3 : x x x1 m a s k e d l o w e r 4 b i t s o f t h e r o t a t e d w i n d o w s t a r t ,
* bits 4 . . . : n u m b e r o f v a l i d 4 - r e g i s t e r f r a m e s
* /
slli a3 , a0 , 4 # n u m b e r o f f r a m e s t o s a v e i n b i t s 8 . . 4
extui a2 , a2 , 0 , 4 # m a s k f o r t h e f i r s t 16 r e g i s t e r s
or a2 , a3 , a2
s3 2 i a2 , a1 , P T _ W M A S K # n e e d e d w h e n w e r e s t o r e t h e r e g - f i l e
/* Save 4 registers at a time */
1 : rotw - 1
s3 2 i a0 , a5 , P T _ A R E G _ E N D - 1 6
s3 2 i a1 , a5 , P T _ A R E G _ E N D - 1 2
s3 2 i a2 , a5 , P T _ A R E G _ E N D - 8
s3 2 i a3 , a5 , P T _ A R E G _ E N D - 4
addi a0 , a4 , - 1
addi a1 , a5 , - 1 6
_ bnez a0 , 1 b
/* WINDOWBASE still in SAR! */
rsr a2 , S A R # o r i g i n a l W I N D O W B A S E
movi a3 , 1
ssl a2
sll a3 , a3
wsr a3 , W I N D O W S T A R T # s e t c o r r e s p o n d i n g W I N D O W S T A R T b i t
wsr a2 , W I N D O W B A S E # a n d W I N D O W S T A R T
rsync
/* We are back to the original stack pointer (a1) */
2008-02-13 00:17:07 +03:00
2 : /* Now, jump to the common exception handler. */
2005-06-24 09:01:16 +04:00
j c o m m o n _ e x c e p t i o n
/ *
* First- l e v e l e x i t h a n d l e r f o r k e r n e l e x c e p t i o n s
* Save s p e c i a l r e g i s t e r s a n d t h e l i v e w i n d o w f r a m e .
* Note : Even t h o u g h w e c h a n g e s t h e s t a c k p o i n t e r , w e d o n ' t h a v e t o d o a
* MOVSP h e r e , a s w e d o t h a t w h e n w e r e t u r n f r o m t h e e x c e p t i o n .
* ( See c o m m e n t i n t h e k e r n e l e x c e p t i o n e x i t c o d e )
*
* Entry c o n d i t i o n f o r k e r n e l _ e x c e p t i o n :
*
* a0 : trashed, o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ A R E G 0 )
* a1 : a1
* a2 : new s t a c k p o i n t e r , o r i g i n a l i n D E P C
* a3 : dispatch t a b l e
* depc : a2 , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ D E P C )
* excsave_1 : a3
*
* PT_ D E P C > = V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S : d o u b l e e x c e p t i o n , D E P C
* < VALID_DOUBLE_EXCEPTION_ADDRESS : regular e x c e p t i o n
*
* Entry c o n d i t i o n f o r _ k e r n e l _ e x c e p t i o n :
*
* a0 - a3 a n d d e p c h a v e b e e n s a v e d t o P T _ A R E G 0 . . . P T _ A R E G 3 a n d P T _ D E P C
* excsave h a s b e e n r e s t o r e d , a n d
* stack p o i n t e r ( a1 ) h a s b e e n s e t .
*
* Note : _ kernel_ e x c e p t i o n m i g h t b e a t a n o d d a d r e s s . D o n ' t u s e c a l l 0 . . c a l l 1 2
* /
ENTRY( k e r n e l _ e x c e p t i o n )
/* Save a0, a2, a3, DEPC and set SP. */
xsr a3 , E X C S A V E _ 1 # r e s t o r e a 3 , e x c s a v e _ 1
rsr a0 , D E P C # g e t a 2
s3 2 i a1 , a2 , P T _ A R E G 1
s3 2 i a0 , a2 , P T _ A R E G 2
s3 2 i a3 , a2 , P T _ A R E G 3
mov a1 , a2
.globl _kernel_exception
_kernel_exception :
/* Save SAR and turn off single stepping */
movi a2 , 0
rsr a3 , S A R
2007-06-01 04:49:32 +04:00
xsr a2 , I C O U N T L E V E L
2005-06-24 09:01:16 +04:00
s3 2 i a3 , a1 , P T _ S A R
2007-06-01 04:49:32 +04:00
s3 2 i a2 , a1 , P T _ I C O U N T L E V E L
2005-06-24 09:01:16 +04:00
/* Rotate ws so that the current windowbase is at bit0. */
/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
rsr a2 , W I N D O W B A S E # d o n ' t n e e d t o s a v e t h e s e , w e o n l y
rsr a3 , W I N D O W S T A R T # n e e d s h i f t e d w i n d o w s t a r t : w i n d o w m a s k
ssr a2
slli a2 , a3 , 3 2 - W S B I T S
src a2 , a3 , a2
srli a2 , a2 , 3 2 - W S B I T S
s3 2 i a2 , a1 , P T _ W M A S K # n e e d e d f o r k e r n e l _ e x c e p t i o n _ e x i t
/* Save only the live window-frame */
_ bbsi. l a2 , 1 , 1 f
s3 2 i a4 , a1 , P T _ A R E G 4
s3 2 i a5 , a1 , P T _ A R E G 5
s3 2 i a6 , a1 , P T _ A R E G 6
s3 2 i a7 , a1 , P T _ A R E G 7
_ bbsi. l a2 , 2 , 1 f
s3 2 i a8 , a1 , P T _ A R E G 8
s3 2 i a9 , a1 , P T _ A R E G 9
s3 2 i a10 , a1 , P T _ A R E G 1 0
s3 2 i a11 , a1 , P T _ A R E G 1 1
_ bbsi. l a2 , 3 , 1 f
s3 2 i a12 , a1 , P T _ A R E G 1 2
s3 2 i a13 , a1 , P T _ A R E G 1 3
s3 2 i a14 , a1 , P T _ A R E G 1 4
s3 2 i a15 , a1 , P T _ A R E G 1 5
1 :
# ifdef K E R N E L _ S T A C K _ O V E R F L O W _ C H E C K
/* Stack overflow check, for debugging */
extui a2 , a1 , T A S K _ S I Z E _ B I T S ,X X
movi a3 , S I Z E ? ?
_ bge a2 , a3 , o u t _ o f _ s t a c k _ p a n i c
# endif
/ *
* This i s t h e c o m m o n e x c e p t i o n h a n d l e r .
* We g e t h e r e f r o m t h e u s e r e x c e p t i o n h a n d l e r o r s i m p l y b y f a l l i n g t h r o u g h
* from t h e k e r n e l e x c e p t i o n h a n d l e r .
* Save t h e r e m a i n i n g s p e c i a l r e g i s t e r s , s w i t c h t o k e r n e l m o d e , a n d j u m p
* to t h e s e c o n d - l e v e l e x c e p t i o n h a n d l e r .
*
* /
common_exception :
2007-06-01 04:49:32 +04:00
/* Save some registers, disable loops and clear the syscall flag. */
2005-06-24 09:01:16 +04:00
rsr a2 , D E B U G C A U S E
rsr a3 , E P C _ 1
s3 2 i a2 , a1 , P T _ D E B U G C A U S E
s3 2 i a3 , a1 , P T _ P C
2007-06-01 04:49:32 +04:00
movi a2 , - 1
2005-06-24 09:01:16 +04:00
rsr a3 , E X C V A D D R
2007-06-01 04:49:32 +04:00
s3 2 i a2 , a1 , P T _ S Y S C A L L
2005-06-24 09:01:16 +04:00
movi a2 , 0
s3 2 i a3 , a1 , P T _ E X C V A D D R
xsr a2 , L C O U N T
s3 2 i a2 , a1 , P T _ L C O U N T
/* It is now save to restore the EXC_TABLE_FIXUP variable. */
rsr a0 , E X C C A U S E
movi a3 , 0
rsr a2 , E X C S A V E _ 1
s3 2 i a0 , a1 , P T _ E X C C A U S E
s3 2 i a3 , a2 , E X C _ T A B L E _ F I X U P
/ * All u n r e c o v e r a b l e s t a t e s a r e s a v e d o n s t a c k , n o w , a n d a1 i s v a l i d ,
* so w e c a n a l l o w e x c e p t i o n s a n d i n t e r r u p t s ( * ) a g a i n .
* Set P S ( E X C M = 0 , U M = 0 , R I N G = 0 , O W B = 0 , W O E = 1 , I N T L E V E L = X )
*
* ( * ) We o n l y a l l o w i n t e r r u p t s i f P S . I N T L E V E L w a s n o t s e t t o 1 b e f o r e
* ( interrupts d i s a b l e d ) a n d i f t h i s e x c e p t i o n i s n o t a n i n t e r r u p t .
* /
rsr a3 , P S
addi a0 , a0 , - 4
movi a2 , 1
extui a3 , a3 , 0 , 1 # a 3 = P S . I N T L E V E L [ 0 ]
moveqz a3 , a2 , a0 # a 3 = 1 i f f i n t e r r u p t e x c e p t i o n
2006-12-10 13:18:48 +03:00
movi a2 , 1 < < P S _ W O E _ B I T
2005-06-24 09:01:16 +04:00
or a3 , a3 , a2
rsr a0 , E X C C A U S E
xsr a3 , P S
s3 2 i a3 , a1 , P T _ P S # s a v e p s
/* Save LBEG, LEND */
rsr a2 , L B E G
rsr a3 , L E N D
s3 2 i a2 , a1 , P T _ L B E G
s3 2 i a3 , a1 , P T _ L E N D
2008-02-13 00:17:07 +03:00
/* Save optional registers. */
save_ x t r e g s _ o p t a1 a2 a4 a5 a6 a7 P T _ X T R E G S _ O P T
2005-06-24 09:01:16 +04:00
/ * Go t o s e c o n d - l e v e l d i s p a t c h e r . S e t u p p a r a m e t e r s t o p a s s t o t h e
* exception h a n d l e r a n d c a l l t h e e x c e p t i o n h a n d l e r .
* /
movi a4 , e x c _ t a b l e
mov a6 , a1 # p a s s s t a c k f r a m e
mov a7 , a0 # p a s s E X C C A U S E
addx4 a4 , a0 , a4
l3 2 i a4 , a4 , E X C _ T A B L E _ D E F A U L T # l o a d h a n d l e r
/* Call the second-level handler */
callx4 a4
/* Jump here for exception exit */
common_exception_return :
/* Jump if we are returning from kernel exceptions. */
1 : l3 2 i a3 , a1 , P T _ P S
2008-01-22 11:45:25 +03:00
_ bbci. l a3 , P S _ U M _ B I T , 4 f
2005-06-24 09:01:16 +04:00
/ * Specific t o a u s e r e x c e p t i o n e x i t :
* We n e e d t o c h e c k s o m e f l a g s f o r s i g n a l h a n d l i n g a n d r e s c h e d u l i n g ,
* and h a v e t o r e s t o r e W B a n d W S , e x t r a s t a t e s , a n d a l l r e g i s t e r s
* in t h e r e g i s t e r f i l e t h a t w e r e i n u s e i n t h e u s e r t a s k .
2008-01-22 11:45:25 +03:00
* Note t h a t w e d o n ' t d i s a b l e i n t e r r u p t s h e r e .
2005-06-24 09:01:16 +04:00
* /
GET_ T H R E A D _ I N F O ( a2 ,a1 )
l3 2 i a4 , a2 , T I _ F L A G S
_ bbsi. l a4 , T I F _ N E E D _ R E S C H E D , 3 f
_ bbci. l a4 , T I F _ S I G P E N D I N G , 4 f
l3 2 i a4 , a1 , P T _ D E P C
bgeui a4 , V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S , 4 f
2008-01-22 11:45:25 +03:00
/* Call do_signal() */
2005-06-24 09:01:16 +04:00
movi a4 , d o _ s i g n a l # i n t d o _ s i g n a l ( s t r u c t p t _ r e g s * , s i g s e t _ t * )
mov a6 , a1
movi a7 , 0
callx4 a4
j 1 b
2008-01-22 11:45:25 +03:00
3 : /* Reschedule */
2005-06-24 09:01:16 +04:00
movi a4 , s c h e d u l e # v o i d s c h e d u l e ( v o i d )
callx4 a4
j 1 b
2008-01-22 11:45:25 +03:00
4 : /* Restore optional registers. */
load_ x t r e g s _ o p t a1 a2 a4 a5 a6 a7 P T _ X T R E G S _ O P T
2005-06-24 09:01:16 +04:00
2008-01-22 11:45:25 +03:00
wsr a3 , P S / * d i s a b l e i n t e r r u p t s * /
_ bbci. l a3 , P S _ U M _ B I T , k e r n e l _ e x c e p t i o n _ e x i t
user_exception_exit :
/* Restore the state of the task and return from the exception. */
2005-06-24 09:01:16 +04:00
/* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */
l3 2 i a2 , a1 , P T _ W I N D O W B A S E
l3 2 i a3 , a1 , P T _ W I N D O W S T A R T
wsr a1 , D E P C # u s e D E P C a s t e m p s t o r a g e
wsr a3 , W I N D O W S T A R T # r e s t o r e W I N D O W S T A R T
ssr a2 # p r e s e r v e u s e r ' s W B i n t h e S A R
wsr a2 , W I N D O W B A S E # s w i t c h t o u s e r ' s s a v e d W B
rsync
rsr a1 , D E P C # r e s t o r e s t a c k p o i n t e r
l3 2 i a2 , a1 , P T _ W M A S K # r e g i s t e r f r a m e s s a v e d ( i n b i t s 4 . . . 9 )
rotw - 1 # w e r e s t o r e a 4 . . a7
_ bltui a6 , 1 6 , 1 f # o n l y h a v e t o r e s t o r e c u r r e n t w i n d o w ?
/ * The w o r k i n g r e g i s t e r s a r e a0 a n d a3 . W e a r e r e s t o r i n g t o
* a4 . . a7 . B e c a r e f u l n o t t o d e s t r o y w h a t w e h a v e j u s t r e s t o r e d .
* Note : wmask h a s t h e f o r m a t Y Y Y Y M :
* Y : number o f r e g i s t e r s s a v e d i n g r o u p s o f 4
* M : 4 bit m a s k o f f i r s t 1 6 r e g i s t e r s
* /
mov a2 , a6
mov a3 , a5
2 : rotw - 1 # a 0 . . a3 b e c o m e a4 . . a7
addi a3 , a7 , - 4 * 4 # n e x t i t e r a t i o n
addi a2 , a6 , - 1 6 # d e c r e m e n t i n g Y i n W M A S K
l3 2 i a4 , a3 , P T _ A R E G _ E N D + 0
l3 2 i a5 , a3 , P T _ A R E G _ E N D + 4
l3 2 i a6 , a3 , P T _ A R E G _ E N D + 8
l3 2 i a7 , a3 , P T _ A R E G _ E N D + 1 2
_ bgeui a2 , 1 6 , 2 b
/* Clear unrestored registers (don't leak anything to user-land */
1 : rsr a0 , W I N D O W B A S E
rsr a3 , S A R
sub a3 , a0 , a3
beqz a3 , 2 f
extui a3 , a3 , 0 , W B B I T S
1 : rotw - 1
addi a3 , a7 , - 1
movi a4 , 0
movi a5 , 0
movi a6 , 0
movi a7 , 0
bgei a3 , 1 , 1 b
/ * We a r e b a c k w e r e w e w e r e w h e n w e s t a r t e d .
* Note : a2 s t i l l c o n t a i n s W M A S K ( i f w e ' v e r e t u r n e d t o t h e o r i g i n a l
* frame w h e r e w e h a d l o a d e d a2 ) , o r a t l e a s t t h e l o w e r 4 b i t s
* ( if w e h a v e r e s t o r e d W S B I T S - 1 f r a m e s ) .
* /
2 : j c o m m o n _ e x c e p t i o n _ e x i t
/ * This i s t h e k e r n e l e x c e p t i o n e x i t .
* We a v o i d e d t o d o a M O V S P w h e n w e e n t e r e d t h e e x c e p t i o n , b u t w e
* have t o d o i t h e r e .
* /
kernel_exception_exit :
# ifdef P R E E M P T I B L E _ K E R N E L
# ifdef C O N F I G _ P R E E M P T
/ *
* Note : We' v e j u s t r e t u r n e d f r o m a c a l l 4 , s o w e h a v e
* at l e a s t 4 a d d t ' l r e g s .
* /
/* Check current_thread_info->preempt_count */
GET_ T H R E A D _ I N F O ( a2 )
l3 2 i a3 , a2 , T I _ P R E E M P T
bnez a3 , 1 f
l3 2 i a2 , a2 , T I _ F L A G S
1 :
# endif
# endif
/ * Check i f w e h a v e t o d o a m o v s p .
*
* We o n l y h a v e t o d o a m o v s p i f t h e p r e v i o u s w i n d o w - f r a m e h a s
* been s p i l l e d t o t h e * t e m p o r a r y * e x c e p t i o n s t a c k i n s t e a d o f t h e
* task' s s t a c k . T h i s i s t h e c a s e i f t h e c o r r e s p o n d i n g b i t i n
* WINDOWSTART f o r t h e p r e v i o u s w i n d o w - f r a m e w a s s e t b e f o r e
* ( not s p i l l e d ) b u t i s z e r o n o w ( s p i l l e d ) .
* If t h i s b i t i s z e r o , a l l o t h e r b i t s e x c e p t t h e o n e f o r t h e
* current w i n d o w f r a m e a r e a l s o z e r o . S o , w e c a n u s e a s i m p l e t e s t :
* ' and' W I N D O W S T A R T a n d W I N D O W S T A R T - 1 :
*
* ( XXXXXX1 [ 0 ] * - 1 ) A N D X X X X X X 1 [ 0 ] * = X X X X X X 0 [ 0 ] *
*
* The r e s u l t i s z e r o o n l y i f o n e b i t w a s s e t .
*
* ( Note : We m i g h t h a v e g o n e t h r o u g h s e v e r a l t a s k s w i t c h e s b e f o r e
* we c o m e b a c k t o t h e c u r r e n t t a s k , s o W I N D O W B A S E m i g h t b e
* different f r o m t h e t i m e t h e e x c e p t i o n o c c u r r e d . )
* /
/ * Test W I N D O W S T A R T b e f o r e a n d a f t e r t h e e x c e p t i o n .
* We a c t u a l l y h a v e W M A S K , s o w e o n l y h a v e t o t e s t i f i t i s 1 o r n o t .
* /
l3 2 i a2 , a1 , P T _ W M A S K
_ beqi a2 , 1 , c o m m o n _ e x c e p t i o n _ e x i t # S p i l l e d b e f o r e e x c e p t i o n , j u m p
/* Test WINDOWSTART now. If spilled, do the movsp */
rsr a3 , W I N D O W S T A R T
addi a0 , a3 , - 1
and a3 , a3 , a0
_ bnez a3 , c o m m o n _ e x c e p t i o n _ e x i t
/* Do a movsp (we returned from a call4, so we have at least a0..a7) */
addi a0 , a1 , - 1 6
l3 2 i a3 , a0 , 0
l3 2 i a4 , a0 , 4
s3 2 i a3 , a1 , P T _ S I Z E + 0
s3 2 i a4 , a1 , P T _ S I Z E + 4
l3 2 i a3 , a0 , 8
l3 2 i a4 , a0 , 1 2
s3 2 i a3 , a1 , P T _ S I Z E + 8
s3 2 i a4 , a1 , P T _ S I Z E + 1 2
/ * Common e x c e p t i o n e x i t .
* We r e s t o r e t h e s p e c i a l r e g i s t e r a n d t h e c u r r e n t w i n d o w f r a m e , a n d
* return f r o m t h e e x c e p t i o n .
*
* Note : We e x p e c t a2 t o h o l d P T _ W M A S K
* /
common_exception_exit :
2008-02-13 00:17:07 +03:00
/* Restore address registers. */
2005-06-24 09:01:16 +04:00
_ bbsi. l a2 , 1 , 1 f
l3 2 i a4 , a1 , P T _ A R E G 4
l3 2 i a5 , a1 , P T _ A R E G 5
l3 2 i a6 , a1 , P T _ A R E G 6
l3 2 i a7 , a1 , P T _ A R E G 7
_ bbsi. l a2 , 2 , 1 f
l3 2 i a8 , a1 , P T _ A R E G 8
l3 2 i a9 , a1 , P T _ A R E G 9
l3 2 i a10 , a1 , P T _ A R E G 1 0
l3 2 i a11 , a1 , P T _ A R E G 1 1
_ bbsi. l a2 , 3 , 1 f
l3 2 i a12 , a1 , P T _ A R E G 1 2
l3 2 i a13 , a1 , P T _ A R E G 1 3
l3 2 i a14 , a1 , P T _ A R E G 1 4
l3 2 i a15 , a1 , P T _ A R E G 1 5
/* Restore PC, SAR */
1 : l3 2 i a2 , a1 , P T _ P C
l3 2 i a3 , a1 , P T _ S A R
wsr a2 , E P C _ 1
wsr a3 , S A R
/* Restore LBEG, LEND, LCOUNT */
l3 2 i a2 , a1 , P T _ L B E G
l3 2 i a3 , a1 , P T _ L E N D
wsr a2 , L B E G
l3 2 i a2 , a1 , P T _ L C O U N T
wsr a3 , L E N D
wsr a2 , L C O U N T
2007-06-01 04:49:32 +04:00
/* We control single stepping through the ICOUNTLEVEL register. */
l3 2 i a2 , a1 , P T _ I C O U N T L E V E L
movi a3 , - 2
wsr a2 , I C O U N T L E V E L
wsr a3 , I C O U N T
2005-06-24 09:01:16 +04:00
/* Check if it was double exception. */
l3 2 i a0 , a1 , P T _ D E P C
l3 2 i a3 , a1 , P T _ A R E G 3
l3 2 i a2 , a1 , P T _ A R E G 2
_ bgeui a0 , V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S , 1 f
/* Restore a0...a3 and return */
l3 2 i a0 , a1 , P T _ A R E G 0
l3 2 i a1 , a1 , P T _ A R E G 1
rfe
1 : wsr a0 , D E P C
l3 2 i a0 , a1 , P T _ A R E G 0
l3 2 i a1 , a1 , P T _ A R E G 1
rfde
/ *
* Debug e x c e p t i o n h a n d l e r .
*
* Currently, w e d o n ' t s u p p o r t K G D B , s o o n l y u s e r a p p l i c a t i o n c a n b e d e b u g g e d .
*
* When w e g e t h e r e , a0 i s t r a s h e d a n d s a v e d t o e x c s a v e [ d e b u g l e v e l ]
* /
ENTRY( d e b u g _ e x c e p t i o n )
rsr a0 , E P S + X C H A L _ D E B U G L E V E L
2006-12-10 13:18:48 +03:00
bbsi. l a0 , P S _ E X C M _ B I T , 1 f # e x c e p t i o n m o d e
2005-06-24 09:01:16 +04:00
/* Set EPC_1 and EXCCAUSE */
wsr a2 , D E P C # s a v e a 2 t e m p o r a r i l y
rsr a2 , E P C + X C H A L _ D E B U G L E V E L
wsr a2 , E P C _ 1
movi a2 , E X C C A U S E _ M A P P E D _ D E B U G
wsr a2 , E X C C A U S E
/* Restore PS to the value before the debug exc but with PS.EXCM set.*/
2006-12-10 13:18:48 +03:00
movi a2 , 1 < < P S _ E X C M _ B I T
2005-06-24 09:01:16 +04:00
or a2 , a0 , a2
movi a0 , d e b u g _ e x c e p t i o n # r e s t o r e a 3 , d e b u g j u m p v e c t o r
wsr a2 , P S
xsr a0 , E X C S A V E + X C H A L _ D E B U G L E V E L
/* Switch to kernel/user stack, restore jump vector, and save a0 */
2006-12-10 13:18:48 +03:00
bbsi. l a2 , P S _ U M _ B I T , 2 f # j u m p i f u s e r m o d e
2005-06-24 09:01:16 +04:00
addi a2 , a1 , - 1 6 - P T _ S I Z E # a s s u m e k e r n e l s t a c k
s3 2 i a0 , a2 , P T _ A R E G 0
movi a0 , 0
s3 2 i a1 , a2 , P T _ A R E G 1
s3 2 i a0 , a2 , P T _ D E P C # m a r k i t a s a r e g u l a r e x c e p t i o n
xsr a0 , D E P C
s3 2 i a3 , a2 , P T _ A R E G 3
s3 2 i a0 , a2 , P T _ A R E G 2
mov a1 , a2
j _ k e r n e l _ e x c e p t i o n
2 : rsr a2 , E X C S A V E _ 1
l3 2 i a2 , a2 , E X C _ T A B L E _ K S T K # l o a d k e r n e l s t a c k p o i n t e r
s3 2 i a0 , a2 , P T _ A R E G 0
movi a0 , 0
s3 2 i a1 , a2 , P T _ A R E G 1
s3 2 i a0 , a2 , P T _ D E P C
xsr a0 , D E P C
s3 2 i a3 , a2 , P T _ A R E G 3
s3 2 i a0 , a2 , P T _ A R E G 2
mov a1 , a2
j _ u s e r _ e x c e p t i o n
/* Debug exception while in exception mode. */
1 : j 1 b / / F I X M E ! !
/ *
* We g e t h e r e i n c a s e o f a n u n r e c o v e r a b l e e x c e p t i o n .
* The o n l y t h i n g w e c a n d o i s t o b e n i c e a n d p r i n t a p a n i c m e s s a g e .
* We o n l y p r o d u c e a s i n g l e s t a c k f r a m e f o r p a n i c , s o ? ? ?
*
*
* Entry c o n d i t i o n s :
*
* - a0 c o n t a i n s t h e c a l l e r a d d r e s s ; original value saved in excsave1.
* - the o r i g i n a l a0 c o n t a i n s a v a l i d r e t u r n a d d r e s s ( b a c k t r a c e ) o r 0 .
* - a2 c o n t a i n s a v a l i d s t a c k p o i n t e r
*
* Notes :
*
* - If t h e s t a c k p o i n t e r c o u l d b e i n v a l i d , t h e c a l l e r h a s t o s e t u p a
* dummy s t a c k p o i n t e r ( e . g . t h e s t a c k o f t h e i n i t _ t a s k )
*
* - If t h e r e t u r n a d d r e s s c o u l d b e i n v a l i d , t h e c a l l e r h a s t o s e t i t
* to 0 , s o t h e b a c k t r a c e w o u l d s t o p .
*
* /
.align 4
unrecoverable_text :
.ascii " Unrecoverable e r r o r i n e x c e p t i o n h a n d l e r \ 0 "
ENTRY( u n r e c o v e r a b l e _ e x c e p t i o n )
movi a0 , 1
movi a1 , 0
wsr a0 , W I N D O W S T A R T
wsr a1 , W I N D O W B A S E
rsync
2006-12-10 13:18:48 +03:00
movi a1 , ( 1 < < P S _ W O E _ B I T ) | 1
2005-06-24 09:01:16 +04:00
wsr a1 , P S
rsync
movi a1 , i n i t _ t a s k
movi a0 , 0
addi a1 , a1 , P T _ R E G S _ O F F S E T
movi a4 , p a n i c
movi a6 , u n r e c o v e r a b l e _ t e x t
callx4 a4
1 : j 1 b
/* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
/ *
* Fast- h a n d l e r f o r a l l o c a e x c e p t i o n s
*
* The A L L O C A h a n d l e r i s e n t e r e d w h e n u s e r c o d e e x e c u t e s t h e M O V S P
* instruction a n d t h e c a l l e r ' s f r a m e i s n o t i n t h e r e g i s t e r f i l e .
* In t h i s c a s e , t h e c a l l e r f r a m e ' s a0 . . a3 a r e o n t h e s t a c k j u s t
* below s p ( a1 ) , a n d t h i s h a n d l e r m o v e s t h e m .
*
* For " M O V S P < a r > ,< a s > " w i t h o u t d e s t i n a t i o n r e g i s t e r a1 , t h i s r o u t i n e
* simply m o v e s t h e v a l u e f r o m < a s > t o < a r > w i t h o u t m o v i n g t h e s a v e a r e a .
*
* Entry c o n d i t i o n :
*
* a0 : trashed, o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ A R E G 0 )
* a1 : a1
* a2 : new s t a c k p o i n t e r , o r i g i n a l i n D E P C
* a3 : dispatch t a b l e
* depc : a2 , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ D E P C )
* excsave_1 : a3
*
* PT_ D E P C > = V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S : d o u b l e e x c e p t i o n , D E P C
* < VALID_DOUBLE_EXCEPTION_ADDRESS : regular e x c e p t i o n
* /
# if X C H A L _ H A V E _ B E
# define _ E X T U I _ M O V S P _ S R C ( a r ) e x t u i a r , a r , 4 , 4
# define _ E X T U I _ M O V S P _ D S T ( a r ) e x t u i a r , a r , 0 , 4
# else
# define _ E X T U I _ M O V S P _ S R C ( a r ) e x t u i a r , a r , 0 , 4
# define _ E X T U I _ M O V S P _ D S T ( a r ) e x t u i a r , a r , 4 , 4
# endif
ENTRY( f a s t _ a l l o c a )
/* We shouldn't be in a double exception. */
l3 2 i a0 , a2 , P T _ D E P C
_ bgeui a0 , V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S , . L u n h a n d l e d _ d o u b l e
rsr a0 , D E P C # g e t a 2
s3 2 i a4 , a2 , P T _ A R E G 4 # s a v e a 4 a n d
s3 2 i a0 , a2 , P T _ A R E G 2 # a 2 t o s t a c k
/* Exit critical section. */
movi a0 , 0
s3 2 i a0 , a3 , E X C _ T A B L E _ F I X U P
/* Restore a3, excsave_1 */
xsr a3 , E X C S A V E _ 1 # m a k e s u r e e x c s a v e _ 1 i s v a l i d f o r d b l .
rsr a4 , E P C _ 1 # g e t e x c e p t i o n a d d r e s s
s3 2 i a3 , a2 , P T _ A R E G 3 # s a v e a 3 t o s t a c k
# ifdef A L L O C A _ E X C E P T I O N _ I N _ I R A M
# error i r a m n o t s u p p o r t e d
# else
/* Note: l8ui not allowed in IRAM/IROM!! */
l8 u i a0 , a4 , 1 # r e a d a s ( s r c ) f r o m M O V S P i n s t r u c t i o n
# endif
movi a3 , . L m o v s p _ s r c
_ EXTUI_ M O V S P _ S R C ( a0 ) # e x t r a c t s o u r c e r e g i s t e r n u m b e r
addx8 a3 , a0 , a3
jx a3
.Lunhandled_double :
wsr a0 , E X C S A V E _ 1
movi a0 , u n r e c o v e r a b l e _ e x c e p t i o n
callx0 a0
.align 8
.Lmovsp_src :
l3 2 i a3 , a2 , P T _ A R E G 0 ; _j 1f; .align 8
mov a3 , a1 ; _j 1f; .align 8
l3 2 i a3 , a2 , P T _ A R E G 2 ; _j 1f; .align 8
l3 2 i a3 , a2 , P T _ A R E G 3 ; _j 1f; .align 8
l3 2 i a3 , a2 , P T _ A R E G 4 ; _j 1f; .align 8
mov a3 , a5 ; _j 1f; .align 8
mov a3 , a6 ; _j 1f; .align 8
mov a3 , a7 ; _j 1f; .align 8
mov a3 , a8 ; _j 1f; .align 8
mov a3 , a9 ; _j 1f; .align 8
mov a3 , a10 ; _j 1f; .align 8
mov a3 , a11 ; _j 1f; .align 8
mov a3 , a12 ; _j 1f; .align 8
mov a3 , a13 ; _j 1f; .align 8
mov a3 , a14 ; _j 1f; .align 8
mov a3 , a15 ; _j 1f; .align 8
1 :
# ifdef A L L O C A _ E X C E P T I O N _ I N _ I R A M
# error i r a m n o t s u p p o r t e d
# else
l8 u i a0 , a4 , 0 # r e a d a r ( d s t ) f r o m M O V S P i n s t r u c t i o n
# endif
addi a4 , a4 , 3 # s t e p o v e r m o v s p
_ EXTUI_ M O V S P _ D S T ( a0 ) # e x t r a c t d e s t i n a t i o n r e g i s t e r
wsr a4 , E P C _ 1 # s a v e n e w e p c _ 1
_ bnei a0 , 1 , 1 f # n o ' m o v s p a 1 , a x ' : j u m p
/ * Move t h e s a v e a r e a . T h i s i m p l i e s t h e u s e o f t h e L 3 2 E
* and S 3 2 E i n s t r u c t i o n s , b e c a u s e t h i s m o v e m u s t b e d o n e w i t h
* the u s e r ' s P S . R I N G p r i v i l e g e l e v e l s , n o t w i t h r i n g 0
* ( kernel' s ) p r i v i l e g e s c u r r e n t l y a c t i v e w i t h P S . E X C M
* set. N o t e t h a t w e h a v e s t i l r e g i s t e r e d a f i x u p r o u t i n e w i t h t h e
* double e x c e p t i o n v e c t o r i n c a s e a d o u b l e e x c e p t i o n o c c u r s .
* /
/* a0,a4:avail a1:old user stack a2:exc. stack a3:new user stack. */
l3 2 e a0 , a1 , - 1 6
l3 2 e a4 , a1 , - 1 2
s3 2 e a0 , a3 , - 1 6
s3 2 e a4 , a3 , - 1 2
l3 2 e a0 , a1 , - 8
l3 2 e a4 , a1 , - 4
s3 2 e a0 , a3 , - 8
s3 2 e a4 , a3 , - 4
/* Restore stack-pointer and all the other saved registers. */
mov a1 , a3
l3 2 i a4 , a2 , P T _ A R E G 4
l3 2 i a3 , a2 , P T _ A R E G 3
l3 2 i a0 , a2 , P T _ A R E G 0
l3 2 i a2 , a2 , P T _ A R E G 2
rfe
/ * MOVSP < a t > ,< a s > w a s i n v o k e d w i t h < a t > ! = a1 .
* Because t h e s t a c k p o i n t e r i s n o t b e i n g m o d i f i e d ,
* we s h o u l d b e a b l e t o j u s t m o d i f y t h e p o i n t e r
* without m o v i n g a n y s a v e a r e a .
* The p r o c e s s o r o n l y t r a p s t h e s e o c c u r r e n c e s i f t h e
* caller w i n d o w i s n ' t l i v e , s o u n f o r t u n a t e l y w e c a n ' t
* use t h i s a s a n a l t e r n a t e t r a p m e c h a n i s m .
* So w e j u s t d o t h e m o v e . T h i s r e q u i r e s t h a t w e
* resolve t h e d e s t i n a t i o n r e g i s t e r , n o t j u s t t h e s o u r c e ,
* so t h e r e ' s s o m e e x t r a w o r k .
* ( PERHAPS N O T R E A L L Y N E E D E D , B U T C L E A N E R . . . )
* /
/* a0 dst-reg, a1 user-stack, a2 stack, a3 value of src reg. */
1 : movi a4 , . L m o v s p _ d s t
addx8 a4 , a0 , a4
jx a4
.align 8
.Lmovsp_dst :
s3 2 i a3 , a2 , P T _ A R E G 0 ; _j 1f; .align 8
mov a1 , a3 ; _j 1f; .align 8
s3 2 i a3 , a2 , P T _ A R E G 2 ; _j 1f; .align 8
s3 2 i a3 , a2 , P T _ A R E G 3 ; _j 1f; .align 8
s3 2 i a3 , a2 , P T _ A R E G 4 ; _j 1f; .align 8
mov a5 , a3 ; _j 1f; .align 8
mov a6 , a3 ; _j 1f; .align 8
mov a7 , a3 ; _j 1f; .align 8
mov a8 , a3 ; _j 1f; .align 8
mov a9 , a3 ; _j 1f; .align 8
mov a10 , a3 ; _j 1f; .align 8
mov a11 , a3 ; _j 1f; .align 8
mov a12 , a3 ; _j 1f; .align 8
mov a13 , a3 ; _j 1f; .align 8
mov a14 , a3 ; _j 1f; .align 8
mov a15 , a3 ; _j 1f; .align 8
1 : l3 2 i a4 , a2 , P T _ A R E G 4
l3 2 i a3 , a2 , P T _ A R E G 3
l3 2 i a0 , a2 , P T _ A R E G 0
l3 2 i a2 , a2 , P T _ A R E G 2
rfe
/ *
* fast s y s t e m c a l l s .
*
* WARNING : The k e r n e l d o e s n ' t s a v e t h e e n t i r e u s e r c o n t e x t b e f o r e
* handling a f a s t s y s t e m c a l l . T h e s e f u n c t i o n s a r e s m a l l a n d s h o r t ,
* usually o f f e r i n g s o m e f u n c t i o n a l i t y n o t a v a i l a b l e t o u s e r t a s k s .
*
* BE C A R E F U L T O P R E S E R V E T H E U S E R ' S C O N T E X T .
*
* Entry c o n d i t i o n :
*
* a0 : trashed, o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ A R E G 0 )
* a1 : a1
* a2 : new s t a c k p o i n t e r , o r i g i n a l i n D E P C
* a3 : dispatch t a b l e
* depc : a2 , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ D E P C )
* excsave_1 : a3
* /
ENTRY( f a s t _ s y s c a l l _ k e r n e l )
/* Skip syscall. */
rsr a0 , E P C _ 1
addi a0 , a0 , 3
wsr a0 , E P C _ 1
l3 2 i a0 , a2 , P T _ D E P C
bgeui a0 , V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S , f a s t _ s y s c a l l _ u n r e c o v e r a b l e
rsr a0 , D E P C # g e t s y s c a l l - n r
_ beqz a0 , f a s t _ s y s c a l l _ s p i l l _ r e g i s t e r s
2006-12-10 13:18:52 +03:00
_ beqi a0 , _ _ N R _ x t e n s a , f a s t _ s y s c a l l _ x t e n s a
2005-06-24 09:01:16 +04:00
j k e r n e l _ e x c e p t i o n
ENTRY( f a s t _ s y s c a l l _ u s e r )
/* Skip syscall. */
rsr a0 , E P C _ 1
addi a0 , a0 , 3
wsr a0 , E P C _ 1
l3 2 i a0 , a2 , P T _ D E P C
bgeui a0 , V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S , f a s t _ s y s c a l l _ u n r e c o v e r a b l e
rsr a0 , D E P C # g e t s y s c a l l - n r
_ beqz a0 , f a s t _ s y s c a l l _ s p i l l _ r e g i s t e r s
2006-12-10 13:18:52 +03:00
_ beqi a0 , _ _ N R _ x t e n s a , f a s t _ s y s c a l l _ x t e n s a
2005-06-24 09:01:16 +04:00
j u s e r _ e x c e p t i o n
ENTRY( f a s t _ s y s c a l l _ u n r e c o v e r a b l e )
/* Restore all states. */
l3 2 i a0 , a2 , P T _ A R E G 0 # r e s t o r e a 0
xsr a2 , D E P C # r e s t o r e a 2 , d e p c
rsr a3 , E X C S A V E _ 1
wsr a0 , E X C S A V E _ 1
movi a0 , u n r e c o v e r a b l e _ e x c e p t i o n
callx0 a0
/ *
* sysxtensa s y s c a l l h a n d l e r
*
2006-12-10 13:18:52 +03:00
* int s y s x t e n s a ( S Y S _ X T E N S A _ A T O M I C _ S E T , p t r , v a l , u n u s e d ) ;
* int s y s x t e n s a ( S Y S _ X T E N S A _ A T O M I C _ A D D , p t r , v a l , u n u s e d ) ;
* int s y s x t e n s a ( S Y S _ X T E N S A _ A T O M I C _ E X G _ A D D , p t r , v a l , u n u s e d ) ;
* int s y s x t e n s a ( S Y S _ X T E N S A _ A T O M I C _ C M P _ S W P , p t r , o l d v a l , n e w v a l ) ;
* a2 a6 a3 a4 a5
2005-06-24 09:01:16 +04:00
*
* Entry c o n d i t i o n :
*
2006-12-10 13:18:52 +03:00
* a0 : a2 ( s y s c a l l - n r ) , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ A R E G 0 )
2005-06-24 09:01:16 +04:00
* a1 : a1
2006-12-10 13:18:52 +03:00
* a2 : new s t a c k p o i n t e r , o r i g i n a l i n a0 a n d D E P C
* a3 : dispatch t a b l e , o r i g i n a l i n e x c s a v e _ 1
* a4 . . a15 : u n c h a n g e d
2005-06-24 09:01:16 +04:00
* depc : a2 , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ D E P C )
* excsave_1 : a3
*
* PT_ D E P C > = V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S : d o u b l e e x c e p t i o n , D E P C
* < VALID_DOUBLE_EXCEPTION_ADDRESS : regular e x c e p t i o n
*
* Note : we d o n ' t h a v e t o s a v e a2 ; a2 holds the return value
*
* We u s e t h e t w o m a c r o s T R Y a n d C A T C H :
*
* TRY a d d s a n e n t r y t o t h e _ _ e x _ t a b l e f i x u p t a b l e f o r t h e i m m e d i a t e l y
* following i n s t r u c t i o n .
*
* CATCH c a t c h e s a n y e x c e p t i o n t h a t o c c u r r e d a t o n e o f t h e p r e c e e d i n g T R Y
* statements a n d c o n t i n u e s f r o m t h e r e
*
* Usage T R Y l 3 2 i a0 , a1 , 0
* < other c o d e >
* done : rfe
* CATCH < s e t r e t u r n c o d e >
* j d o n e
* /
# define T R Y \
.section _ _ ex_ t a b l e , " a " ; \
.word 6 6 f, 6 7 f ; \
.text ; \
66 :
# define C A T C H \
67 :
2006-12-10 13:18:52 +03:00
ENTRY( f a s t _ s y s c a l l _ x t e n s a )
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
xsr a3 , E X C S A V E _ 1 # r e s t o r e a 3 , e x c s a v e 1
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
s3 2 i a7 , a2 , P T _ A R E G 7 # w e n e e d a n a d d i t i o n a l r e g i s t e r
2005-06-24 09:01:16 +04:00
movi a7 , 4 # s i z e o f ( u n s i g n e d i n t )
2006-12-10 13:18:52 +03:00
access_ o k a3 , a7 , a0 , a2 , . L e a c # a 0 : s c r a t c h r e g , a2 : s p
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
addi a6 , a6 , - 1 # a s s u m i n g S Y S _ X T E N S A _ A T O M I C _ S E T = 1
_ bgeui a6 , S Y S _ X T E N S A _ C O U N T - 1 , . L i l l
_ bnei a6 , S Y S _ X T E N S A _ A T O M I C _ C M P _ S W P - 1 , . L n s w p
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
/* Fall through for ATOMIC_CMP_SWP. */
2005-06-24 09:01:16 +04:00
.Lswp : /* Atomic compare and swap */
2006-12-10 13:18:52 +03:00
TRY l 3 2 i a0 , a3 , 0 # r e a d o l d v a l u e
bne a0 , a4 , 1 f # s a m e a s o l d v a l u e ? j u m p
TRY s32 i a5 , a3 , 0 # d i f f e r e n t , m o d i f y v a l u e
l3 2 i a7 , a2 , P T _ A R E G 7 # r e s t o r e a 7
l3 2 i a0 , a2 , P T _ A R E G 0 # r e s t o r e a 0
movi a2 , 1 # a n d r e t u r n 1
addi a6 , a6 , 1 # r e s t o r e a 6 ( r e a l l y n e c e s s a r y ? )
rfe
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
1 : l3 2 i a7 , a2 , P T _ A R E G 7 # r e s t o r e a 7
l3 2 i a0 , a2 , P T _ A R E G 0 # r e s t o r e a 0
movi a2 , 0 # r e t u r n 0 ( n o t e t h a t w e c a n n o t s e t
addi a6 , a6 , 1 # r e s t o r e a 6 ( r e a l l y n e c e s s a r y ? )
rfe
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
.Lnswp : /* Atomic set, add, and exg_add. */
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
TRY l 3 2 i a7 , a3 , 0 # o r i g
add a0 , a4 , a7 # + a r g
moveqz a0 , a4 , a6 # s e t
TRY s32 i a0 , a3 , 0 # w r i t e n e w v a l u e
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
mov a0 , a2
2005-06-24 09:01:16 +04:00
mov a2 , a7
2006-12-10 13:18:52 +03:00
l3 2 i a7 , a0 , P T _ A R E G 7 # r e s t o r e a 7
l3 2 i a0 , a0 , P T _ A R E G 0 # r e s t o r e a 0
addi a6 , a6 , 1 # r e s t o r e a 6 ( r e a l l y n e c e s s a r y ? )
2005-06-24 09:01:16 +04:00
rfe
CATCH
2006-12-10 13:18:52 +03:00
.Leac : l3 2 i a7 , a2 , P T _ A R E G 7 # r e s t o r e a 7
l3 2 i a0 , a2 , P T _ A R E G 0 # r e s t o r e a 0
movi a2 , - E F A U L T
rfe
.Lill : l3 2 i a7 , a2 , P T _ A R E G 0 # r e s t o r e a 7
l3 2 i a0 , a2 , P T _ A R E G 0 # r e s t o r e a 0
movi a2 , - E I N V A L
rfe
2005-06-24 09:01:16 +04:00
/ * fast_ s y s c a l l _ s p i l l _ r e g i s t e r s .
*
* Entry c o n d i t i o n :
*
* a0 : trashed, o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ A R E G 0 )
* a1 : a1
* a2 : new s t a c k p o i n t e r , o r i g i n a l i n D E P C
* a3 : dispatch t a b l e
* depc : a2 , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ D E P C )
* excsave_1 : a3
*
* Note : We a s s u m e t h e s t a c k p o i n t e r i s E X C _ T A B L E _ K S T K i n t h e f i x u p h a n d l e r .
* /
ENTRY( f a s t _ s y s c a l l _ s p i l l _ r e g i s t e r s )
/* Register a FIXUP handler (pass current wb as a parameter) */
movi a0 , f a s t _ s y s c a l l _ s p i l l _ r e g i s t e r s _ f i x u p
s3 2 i a0 , a3 , E X C _ T A B L E _ F I X U P
rsr a0 , W I N D O W B A S E
s3 2 i a0 , a3 , E X C _ T A B L E _ P A R A M
/* Save a3 and SAR on stack. */
rsr a0 , S A R
xsr a3 , E X C S A V E _ 1 # r e s t o r e a 3 a n d e x c s a v e _ 1
s3 2 i a3 , a2 , P T _ A R E G 3
2008-02-13 00:17:07 +03:00
s3 2 i a4 , a2 , P T _ A R E G 4
s3 2 i a0 , a2 , P T _ A R E G 5 # s t o r e S A R t o P T _ A R E G 5
2005-06-24 09:01:16 +04:00
/* The spill routine might clobber a7, a11, and a15. */
2008-02-13 00:17:07 +03:00
s3 2 i a7 , a2 , P T _ A R E G 7
s3 2 i a11 , a2 , P T _ A R E G 1 1
s3 2 i a15 , a2 , P T _ A R E G 1 5
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
call0 _ s p i l l _ r e g i s t e r s # d e s t r o y s a 3 , a4 , a n d S A R
2005-06-24 09:01:16 +04:00
/* Advance PC, restore registers and SAR, and return from exception. */
2008-02-13 00:17:07 +03:00
l3 2 i a3 , a2 , P T _ A R E G 5
l3 2 i a4 , a2 , P T _ A R E G 4
2005-06-24 09:01:16 +04:00
l3 2 i a0 , a2 , P T _ A R E G 0
wsr a3 , S A R
l3 2 i a3 , a2 , P T _ A R E G 3
/* Restore clobbered registers. */
2008-02-13 00:17:07 +03:00
l3 2 i a7 , a2 , P T _ A R E G 7
l3 2 i a11 , a2 , P T _ A R E G 1 1
l3 2 i a15 , a2 , P T _ A R E G 1 5
2005-06-24 09:01:16 +04:00
movi a2 , 0
rfe
/ * Fixup h a n d l e r .
*
* We g e t h e r e i f t h e s p i l l r o u t i n e c a u s e s a n e x c e p t i o n , e . g . t l b m i s s .
* We b a s i c a l l y r e s t o r e W I N D O W B A S E a n d W I N D O W S T A R T t o t h e c o n d i t i o n w h e n
* we e n t e r e d t h e s p i l l r o u t i n e a n d j u m p t o t h e u s e r e x c e p t i o n h a n d l e r .
*
* a0 : value o f d e p c , o r i g i n a l v a l u e i n d e p c
* a2 : trashed, o r i g i n a l v a l u e i n E X C _ T A B L E _ D O U B L E _ S A V E
* a3 : exctable, o r i g i n a l v a l u e i n e x c s a v e 1
* /
fast_syscall_spill_registers_fixup :
rsr a2 , W I N D O W B A S E # g e t c u r r e n t w i n d o w b a s e ( a 2 i s s a v e d )
xsr a0 , D E P C # r e s t o r e d e p c a n d a 0
ssl a2 # s e t s h i f t ( 32 - W B )
/ * We n e e d t o m a k e s u r e t h e c u r r e n t r e g i s t e r s ( a0 - a3 ) a r e p r e s e r v e d .
* To d o t h i s , w e s i m p l y s e t t h e b i t f o r t h e c u r r e n t w i n d o w f r a m e
* in W S , s o t h a t t h e e x c e p t i o n h a n d l e r s s a v e t h e m t o t h e t a s k s t a c k .
* /
rsr a3 , E X C S A V E _ 1 # g e t s p i l l - m a s k
slli a2 , a3 , 1 # s h i f t l e f t b y o n e
slli a3 , a2 , 3 2 - W S B I T S
src a2 , a2 , a3 # a 1 = x x w w w1 y y x x x w w w1 y y . . . . . .
wsr a2 , W I N D O W S T A R T # s e t c o r r e c t e d w i n d o w s t a r t
movi a3 , e x c _ t a b l e
l3 2 i a2 , a3 , E X C _ T A B L E _ D O U B L E _ S A V E # r e s t o r e a 2
l3 2 i a3 , a3 , E X C _ T A B L E _ P A R A M # o r i g i n a l W B ( i n u s e r t a s k )
/ * Return t o t h e o r i g i n a l ( u s e r t a s k ) W I N D O W B A S E .
* We l e a v e t h e f o l l o w i n g f r a m e b e h i n d :
* a0 , a1 , a2 s a m e
* a3 : trashed ( s a v e d i n e x c s a v e _ 1 )
* depc : depc ( w e h a v e t o r e t u r n t o t h a t a d d r e s s )
* excsave_1 : a3
* /
wsr a3 , W I N D O W B A S E
rsync
/ * We a r e n o w i n t h e o r i g i n a l f r a m e w h e n w e e n t e r e d _ s p i l l _ r e g i s t e r s :
* a0 : return a d d r e s s
* a1 : used, s t a c k p o i n t e r
* a2 : kernel s t a c k p o i n t e r
* a3 : available, s a v e d i n E X C S A V E _ 1
* depc : exception a d d r e s s
* excsave : a3
* Note : This f r a m e m i g h t b e t h e s a m e a s a b o v e .
* /
/* Setup stack pointer. */
addi a2 , a2 , - P T _ U S E R _ S I Z E
s3 2 i a0 , a2 , P T _ A R E G 0
/* Make sure we return to this fixup handler. */
movi a3 , f a s t _ s y s c a l l _ s p i l l _ r e g i s t e r s _ f i x u p _ r e t u r n
s3 2 i a3 , a2 , P T _ D E P C # s e t u p d e p c
/* Jump to the exception handler. */
movi a3 , e x c _ t a b l e
rsr a0 , E X C C A U S E
2008-02-13 00:17:07 +03:00
addx4 a0 , a0 , a3 # f i n d e n t r y i n t a b l e
l3 2 i a0 , a0 , E X C _ T A B L E _ F A S T _ U S E R # l o a d h a n d l e r
jx a0
2005-06-24 09:01:16 +04:00
fast_syscall_spill_registers_fixup_return :
/* When we return here, all registers have been restored (a2: DEPC) */
wsr a2 , D E P C # e x c e p t i o n a d d r e s s
/* Restore fixup handler. */
xsr a3 , E X C S A V E _ 1
movi a2 , f a s t _ s y s c a l l _ s p i l l _ r e g i s t e r s _ f i x u p
s3 2 i a2 , a3 , E X C _ T A B L E _ F I X U P
rsr a2 , W I N D O W B A S E
s3 2 i a2 , a3 , E X C _ T A B L E _ P A R A M
l3 2 i a2 , a3 , E X C _ T A B L E _ K S T K
/* Load WB at the time the exception occurred. */
rsr a3 , S A R # W B i s s t i l l i n S A R
neg a3 , a3
wsr a3 , W I N D O W B A S E
rsync
/* Restore a3 and return. */
movi a3 , e x c _ t a b l e
xsr a3 , E X C S A V E _ 1
rfde
/ *
* spill a l l r e g i s t e r s .
*
* This i s n o t a r e a l f u n c t i o n . T h e f o l l o w i n g c o n d i t i o n s m u s t b e m e t :
*
* - must b e c a l l e d w i t h c a l l 0 .
2008-02-13 00:17:07 +03:00
* - uses a3 , a4 a n d S A R .
2005-06-24 09:01:16 +04:00
* - the l a s t ' v a l i d ' r e g i s t e r o f e a c h f r a m e a r e c l o b b e r e d .
* - the c a l l e r m u s t h a v e r e g i s t e r e d a f i x u p h a n d l e r
* ( or b e i n s i d e a c r i t i c a l s e c t i o n )
* - PS_ E X C M m u s t b e s e t ( P S _ W O E c l e a r e d ? )
* /
ENTRY( _ s p i l l _ r e g i s t e r s )
/ *
* Rotate w s s o t h a t t h e c u r r e n t w i n d o w b a s e i s a t b i t 0 .
* Assume w s = x x x w w w1 y y ( w w w1 c u r r e n t w i n d o w f r a m e ) .
2008-02-13 00:17:07 +03:00
* Rotate w s r i g h t s o t h a t a4 = y y x x x w w w1 .
2005-06-24 09:01:16 +04:00
* /
2008-02-13 00:17:07 +03:00
rsr a4 , W I N D O W B A S E
2008-01-09 20:22:36 +03:00
rsr a3 , W I N D O W S T A R T # a 3 = x x x w w w1 y y
2008-02-13 00:17:07 +03:00
ssr a4 # h o l d s W B
slli a4 , a3 , W S B I T S
or a3 , a3 , a4 # a 3 = x x x w w w1 y y x x x w w w1 y y
2008-01-09 20:22:36 +03:00
srl a3 , a3 # a 3 = 0 0 x x x w w w1 y y x x x w w w1
2005-06-24 09:01:16 +04:00
/* We are done if there are no more than the current register frame. */
2007-11-15 00:47:02 +03:00
extui a3 , a3 , 1 , W S B I T S - 1 # a 3 = 0 y y x x x w w w
2008-02-13 00:17:07 +03:00
movi a4 , ( 1 < < ( W S B I T S - 1 ) )
2005-06-24 09:01:16 +04:00
_ beqz a3 , . L n o s p i l l # o n l y o n e a c t i v e f r a m e ? j u m p
/* We want 1 at the top, so that we return to the current windowbase */
2008-02-13 00:17:07 +03:00
or a3 , a3 , a4 # 1 y y x x x w w w
2005-06-24 09:01:16 +04:00
/* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
wsr a3 , W I N D O W S T A R T # s a v e s h i f t e d w i n d o w s t a r t
2008-02-13 00:17:07 +03:00
neg a4 , a3
and a3 , a4 , a3 # f i r s t b i t s e t f r o m r i g h t : 000010000
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
ffs_ w s a4 , a3 # a 4 : s h i f t s t o s k i p e m p t y f r a m e s
2005-06-24 09:01:16 +04:00
movi a3 , W S B I T S
2008-02-13 00:17:07 +03:00
sub a4 , a3 , a4 # W S B I T S - a 4 : n u m b e r o f 0 - b i t s f r o m r i g h t
ssr a4 # s a v e i n S A R f o r l a t e r .
2005-06-24 09:01:16 +04:00
rsr a3 , W I N D O W B A S E
2008-02-13 00:17:07 +03:00
add a3 , a3 , a4
2005-06-24 09:01:16 +04:00
wsr a3 , W I N D O W B A S E
rsync
rsr a3 , W I N D O W S T A R T
srl a3 , a3 # s h i f t w i n d o w s t a r t
/ * WB i s n o w j u s t o n e f r a m e b e l o w t h e o l d e s t f r a m e i n t h e r e g i s t e r
window. W S i s s h i f t e d s o t h e o l d e s t f r a m e i s i n b i t 0 , t h u s , W B
and W S d i f f e r b y o n e 4 - r e g i s t e r f r a m e . * /
/ * Save f r a m e s . D e p e n d i n g w h a t c a l l w a s u s e d ( c a l l 4 , c a l l 8 , c a l l 1 2 ) ,
* we h a v e t o s a v e 4 ,8 . o r 1 2 r e g i s t e r s .
* /
_ bbsi. l a3 , 1 , . L c4
_ bbsi. l a3 , 2 , . L c8
/* Special case: we have a call12-frame starting at a4. */
_ bbci. l a3 , 3 , . L c12 # b i t 3 s h o u l d n ' t b e z e r o ! ( J u m p t o L c12 f i r s t )
s3 2 e a4 , a1 , - 1 6 # a 1 i s v a l i d w i t h a n e m p t y s p i l l a r e a
l3 2 e a4 , a5 , - 1 2
s3 2 e a8 , a4 , - 4 8
mov a8 , a4
l3 2 e a4 , a1 , - 1 6
j . L c12 c
2007-11-15 00:47:02 +03:00
.Lnospill :
2008-01-09 20:22:36 +03:00
ret
2007-11-15 00:47:02 +03:00
2005-06-24 09:01:16 +04:00
.Lloop : _ bbsi. l a3 , 1 , . L c4
_ bbci. l a3 , 2 , . L c12
.Lc8 : s3 2 e a4 , a13 , - 1 6
l3 2 e a4 , a5 , - 1 2
s3 2 e a8 , a4 , - 3 2
s3 2 e a5 , a13 , - 1 2
s3 2 e a6 , a13 , - 8
s3 2 e a7 , a13 , - 4
s3 2 e a9 , a4 , - 2 8
s3 2 e a10 , a4 , - 2 4
s3 2 e a11 , a4 , - 2 0
srli a11 , a3 , 2 # s h i f t w i n d o w b a s e b y 2
rotw 2
_ bnei a3 , 1 , . L l o o p
.Lexit : /* Done. Do the final rotation, set WS, and return. */
rotw 1
rsr a3 , W I N D O W B A S E
ssl a3
movi a3 , 1
sll a3 , a3
wsr a3 , W I N D O W S T A R T
2008-01-09 20:22:36 +03:00
ret
2005-06-24 09:01:16 +04:00
.Lc4 : s3 2 e a4 , a9 , - 1 6
s3 2 e a5 , a9 , - 1 2
s3 2 e a6 , a9 , - 8
s3 2 e a7 , a9 , - 4
srli a7 , a3 , 1
rotw 1
_ bnei a3 , 1 , . L l o o p
j . L e x i t
.Lc12 : _ bbci. l a3 , 3 , . L i n v a l i d _ m a s k # b i t 2 s h o u l d n ' t b e z e r o !
/* 12-register frame (call12) */
l3 2 e a2 , a5 , - 1 2
s3 2 e a8 , a2 , - 4 8
mov a8 , a2
.Lc12c : s3 2 e a9 , a8 , - 4 4
s3 2 e a10 , a8 , - 4 0
s3 2 e a11 , a8 , - 3 6
s3 2 e a12 , a8 , - 3 2
s3 2 e a13 , a8 , - 2 8
s3 2 e a14 , a8 , - 2 4
s3 2 e a15 , a8 , - 2 0
srli a15 , a3 , 3
/ * The s t a c k p o i n t e r f o r a4 . . a7 i s o u t o f r e a c h , s o w e r o t a t e t h e
* window, g r a b t h e s t a c k p o i n t e r , a n d r o t a t e b a c k .
* Alternatively, w e c o u l d a l s o u s e t h e f o l l o w i n g a p p r o a c h , b u t t h a t
* makes t h e f i x u p r o u t i n e m u c h m o r e c o m p l i c a t e d :
* rotw 1
* s3 2 e a0 , a13 , - 1 6
* . . .
* rotw 2
* /
rotw 1
mov a5 , a13
rotw - 1
s3 2 e a4 , a9 , - 1 6
s3 2 e a5 , a9 , - 1 2
s3 2 e a6 , a9 , - 8
s3 2 e a7 , a9 , - 4
rotw 3
_ beqi a3 , 1 , . L e x i t
j . L l o o p
.Linvalid_mask :
/ * We g e t h e r e b e c a u s e o f a n u n r e c o v e r a b l e e r r o r i n t h e w i n d o w
* registers. I f w e a r e i n u s e r s p a c e , w e k i l l t h e a p p l i c a t i o n ,
* however, t h i s c o n d i t i o n i s u n r e c o v e r a b l e i n k e r n e l s p a c e .
* /
rsr a0 , P S
2006-12-10 13:18:48 +03:00
_ bbci. l a0 , P S _ U M _ B I T , 1 f
2005-06-24 09:01:16 +04:00
/ * User s p a c e : S e t u p a d u m m y f r a m e a n d k i l l a p p l i c a t i o n .
* Note : We a s s u m e E X C _ T A B L E _ K S T K c o n t a i n s a v a l i d s t a c k p o i n t e r .
* /
movi a0 , 1
movi a1 , 0
wsr a0 , W I N D O W S T A R T
wsr a1 , W I N D O W B A S E
rsync
movi a0 , 0
movi a3 , e x c _ t a b l e
l3 2 i a1 , a3 , E X C _ T A B L E _ K S T K
wsr a3 , E X C S A V E _ 1
2006-12-10 13:18:48 +03:00
movi a4 , ( 1 < < P S _ W O E _ B I T ) | 1
2005-06-24 09:01:16 +04:00
wsr a4 , P S
rsync
movi a6 , S I G S E G V
movi a4 , d o _ e x i t
callx4 a4
1 : /* Kernel space: PANIC! */
wsr a0 , E X C S A V E _ 1
movi a0 , u n r e c o v e r a b l e _ e x c e p t i o n
callx0 a0 # s h o u l d n o t r e t u r n
1 : j 1 b
2009-03-04 18:21:31 +03:00
# ifdef C O N F I G _ M M U
2005-06-24 09:01:16 +04:00
/ *
* We s h o u l d n e v e r g e t h e r e . B a i l o u t !
* /
ENTRY( f a s t _ s e c o n d _ l e v e l _ m i s s _ d o u b l e _ k e r n e l )
1 : movi a0 , u n r e c o v e r a b l e _ e x c e p t i o n
callx0 a0 # s h o u l d n o t r e t u r n
1 : j 1 b
/ * First- l e v e l e n t r y h a n d l e r f o r u s e r , k e r n e l , a n d d o u b l e 2 n d - l e v e l
* TLB m i s s e x c e p t i o n s . N o t e t h a t f o r n o w , u s e r a n d k e r n e l m i s s
* exceptions s h a r e t h e s a m e e n t r y p o i n t a n d a r e h a n d l e d i d e n t i c a l l y .
*
* An o l d , l e s s - e f f i c i e n t C v e r s i o n o f t h i s f u n c t i o n u s e d t o e x i s t .
* We i n c l u d e i t b e l o w , i n t e r l e a v e d a s c o m m e n t s , f o r r e f e r e n c e .
*
* Entry c o n d i t i o n :
*
* a0 : trashed, o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ A R E G 0 )
* a1 : a1
* a2 : new s t a c k p o i n t e r , o r i g i n a l i n D E P C
* a3 : dispatch t a b l e
* depc : a2 , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ D E P C )
* excsave_1 : a3
*
* PT_ D E P C > = V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S : d o u b l e e x c e p t i o n , D E P C
* < VALID_DOUBLE_EXCEPTION_ADDRESS : regular e x c e p t i o n
* /
ENTRY( f a s t _ s e c o n d _ l e v e l _ m i s s )
/* Save a1. Note: we don't expect a double exception. */
s3 2 i a1 , a2 , P T _ A R E G 1
/ * We n e e d t o m a p t h e p a g e o f P T E s f o r t h e u s e r t a s k . F i n d
* the p o i n t e r t o t h a t p a g e . A l s o , i t ' s p o s s i b l e f o r t s k - > m m
* to b e N U L L w h i l e t s k - > a c t i v e _ m m i s n o n z e r o i f w e f a u l t e d o n
* a v m a l l o c a d d r e s s . I n t h a t r a r e c a s e , w e m u s t u s e
* active_ m m i n s t e a d t o a v o i d a f a u l t i n t h i s h a n d l e r . S e e
*
* http : / / mail. n l . l i n u x . o r g / l i n u x - m m / 2 0 0 2 - 0 8 / m s g 0 0 2 5 8 . h t m l
* ( or s e a r c h I n t e r n e t o n " m m v s . a c t i v e _ m m " )
*
* if ( ! m m )
* mm = t s k - > a c t i v e _ m m ;
* pgd = p g d _ o f f s e t ( m m , r e g s - > e x c v a d d r ) ;
* pmd = p m d _ o f f s e t ( p g d , r e g s - > e x c v a d d r ) ;
* pmdval = * p m d ;
* /
GET_ C U R R E N T ( a1 ,a2 )
l3 2 i a0 , a1 , T A S K _ M M # t s k - > m m
beqz a0 , 9 f
2007-08-07 10:57:57 +04:00
/* We deliberately destroy a3 that holds the exception table. */
8 : rsr a3 , E X C V A D D R # f a u l t a d d r e s s
_ PGD_ O F F S E T ( a0 , a3 , a1 )
2005-06-24 09:01:16 +04:00
l3 2 i a0 , a0 , 0 # r e a d p m d v a l
beqz a0 , 2 f
/ * Read p t e v a d d r a n d c o n v e r t t o t o p o f p a g e - t a b l e p a g e .
*
* vpnval = r e a d _ p t e v a d d r _ r e g i s t e r ( ) & P A G E _ M A S K ;
* vpnval + = D T L B _ W A Y _ P G T A B L E ;
* pteval = m k _ p t e ( v i r t _ t o _ p a g e ( p m d _ v a l ( p m d v a l ) ) , P A G E _ K E R N E L ) ;
* write_ d t l b _ e n t r y ( p t e v a l , v p n v a l ) ;
*
* The m e s s y c o m p u t a t i o n f o r ' p t e v a l ' a b o v e r e a l l y s i m p l i f i e s
* into t h e f o l l o w i n g :
*
2007-08-22 21:14:51 +04:00
* pteval = ( ( p m d v a l - P A G E _ O F F S E T ) & P A G E _ M A S K ) | P A G E _ D I R E C T O R Y
2005-06-24 09:01:16 +04:00
* /
movi a1 , - P A G E _ O F F S E T
add a0 , a0 , a1 # p m d v a l - P A G E _ O F F S E T
extui a1 , a0 , 0 , P A G E _ S H I F T # . . . & P A G E _ M A S K
xor a0 , a0 , a1
2007-08-07 10:57:57 +04:00
movi a1 , _ P A G E _ D I R E C T O R Y
2005-06-24 09:01:16 +04:00
or a0 , a0 , a1 # . . . | P A G E _ D I R E C T O R Y
2007-08-07 10:57:57 +04:00
/ *
2007-08-22 21:14:51 +04:00
* We u t i l i z e a l l t h r e e w i r e d - w a y s ( 7 - 9 ) t o h o l d p m d t r a n s l a t i o n s .
2007-08-07 10:57:57 +04:00
* Memory r e g i o n s a r e m a p p e d t o t h e D T L B s a c c o r d i n g t o b i t s 2 8 a n d 2 9 .
* This a l l o w s t o m a p t h e t h r e e m o s t c o m m o n r e g i o n s t o t h r e e d i f f e r e n t
* DTLBs :
* 0 , 1 - > way 7 p r o g r a m ( 0 0 4 0 . 0 0 0 0 ) a n d v i r t u a l ( c00 0 . 0 0 0 0 )
* 2 - > way 8 s h a r e d l i b a r i e s ( 2 0 0 0 . 0 0 0 0 )
* 3 - > way 0 s t a c k ( 3 0 0 0 . 0 0 0 0 )
* /
extui a3 , a3 , 2 8 , 2 # a d d r . b i t 28 a n d 2 9 0 ,1 ,2 ,3
2005-06-24 09:01:16 +04:00
rsr a1 , P T E V A D D R
2007-08-07 10:57:57 +04:00
addx2 a3 , a3 , a3 # - > 0 ,3 ,6 ,9
2005-06-24 09:01:16 +04:00
srli a1 , a1 , P A G E _ S H I F T
2007-08-07 10:57:57 +04:00
extui a3 , a3 , 2 , 2 # - > 0 ,0 ,1 ,2
2005-06-24 09:01:16 +04:00
slli a1 , a1 , P A G E _ S H I F T # p t e v a d d r & P A G E _ M A S K
2007-08-07 10:57:57 +04:00
addi a3 , a3 , D T L B _ W A Y _ P G D
add a1 , a1 , a3 # . . . + w a y _ n u m b e r
2005-06-24 09:01:16 +04:00
2007-08-07 10:57:57 +04:00
3 : wdtlb a0 , a1
2005-06-24 09:01:16 +04:00
dsync
/* Exit critical section. */
2007-08-07 10:57:57 +04:00
4 : movi a3 , e x c _ t a b l e # r e s t o r e a 3
2005-06-24 09:01:16 +04:00
movi a0 , 0
s3 2 i a0 , a3 , E X C _ T A B L E _ F I X U P
/* Restore the working registers, and return. */
l3 2 i a0 , a2 , P T _ A R E G 0
l3 2 i a1 , a2 , P T _ A R E G 1
l3 2 i a2 , a2 , P T _ D E P C
xsr a3 , E X C S A V E _ 1
bgeui a2 , V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S , 1 f
/* Restore excsave1 and return. */
rsr a2 , D E P C
rfe
/* Return from double exception. */
1 : xsr a2 , D E P C
esync
rfde
9 : l3 2 i a0 , a1 , T A S K _ A C T I V E _ M M # u n l i k e l y c a s e m m = = 0
j 8 b
2007-08-22 21:14:51 +04:00
# if ( D C A C H E _ W A Y _ S I Z E > P A G E _ S I Z E )
2 : / * Special c a s e f o r c a c h e a l i a s i n g .
* We ( s h o u l d ) o n l y g e t h e r e i f a c l e a r _ u s e r _ p a g e , c o p y _ u s e r _ p a g e
* or t h e a l i a s e d c a c h e f l u s h f u n c t i o n s g o t p r e e m p t i v e l y i n t e r r u p t e d
* by a n o t h e r t a s k . R e - e s t a b l i s h t e m p o r a r y m a p p i n g t o t h e
* TLBTEMP_ B A S E a r e a s .
* /
/* We shouldn't be in a double exception */
l3 2 i a0 , a2 , P T _ D E P C
bgeui a0 , V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S , 2 f
/* Make sure the exception originated in the special functions */
movi a0 , _ _ t l b t e m p _ m a p p i n g _ s t a r t
rsr a3 , E P C _ 1
bltu a3 , a0 , 2 f
movi a0 , _ _ t l b t e m p _ m a p p i n g _ e n d
bgeu a3 , a0 , 2 f
/* Check if excvaddr was in one of the TLBTEMP_BASE areas. */
movi a3 , T L B T E M P _ B A S E _ 1
rsr a0 , E X C V A D D R
bltu a0 , a3 , 2 f
addi a1 , a0 , - ( 2 < < ( D C A C H E _ A L I A S _ O R D E R + P A G E _ S H I F T ) )
bgeu a1 , a3 , 2 f
/* Check if we have to restore an ITLB mapping. */
movi a1 , _ _ t l b t e m p _ m a p p i n g _ i t l b
rsr a3 , E P C _ 1
sub a3 , a3 , a1
/* Calculate VPN */
movi a1 , P A G E _ M A S K
and a1 , a1 , a0
/* Jump for ITLB entry */
bgez a3 , 1 f
/* We can use up to two TLBTEMP areas, one for src and one for dst. */
extui a3 , a0 , P A G E _ S H I F T + D C A C H E _ A L I A S _ O R D E R , 1
add a1 , a3 , a1
/* PPN is in a6 for the first TLBTEMP area and in a7 for the second. */
mov a0 , a6
movnez a0 , a7 , a3
j 3 b
/* ITLB entry. We only use dst in a6. */
1 : witlb a6 , a1
isync
j 4 b
# endif / / D C A C H E _ W A Y _ S I Z E > P A G E _ S I Z E
2005-06-24 09:01:16 +04:00
2 : /* Invalid PGD, default exception handling */
2007-08-07 10:57:57 +04:00
movi a3 , e x c _ t a b l e
2005-06-24 09:01:16 +04:00
rsr a1 , D E P C
xsr a3 , E X C S A V E _ 1
s3 2 i a1 , a2 , P T _ A R E G 2
s3 2 i a3 , a2 , P T _ A R E G 3
mov a1 , a2
rsr a2 , P S
2006-12-10 13:18:48 +03:00
bbsi. l a2 , P S _ U M _ B I T , 1 f
2005-06-24 09:01:16 +04:00
j _ k e r n e l _ e x c e p t i o n
1 : j _ u s e r _ e x c e p t i o n
/ *
* StoreProhibitedException
*
* Update t h e p t e a n d i n v a l i d a t e t h e i t l b m a p p i n g f o r t h i s p t e .
*
* Entry c o n d i t i o n :
*
* a0 : trashed, o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ A R E G 0 )
* a1 : a1
* a2 : new s t a c k p o i n t e r , o r i g i n a l i n D E P C
* a3 : dispatch t a b l e
* depc : a2 , o r i g i n a l v a l u e s a v e d o n s t a c k ( P T _ D E P C )
* excsave_1 : a3
*
* PT_ D E P C > = V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S : d o u b l e e x c e p t i o n , D E P C
* < VALID_DOUBLE_EXCEPTION_ADDRESS : regular e x c e p t i o n
* /
ENTRY( f a s t _ s t o r e _ p r o h i b i t e d )
/* Save a1 and a4. */
s3 2 i a1 , a2 , P T _ A R E G 1
s3 2 i a4 , a2 , P T _ A R E G 4
GET_ C U R R E N T ( a1 ,a2 )
l3 2 i a0 , a1 , T A S K _ M M # t s k - > m m
beqz a0 , 9 f
8 : rsr a1 , E X C V A D D R # f a u l t a d d r e s s
_ PGD_ O F F S E T ( a0 , a1 , a4 )
l3 2 i a0 , a0 , 0
beqz a0 , 2 f
2007-08-07 10:57:57 +04:00
/* Note that we assume _PAGE_WRITABLE_BIT is only set if pte is valid.*/
2005-06-24 09:01:16 +04:00
_ PTE_ O F F S E T ( a0 , a1 , a4 )
l3 2 i a4 , a0 , 0 # r e a d p t e v a l
2007-08-07 10:57:57 +04:00
bbci. l a4 , _ P A G E _ W R I T A B L E _ B I T , 2 f
2005-06-24 09:01:16 +04:00
2007-08-07 10:57:57 +04:00
movi a1 , _ P A G E _ A C C E S S E D | _ P A G E _ D I R T Y | _ P A G E _ H W _ W R I T E
2005-06-24 09:01:16 +04:00
or a4 , a4 , a1
rsr a1 , E X C V A D D R
s3 2 i a4 , a0 , 0
/* We need to flush the cache if we have page coloring. */
# if ( D C A C H E _ W A Y _ S I Z E > P A G E _ S I Z E ) & & X C H A L _ D C A C H E _ I S _ W R I T E B A C K
dhwb a0 , 0
# endif
pdtlb a0 , a1
wdtlb a4 , a0
/* Exit critical section. */
movi a0 , 0
s3 2 i a0 , a3 , E X C _ T A B L E _ F I X U P
/* Restore the working registers, and return. */
l3 2 i a4 , a2 , P T _ A R E G 4
l3 2 i a1 , a2 , P T _ A R E G 1
l3 2 i a0 , a2 , P T _ A R E G 0
l3 2 i a2 , a2 , P T _ D E P C
/* Restore excsave1 and a3. */
xsr a3 , E X C S A V E _ 1
bgeui a2 , V A L I D _ D O U B L E _ E X C E P T I O N _ A D D R E S S , 1 f
rsr a2 , D E P C
rfe
/* Double exception. Restore FIXUP handler and return. */
1 : xsr a2 , D E P C
esync
rfde
9 : l3 2 i a0 , a1 , T A S K _ A C T I V E _ M M # u n l i k e l y c a s e m m = = 0
j 8 b
2 : /* If there was a problem, handle fault in C */
rsr a4 , D E P C # s t i l l h o l d s a 2
xsr a3 , E X C S A V E _ 1
s3 2 i a4 , a2 , P T _ A R E G 2
s3 2 i a3 , a2 , P T _ A R E G 3
l3 2 i a4 , a2 , P T _ A R E G 4
mov a1 , a2
rsr a2 , P S
2006-12-10 13:18:48 +03:00
bbsi. l a2 , P S _ U M _ B I T , 1 f
2005-06-24 09:01:16 +04:00
j _ k e r n e l _ e x c e p t i o n
1 : j _ u s e r _ e x c e p t i o n
2009-03-04 18:21:31 +03:00
# endif / * C O N F I G _ M M U * /
2005-06-24 09:01:16 +04:00
2006-12-10 13:18:52 +03:00
/ *
* System C a l l s .
*
* void s y s t e m _ c a l l ( s t r u c t p t _ r e g s * r e g s , i n t e x c c a u s e )
* a2 a3
* /
ENTRY( s y s t e m _ c a l l )
entry a1 , 3 2
/* regs->syscall = regs->areg[2] */
l3 2 i a3 , a2 , P T _ A R E G 2
mov a6 , a2
movi a4 , d o _ s y s c a l l _ t r a c e _ e n t e r
s3 2 i a3 , a2 , P T _ S Y S C A L L
callx4 a4
/* syscall = sys_call_table[syscall_nr] */
movi a4 , s y s _ c a l l _ t a b l e ;
movi a5 , _ _ N R _ s y s c a l l _ c o u n t
movi a6 , - E N O S Y S
bgeu a3 , a5 , 1 f
addx4 a4 , a3 , a4
l3 2 i a4 , a4 , 0
movi a5 , s y s _ n i _ s y s c a l l ;
beq a4 , a5 , 1 f
/* Load args: arg0 - arg5 are passed via regs. */
l3 2 i a6 , a2 , P T _ A R E G 6
l3 2 i a7 , a2 , P T _ A R E G 3
l3 2 i a8 , a2 , P T _ A R E G 4
l3 2 i a9 , a2 , P T _ A R E G 5
l3 2 i a10 , a2 , P T _ A R E G 8
l3 2 i a11 , a2 , P T _ A R E G 9
/* Pass one additional argument to the syscall: pt_regs (on stack) */
s3 2 i a2 , a1 , 0
callx4 a4
1 : /* regs->areg[2] = return_value */
s3 2 i a6 , a2 , P T _ A R E G 2
movi a4 , d o _ s y s c a l l _ t r a c e _ l e a v e
mov a6 , a2
callx4 a4
retw
/ *
* Create a k e r n e l t h r e a d
*
* int k e r n e l _ t h r e a d ( i n t ( * f n ) ( v o i d * ) , v o i d * a r g , u n s i g n e d l o n g f l a g s )
* a2 a2 a3 a4
* /
ENTRY( k e r n e l _ t h r e a d )
entry a1 , 1 6
mov a5 , a2 # p r e s e r v e f n o v e r s y s c a l l
mov a7 , a3 # p r e s e r v e a r g s o v e r s y s c a l l
movi a3 , _ C L O N E _ V M | _ C L O N E _ U N T R A C E D
movi a2 , _ _ N R _ c l o n e
or a6 , a4 , a3 # a r g 0 : f l a g s
mov a3 , a1 # a r g 1 : s p
syscall
beq a3 , a1 , 1 f # b r a n c h i f p a r e n t
mov a6 , a7 # a r g s
callx4 a5 # f n ( a r g s )
movi a2 , _ _ N R _ e x i t
syscall # r e t u r n v a l u e o f f n ( a r g s ) s t i l l i n a 6
1 : retw
/ *
* Do a s y s t e m c a l l f r o m k e r n e l i n s t e a d o f c a l l i n g s y s _ e x e c v e , s o w e e n d u p
* with p r o p e r p t _ r e g s .
*
* int k e r n e l _ e x e c v e ( c o n s t c h a r * f n a m e , c h a r * c o n s t a r g v [ ] , c h a r g * c o n s t e n v p [ ] )
* a2 a2 a3 a4
* /
ENTRY( k e r n e l _ e x e c v e )
entry a1 , 1 6
mov a6 , a2 # a r g 0 i s i n a6
movi a2 , _ _ N R _ e x e c v e
syscall
retw
2005-06-24 09:01:16 +04:00
/ *
* Task s w i t c h .
*
* struct t a s k * _ s w i t c h _ t o ( s t r u c t t a s k * p r e v , s t r u c t t a s k * n e x t )
* a2 a2 a3
* /
ENTRY( _ s w i t c h _ t o )
entry a1 , 1 6
2008-02-13 00:17:07 +03:00
mov a12 , a2 # p r e s e r v e ' p r e v ' ( a 2 )
mov a13 , a3 # a n d ' n e x t ' ( a 3 )
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
l3 2 i a4 , a2 , T A S K _ T H R E A D _ I N F O
l3 2 i a5 , a3 , T A S K _ T H R E A D _ I N F O
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
save_ x t r e g s _ u s e r a4 a6 a8 a9 a10 a11 T H R E A D _ X T R E G S _ U S E R
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
s3 2 i a0 , a12 , T H R E A D _ R A # s a v e r e t u r n a d d r e s s
s3 2 i a1 , a12 , T H R E A D _ S P # s a v e s t a c k p o i n t e r
/* Disable ints while we manipulate the stack pointer. */
movi a14 , ( 1 < < P S _ E X C M _ B I T ) | L O C K L E V E L
xsr a14 , P S
2005-06-24 09:01:16 +04:00
rsr a3 , E X C S A V E _ 1
rsync
s3 2 i a3 , a3 , E X C _ T A B L E _ F I X U P / * e n t e r c r i t i c a l s e c t i o n * /
2008-02-13 00:17:07 +03:00
/* Switch CPENABLE */
# if ( X T E N S A _ H A V E _ C O P R O C E S S O R S | | X T E N S A _ H A V E _ I O _ P O R T S )
l3 2 i a3 , a5 , T H R E A D _ C P E N A B L E
xsr a3 , C P E N A B L E
s3 2 i a3 , a4 , T H R E A D _ C P E N A B L E
# endif
/* Flush register file. */
call0 _ s p i l l _ r e g i s t e r s # d e s t r o y s a 3 , a4 , a n d S A R
2005-06-24 09:01:16 +04:00
/ * Set k e r n e l s t a c k ( a n d l e a v e c r i t i c a l s e c t i o n )
* Note : It' s s a v e t o s e t i t h e r e . T h e s t a c k w i l l n o t b e o v e r w r i t t e n
* because t h e k e r n e l s t a c k w i l l o n l y b e l o a d e d a g a i n a f t e r
* we r e t u r n f r o m k e r n e l s p a c e .
* /
rsr a3 , E X C S A V E _ 1 # e x c _ t a b l e
2008-02-13 00:17:07 +03:00
movi a6 , 0
addi a7 , a5 , P T _ R E G S _ O F F S E T
s3 2 i a6 , a3 , E X C _ T A B L E _ F I X U P
s3 2 i a7 , a3 , E X C _ T A B L E _ K S T K
2005-06-24 09:01:16 +04:00
/* restore context of the task that 'next' addresses */
2008-02-13 00:17:07 +03:00
l3 2 i a0 , a13 , T H R E A D _ R A # r e s t o r e r e t u r n a d d r e s s
l3 2 i a1 , a13 , T H R E A D _ S P # r e s t o r e s t a c k p o i n t e r
load_ x t r e g s _ u s e r a5 a6 a8 a9 a10 a11 T H R E A D _ X T R E G S _ U S E R
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
wsr a14 , P S
mov a2 , a12 # r e t u r n ' p r e v '
2005-06-24 09:01:16 +04:00
rsync
retw
ENTRY( r e t _ f r o m _ f o r k )
/ * void s c h e d u l e _ t a i l ( s t r u c t t a s k _ s t r u c t * p r e v )
* Note : prev i s s t i l l i n a6 ( r e t u r n v a l u e f r o m f a k e c a l l 4 f r a m e )
* /
movi a4 , s c h e d u l e _ t a i l
callx4 a4
2006-12-10 13:18:52 +03:00
movi a4 , d o _ s y s c a l l _ t r a c e _ l e a v e
mov a6 , a1
2005-06-24 09:01:16 +04:00
callx4 a4
j c o m m o n _ e x c e p t i o n _ r e t u r n