2005-06-23 22:01:16 -07:00
/ *
* arch/ x t e n s a / k e r n e l / a l i g n . S
*
* Handle u n a l i g n m e n t e x c e p t i o n s i n k e r n e l s p a c e .
*
* 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
* Public L i c e n s e . 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
* this a r c h i v e f o r m o r e d e t a i l s .
*
* Copyright ( C ) 2 0 0 1 - 2 0 0 5 T e n s i l i c a , I n c .
*
* Rewritten b y C h r i s Z a n k e l < c h r i s @zankel.net>
*
* Based o n w o r k f r o m J o e T a y l o r < j o e @tensilica.com, joetylr@yahoo.com>
* and M a r c G a u t h i e r < m a r c @tensilica.com, marc@alimni.uwaterloo.ca>
* /
# include < l i n u x / l i n k a g e . h >
# include < a s m / p t r a c e . h >
# include < a s m / p t r a c e . h >
# include < a s m / c u r r e n t . h >
2005-09-09 20:57:26 +02:00
# include < a s m / a s m - o f f s e t s . h >
2005-06-23 22:01:16 -07:00
# include < a s m / p g t a b l e . h >
# include < a s m / p r o c e s s o r . h >
# include < a s m / p a g e . h >
# include < a s m / t h r e a d _ i n f o . h >
# if X C H A L _ U N A L I G N E D _ L O A D _ E X C E P T I O N | | X C H A L _ U N A L I G N E D _ S T O R E _ E X C E P T I O N
/ * 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 n a l i g n e d e x c e p t i o n s .
*
* Note : This h a n d l e r w o r k s o n l y f o r k e r n e l e x c e p t i o n s . U n a l i g n e d u s e r
* access s h o u l d g e t a s e g f a u l t .
* /
/ * Big a n d l i t t l e e n d i a n 1 6 - b i t v a l u e s a r e l o c a t e d i n
* different h a l v e s o f a r e g i s t e r . H W O R D _ S T A R T h e l p s t o
* abstract t h e n o t i o n o f e x t r a c t i n g a 1 6 - b i t v a l u e f r o m a
* register.
* We a l s o h a v e t o d e f i n e n e w s h i f t i n g i n s t r u c t i o n s b e c a u s e
* lsb a n d m s b a r e o n ' o p p o s i t e ' e n d s i n a r e g i s t e r f o r
* different e n d i a n m a c h i n e s .
*
* Assume a m e m o r y r e g i o n i n a s c e n d i n g a d d r e s s :
* 0 1 2 3 | 4 5 6 7
*
* When l o a d i n g o n e w o r d i n t o a r e g i s t e r , t h e c o n t e n t o f t h a t r e g i s t e r i s :
* LE 3 2 1 0 , 7 6 5 4
* BE 0 1 2 3 , 4 5 6 7
*
* Masking t h e b i t s o f t h e h i g h e r / l o w e r a d d r e s s m e a n s :
* LE X X 0 0 , 0 0 X X
* BE 0 0 X X , X X 0 0
*
* Shifting t o h i g h e r / l o w e r a d d r e s s e s , m e a n s :
* LE s h i f t l e f t / s h i f t r i g h t
* BE s h i f t r i g h t / s h i f t l e f t
*
* Extracting 1 6 b i t s f r o m a 3 2 b i t r e g . v a l u e t o h i g h e r / l o w e r a d d r e s s m e a n s :
* LE m a s k 0 0 X X / s h i f t l e f t
* BE s h i f t l e f t / m a s k 0 0 X X
* /
# define U N A L I G N E D _ U S E R _ E X C E P T I O N
# if X C H A L _ H A V E _ B E
# define H W O R D _ S T A R T 1 6
# define I N S N _ O P 0 2 8
# define I N S N _ T 2 4
# define I N S N _ O P 1 1 6
.macro __src_b r, w0 , w1 ; src \r, \w0, \w1; .endm
.macro __ssa8 r; ssa8b \r; .endm
.macro __ssa8r r; ssa8l \r; .endm
.macro __sh r, s ; srl \r, \s; .endm
.macro __sl r, s ; sll \r, \s; .endm
.macro __exth r, s ; extui \r, \s, 0, 16; .endm
.macro __extl r, s ; slli \r, \s, 16; .endm
# else
# define H W O R D _ S T A R T 0
# define I N S N _ O P 0 0
# define I N S N _ T 4
# define I N S N _ O P 1 1 2
.macro __src_b r, w0 , w1 ; src \r, \w1, \w0; .endm
.macro __ssa8 r; ssa8l \r; .endm
.macro __ssa8r r; ssa8b \r; .endm
.macro __sh r, s ; sll \r, \s; .endm
.macro __sl r, s ; srl \r, \s; .endm
.macro __exth r, s ; slli \r, \s, 16; .endm
.macro __extl r, s ; extui \r, \s, 0, 16; .endm
# endif
/ *
* xxxx x x x x = i m m 8 f i e l d
* yyyy = i m m 4 f i e l d
* ssss = s f i e l d
* tttt = t f i e l d
*
* 1 6 0
* - - - - - - - - - - - - - - - - - - -
* L3 2 I . N y y y y s s s s t t t t 1 0 0 0
* S3 2 I . N y y y y s s s s t t t t 1 0 0 1
*
* 2 3 0
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* res 0 0 0 0 0 0 1 0
* L1 6 U I x x x x x x x x 0 0 0 1 s s s s t t t t 0 0 1 0
* L3 2 I x x x x x x x x 0 0 1 0 s s s s t t t t 0 0 1 0
* XXX 0 0 1 1 s s s s t t t t 0 0 1 0
* XXX 0 1 0 0 s s s s t t t t 0 0 1 0
* S1 6 I x x x x x x x x 0 1 0 1 s s s s t t t t 0 0 1 0
* S3 2 I x x x x x x x x 0 1 1 0 s s s s t t t t 0 0 1 0
* XXX 0 1 1 1 s s s s t t t t 0 0 1 0
* XXX 1 0 0 0 s s s s t t t t 0 0 1 0
* L1 6 S I x x x x x x x x 1 0 0 1 s s s s t t t t 0 0 1 0
* XXX 1 0 1 0 0 0 1 0
* * * L3 2 A I x x x x x x x x 1 0 1 1 s s s s t t t t 0 0 1 0 u n s u p p o r t e d
* XXX 1 1 0 0 0 0 1 0
* XXX 1 1 0 1 0 0 1 0
* XXX 1 1 1 0 0 0 1 0
* * * S3 2 R I x x x x x x x x 1 1 1 1 s s s s t t t t 0 0 1 0 u n s u p p o r t e d
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* ^ ^ ^
* sub- o p c o d e ( N I B B L E _ R ) - + | |
* t f i e l d ( N I B B L E _ T ) - - - - - - - - - - - + |
* major o p c o d e ( N I B B L E _ O P 0 ) - - - - - - - - - - - - - - +
* /
# define O P 0 _ L 3 2 I _ N 0 x8 / * l o a d i m m e d i a t e n a r r o w * /
# define O P 0 _ S 3 2 I _ N 0 x9 / * s t o r e i m m e d i a t e n a r r o w * /
# define O P 1 _ S I _ M A S K 0 x4 / * O P 1 b i t s e t f o r s t o r e s * /
# define O P 1 _ S I _ B I T 2 / * O P 1 b i t n u m b e r f o r s t o r e s * /
# define O P 1 _ L 3 2 I 0 x2
# define O P 1 _ L 1 6 U I 0 x1
# define O P 1 _ L 1 6 S I 0 x9
# define O P 1 _ L 3 2 A I 0 x b
# define O P 1 _ S 3 2 I 0 x6
# define O P 1 _ S 1 6 I 0 x5
# define O P 1 _ S 3 2 R I 0 x f
/ *
* 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 _ u n a l i g n e d )
/ * Note : We d o n ' t e x p e c t t h e a d d r e s s t o b e a l i g n e d o n a w o r d
* boundary. A f t e r a l l , t h e p r o c e s s o r g e n e r a t e d t h a t e x c e p t i o n
* and i t w o u l d b e a h a r d w a r e f a u l t .
* /
/* Save some working register */
s3 2 i a4 , a2 , P T _ A R E G 4
s3 2 i a5 , a2 , P T _ A R E G 5
s3 2 i a6 , a2 , P T _ A R E G 6
s3 2 i a7 , a2 , P T _ A R E G 7
s3 2 i a8 , a2 , P T _ A R E G 8
rsr a0 , D E P C
xsr a3 , E X C S A V E _ 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
/* Keep value of SAR in a0 */
rsr a0 , S A R
rsr a8 , E X C V A D D R # l o a d u n a l i g n e d m e m o r y a d d r e s s
/ * Now, i d e n t i f y o n e o f t h e f o l l o w i n g l o a d / s t o r e i n s t r u c t i o n s .
*
* The o n l y p o s s i b l e d a n g e r o f a d o u b l e e x c e p t i o n o n t h e
* following l 3 2 i i n s t r u c t i o n s i s k e r n e l c o d e i n v m a l l o c
* memory. T h e p r o c e s s o r w a s j u s t e x e c u t i n g a t t h e E P C _ 1
* address, a n d i n d e e d , a l r e a d y f e t c h e d t h e i n s t r u c t i o n . T h a t
* guarantees a T L B m a p p i n g , w h i c h h a s n ' t b e e n r e p l a c e d b y
* this u n a l i g n e d e x c e p t i o n h a n d l e r t h a t u s e s o n l y s t a t i c T L B
* mappings. H o w e v e r , h i g h - l e v e l i n t e r r u p t h a n d l e r s m i g h t
* modify T L B e n t r i e s , s o f o r t h e g e n e r i c c a s e , w e r e g i s t e r a
* TABLE_ F I X U P h a n d l e r h e r e , t o o .
* /
/* a3...a6 saved on stack, a2 = SP */
/* Extract the instruction that caused the unaligned access. */
rsr a7 , E P C _ 1 # l o a d e x c e p t i o n a d d r e s s
movi a3 , ~ 3
and a3 , a3 , a7 # m a s k l o w e r b i t s
l3 2 i a4 , a3 , 0 # l o a d 2 w o r d s
l3 2 i a5 , a3 , 4
_ _ ssa8 a7
_ _ src_ b a4 , a4 , a5 # a 4 h a s t h e i n s t r u c t i o n
/* Analyze the instruction (load or store?). */
extui a5 , a4 , I N S N _ O P 0 , 4 # g e t i n s n . o p 0 n i b b l e
# if X C H A L _ H A V E _ N A R R O W
_ beqi a5 , O P 0 _ L 3 2 I _ N , . L l o a d # L 32 I . N , j u m p
addi a6 , a5 , - O P 0 _ S 3 2 I _ N
_ beqz a6 , . L s t o r e # S 32 I . N , d o a s t o r e
# endif
/* 'store indicator bit' not set, jump */
_ bbci. l a4 , O P 1 _ S I _ B I T + I N S N _ O P 1 , . L l o a d
/* Store: Jump to table entry to get the value in the source register.*/
.Lstore : movi a5 , . L s t o r e _ t a b l e # t a b l e
extui a6 , a4 , I N S N _ T , 4 # g e t s o u r c e r e g i s t e r
addx8 a5 , a6 , a5
jx a5 # j u m p i n t o t a b l e
/* Invalid instruction, CRITICAL! */
.Linvalid_instruction_load :
j . L i n v a l i d _ i n s t r u c t i o n
/* Load: Load memory address. */
.Lload : movi a3 , ~ 3
and a3 , a3 , a8 # a l i g n m e m o r y a d d r e s s
_ _ ssa8 a8
# ifdef U N A L I G N E D _ U S E R _ E X C E P T I O N
addi a3 , a3 , 8
l3 2 e a5 , a3 , - 8
l3 2 e a6 , a3 , - 4
# else
l3 2 i a5 , a3 , 0
l3 2 i a6 , a3 , 4
# endif
_ _ src_ b a3 , a5 , a6 # a 3 h a s t h e d a t a w o r d
# if X C H A L _ H A V E _ N A R R O W
addi a7 , a7 , 2 # i n c r e m e n t P C ( a s s u m e 16 - b i t i n s n )
extui a5 , a4 , I N S N _ O P 0 , 4
_ beqi a5 , O P 0 _ L 3 2 I _ N , 1 f # l 32 i . n : j u m p
addi a7 , a7 , 1
# else
addi a7 , a7 , 3
# endif
extui a5 , a4 , I N S N _ O P 1 , 4
_ beqi a5 , O P 1 _ L 3 2 I , 1 f # l 32 i : j u m p
extui a3 , a3 , 0 , 1 6 # e x t r a c t l o w e r 16 b i t s
_ beqi a5 , O P 1 _ L 1 6 U I , 1 f
addi a5 , a5 , - O P 1 _ L 1 6 S I
_ bnez a5 , . L i n v a l i d _ i n s t r u c t i o n _ l o a d
/* sign extend value */
slli a3 , a3 , 1 6
srai a3 , a3 , 1 6
/* Set target register. */
1 :
# if X C H A L _ H A V E _ L O O P
rsr a3 , L E N D # c h e c k i f w e r e a c h e d L E N D
bne a7 , a3 , 1 f
rsr a3 , L C O U N T # a n d L C O U N T ! = 0
beqz a3 , 1 f
addi a3 , a3 , - 1 # d e c r e m e n t L C O U N T a n d s e t
rsr a7 , L B E G # s e t P C t o L B E G I N
wsr a3 , L C O U N T
# endif
1 : wsr a7 , E P C _ 1 # s k i p l o a d i n s t r u c t i o n
extui a4 , a4 , I N S N _ T , 4 # e x t r a c t t a r g e t r e g i s t e r
movi a5 , . L l o a d _ t a b l e
addx8 a4 , a4 , a5
jx a4 # j u m p t o e n t r y f o r t a r g e t r e g i s t e r
.align 8
.Lload_table :
s3 2 i a3 , a2 , P T _ A R E G 0 ; _j .Lexit; .align 8
mov a1 , a3 ; _j .Lexit; .align 8 # fishy??
s3 2 i a3 , a2 , P T _ A R E G 2 ; _j .Lexit; .align 8
s3 2 i a3 , a2 , P T _ A R E G 3 ; _j .Lexit; .align 8
s3 2 i a3 , a2 , P T _ A R E G 4 ; _j .Lexit; .align 8
s3 2 i a3 , a2 , P T _ A R E G 5 ; _j .Lexit; .align 8
s3 2 i a3 , a2 , P T _ A R E G 6 ; _j .Lexit; .align 8
s3 2 i a3 , a2 , P T _ A R E G 7 ; _j .Lexit; .align 8
s3 2 i a3 , a2 , P T _ A R E G 8 ; _j .Lexit; .align 8
mov a9 , a3 ; _j .Lexit; .align 8
mov a10 , a3 ; _j .Lexit; .align 8
mov a11 , a3 ; _j .Lexit; .align 8
mov a12 , a3 ; _j .Lexit; .align 8
mov a13 , a3 ; _j .Lexit; .align 8
mov a14 , a3 ; _j .Lexit; .align 8
mov a15 , a3 ; _j .Lexit; .align 8
.Lstore_table :
l3 2 i a3 , a2 , P T _ A R E G 0 ; _j 1f; .align 8
mov a3 , a1 ; _j 1f; .align 8 # fishy??
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
l3 2 i a3 , a2 , P T _ A R E G 5 ; _j 1f; .align 8
l3 2 i a3 , a2 , P T _ A R E G 6 ; _j 1f; .align 8
l3 2 i a3 , a2 , P T _ A R E G 7 ; _j 1f; .align 8
l3 2 i a3 , a2 , P T _ A R E G 8 ; _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 : # a7 : instruction p o i n t e r , a4 : i n s t r u c t i o n , a3 : v a l u e
movi a6 , 0 # m a s k : f f f f f f f f : 00000000
# if X C H A L _ H A V E _ N A R R O W
addi a7 , a7 , 2 # i n c r . P C , a s s u m e 16 - b i t i n s t r u c t i o n
extui a5 , a4 , I N S N _ O P 0 , 4 # e x t r a c t O P 0
addi a5 , a5 , - O P 0 _ S 3 2 I _ N
_ beqz a5 , 1 f # s 32 i . n : j u m p
addi a7 , a7 , 1 # i n c r e m e n t P C , 32 - b i t i n s t r u c t i o n
# else
addi a7 , a7 , 3 # i n c r e m e n t P C , 32 - b i t i n s t r u c t i o n
# endif
extui a5 , a4 , I N S N _ O P 1 , 4 # e x t r a c t O P 1
_ beqi a5 , O P 1 _ S 3 2 I , 1 f # j u m p i f 32 b i t s t o r e
_ bnei a5 , O P 1 _ S 1 6 I , . L i n v a l i d _ i n s t r u c t i o n _ s t o r e
movi a5 , - 1
_ _ extl a3 , a3 # g e t 16 - b i t v a l u e
_ _ exth a6 , a5 # g e t 16 - b i t m a s k f f f f f f f f : f f f f00 0 0
/* Get memory address */
1 :
# if X C H A L _ H A V E _ L O O P
rsr a3 , L E N D # c h e c k i f w e r e a c h e d L E N D
bne a7 , a3 , 1 f
rsr a3 , L C O U N T # a n d L C O U N T ! = 0
beqz a3 , 1 f
addi a3 , a3 , - 1 # d e c r e m e n t L C O U N T a n d s e t
rsr a7 , L B E G # s e t P C t o L B E G I N
wsr a3 , L C O U N T
# endif
1 : wsr a7 , E P C _ 1 # s k i p s t o r e i n s t r u c t i o n
movi a4 , ~ 3
and a4 , a4 , a8 # a l i g n m e m o r y a d d r e s s
/* Insert value into memory */
movi a5 , - 1 # m a s k : f f f f f f f f : X X X X 0000
# ifdef U N A L I G N E D _ U S E R _ E X C E P T I O N
addi a4 , a4 , 8
# endif
_ _ ssa8 r a8
_ _ src_ b a7 , a5 , a6 # l o - m a s k F . . F 0 . . 0 ( B E ) 0 . . 0 F . . F ( L E )
_ _ src_ b a6 , a6 , a5 # h i - m a s k 0 . . 0 F . . F ( B E ) F . . F 0 . . 0 ( L E )
# ifdef U N A L I G N E D _ U S E R _ E X C E P T I O N
l3 2 e a5 , a4 , - 8
# else
l3 2 i a5 , a4 , 0 # l o a d l o w e r a d d r e s s w o r d
# endif
and a5 , a5 , a7 # m a s k
_ _ sh a7 , a3 # s h i f t v a l u e
or a5 , a5 , a7 # o r w i t h o r i g i n a l v a l u e
# ifdef U N A L I G N E D _ U S E R _ E X C E P T I O N
s3 2 e a5 , a4 , - 8
l3 2 e a7 , a4 , - 4
# else
s3 2 i a5 , a4 , 0 # s t o r e
l3 2 i a7 , a4 , 4 # s a m e f o r u p p e r a d d r e s s w o r d
# endif
_ _ sl a5 , a3
and a6 , a7 , a6
or a6 , a6 , a5
# ifdef U N A L I G N E D _ U S E R _ E X C E P T I O N
s3 2 e a6 , a4 , - 4
# else
s3 2 i a6 , a4 , 4
# endif
/* Done. restore stack and return */
.Lexit :
movi a4 , 0
rsr a3 , E X C S A V E _ 1
s3 2 i a4 , a3 , E X C _ T A B L E _ F I X U P
/* Restore working register */
l3 2 i a7 , a2 , P T _ A R E G 7
l3 2 i a6 , a2 , P T _ A R E G 6
l3 2 i a5 , a2 , P T _ A R E G 5
l3 2 i a4 , a2 , P T _ A R E G 4
l3 2 i a3 , a2 , P T _ A R E G 3
/* restore SAR and return */
wsr a0 , S A R
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
/* We cannot handle this exception. */
.extern _kernel_exception
.Linvalid_instruction_store :
.Linvalid_instruction :
/* Restore a4...a8 and SAR, set SP, and jump to default exception. */
l3 2 i a8 , a2 , P T _ A R E G 8
l3 2 i a7 , a2 , P T _ A R E G 7
l3 2 i a6 , a2 , P T _ A R E G 6
l3 2 i a5 , a2 , P T _ A R E G 5
l3 2 i a4 , a2 , P T _ A R E G 4
wsr a0 , S A R
mov a1 , a2
rsr a0 , P S
bbsi. l a2 , P S _ U M _ S H I F T , 1 f # j u m p i f u s e r m o d e
movi a0 , _ k e r n e l _ e x c e p t i o n
jx a0
1 : movi a0 , _ u s e r _ e x c e p t i o n
jx a0
# endif / * X C H A L _ U N A L I G N E D _ L O A D _ E X C E P T I O N | | X C H A L _ U N A L I G N E D _ S T O R E _ E X C E P T I O N * /