2015-10-25 11:01:56 +03:00
/ *
* Copyright ( C ) 2 0 1 5 - A R M L t d
* Author : Marc Z y n g i e r < m a r c . z y n g i e r @arm.com>
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify
* it u n d e r t h e t e r m s o f t h e G N U G e n e r a l P u b l i c L i c e n s e v e r s i o n 2 a s
* published b y t h e F r e e S o f t w a r e F o u n d a t i o n .
*
* This p r o g r a m i s d i s t r i b u t e d i n t h e h o p e t h a t i t w i l l b e u s e f u l ,
* but W I T H O U T A N Y W A R R A N T Y ; without even the implied warranty of
* MERCHANTABILITY o r F I T N E S S F O R A P A R T I C U L A R P U R P O S E . S e e t h e
* GNU G e n e r a l P u b l i c L i c e n s e f o r m o r e d e t a i l s .
*
* You s h o u l d h a v e r e c e i v e d a c o p y o f t h e G N U G e n e r a l P u b l i c L i c e n s e
* along w i t h t h i s p r o g r a m . I f n o t , s e e < h t t p : / / w w w . g n u . o r g / l i c e n s e s / > .
* /
2018-02-06 20:56:15 +03:00
# include < l i n u x / a r m - s m c c c . h >
2015-10-25 11:01:56 +03:00
# include < l i n u x / l i n k a g e . h >
# include < a s m / a l t e r n a t i v e . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / c p u f e a t u r e . h >
# include < a s m / k v m _ a r m . h >
# include < a s m / k v m _ a s m . h >
# include < a s m / k v m _ m m u . h >
.text
.pushsection .hyp .text , " ax"
2015-01-29 16:52:12 +03:00
.macro do_el2_call
/ *
* Shuffle t h e p a r a m e t e r s b e f o r e c a l l i n g t h e f u n c t i o n
* pointed t o i n x0 . A s s u m e s p a r a m e t e r s i n x [ 1 ,2 ,3 ] .
* /
2017-04-03 21:37:35 +03:00
str l r , [ s p , #- 16 ] !
2015-01-29 16:52:12 +03:00
mov l r , x0
mov x0 , x1
mov x1 , x2
mov x2 , x3
blr l r
2017-04-03 21:37:35 +03:00
ldr l r , [ s p ] , #16
2015-01-29 16:52:12 +03:00
.endm
ENTRY( _ _ v h e _ h y p _ c a l l )
do_ e l 2 _ c a l l
/ *
* We u s e d t o r e l y o n h a v i n g a n e x c e p t i o n r e t u r n t o g e t
* an i m p l i c i t i s b . I n t h e E 2 H c a s e , w e d o n ' t h a v e i t a n y m o r e .
* rather t h a n c h a n g i n g a l l t h e l e a f f u n c t i o n s , j u s t d o i t h e r e
* before r e t u r n i n g t o t h e r e s t o f t h e k e r n e l .
* /
isb
ret
ENDPROC( _ _ v h e _ h y p _ c a l l )
2016-06-30 20:40:44 +03:00
2015-10-25 11:01:56 +03:00
el1_sync : / / Guest t r a p p e d i n t o E L 2
2017-10-08 18:01:56 +03:00
mrs x0 , e s r _ e l 2
lsr x0 , x0 , #E S R _ E L x _ E C _ S H I F T
2016-08-31 05:08:32 +03:00
cmp x0 , #E S R _ E L x _ E C _ H V C 64
2018-02-06 20:56:15 +03:00
ccmp x0 , #E S R _ E L x _ E C _ H V C 32 , #4 , n e
2015-10-25 11:01:56 +03:00
b. n e e l 1 _ t r a p
2018-02-06 20:56:15 +03:00
mrs x1 , v t t b r _ e l 2 / / I f v t t b r i s v a l i d , t h e g u e s t
cbnz x1 , e l 1 _ h v c _ g u e s t / / c a l l e d H V C
2015-10-25 11:01:56 +03:00
/* Here, we're pretty sure the host called HVC. */
2016-08-31 05:08:32 +03:00
ldp x0 , x1 , [ s p ] , #16
2015-10-25 11:01:56 +03:00
2017-04-03 21:37:42 +03:00
/* Check for a stub HVC call */
cmp x0 , #H V C _ S T U B _ H C A L L _ N R
b. h s 1 f
/ *
* Compute t h e i d m a p a d d r e s s o f _ _ k v m _ h a n d l e _ s t u b _ h v c a n d
* jump t h e r e . S i n c e w e u s e k i m a g e _ v o f f s e t , d o n o t u s e t h e
* HYP V A f o r _ _ k v m _ h a n d l e _ s t u b _ h v c , b u t t h e k e r n e l V A i n s t e a d
* ( by l o a d i n g i t f r o m t h e c o n s t a n t p o o l ) .
*
* Preserve x0 - x4 , w h i c h m a y c o n t a i n s t u b p a r a m e t e r s .
* /
ldr x5 , =__kvm_handle_stub_hvc
ldr_ l x6 , k i m a g e _ v o f f s e t
/* x5 = __pa(x5) */
sub x5 , x5 , x6
br x5
2015-10-25 11:01:56 +03:00
2015-01-29 16:52:12 +03:00
1 :
2015-10-25 11:01:56 +03:00
/ *
2015-01-29 16:52:12 +03:00
* Perform t h e E L 2 c a l l
2015-10-25 11:01:56 +03:00
* /
kern_ h y p _ v a x0
2015-01-29 16:52:12 +03:00
do_ e l 2 _ c a l l
2015-10-25 11:01:56 +03:00
2017-04-03 21:37:42 +03:00
eret
2015-10-25 11:01:56 +03:00
2018-02-06 20:56:15 +03:00
el1_hvc_guest :
/ *
* Fastest p o s s i b l e p a t h f o r A R M _ S M C C C _ A R C H _ W O R K A R O U N D _ 1 .
* The w o r k a r o u n d h a s a l r e a d y b e e n a p p l i e d o n t h e h o s t ,
* so l e t ' s q u i c k l y g e t b a c k t o t h e g u e s t . W e d o n ' t b o t h e r
* restoring x1 , a s i t c a n b e c l o b b e r e d a n y w a y .
* /
ldr x1 , [ s p ] / / G u e s t ' s x0
eor w1 , w1 , #A R M _ S M C C C _ A R C H _ W O R K A R O U N D _ 1
cbnz w1 , e l 1 _ t r a p
mov x0 , x1
add s p , s p , #16
eret
2015-10-25 11:01:56 +03:00
el1_trap :
2017-10-08 18:01:56 +03:00
get_ v c p u _ p t r x1 , x0
mrs x0 , e s r _ e l 2
lsr x0 , x0 , #E S R _ E L x _ E C _ S H I F T
2015-10-25 11:01:56 +03:00
/ *
2016-08-31 05:08:32 +03:00
* x0 : ESR_ E C
2017-10-08 18:01:56 +03:00
* x1 : vcpu p o i n t e r
2015-10-25 11:01:56 +03:00
* /
2016-11-08 16:56:21 +03:00
/ *
* We t r a p t h e f i r s t a c c e s s t o t h e F P / S I M D t o s a v e t h e h o s t c o n t e x t
* and r e s t o r e t h e g u e s t c o n t e x t l a z i l y .
* If F P / S I M D i s n o t i m p l e m e n t e d , h a n d l e t h e t r a p a n d i n j e c t a n
* undefined i n s t r u c t i o n e x c e p t i o n t o t h e g u e s t .
* /
alternative_ i f _ n o t A R M 6 4 _ H A S _ N O _ F P S I M D
2016-08-31 05:08:32 +03:00
cmp x0 , #E S R _ E L x _ E C _ F P _ A S I M D
2015-10-25 11:01:56 +03:00
b. e q _ _ f p s i m d _ g u e s t _ r e s t o r e
2016-11-08 16:56:21 +03:00
alternative_ e l s e _ n o p _ e n d i f
2015-10-25 11:01:56 +03:00
2016-08-31 05:08:32 +03:00
mov x0 , #A R M _ E X C E P T I O N _ T R A P
2015-10-25 11:01:56 +03:00
b _ _ g u e s t _ e x i t
el1_irq :
2017-10-08 18:01:56 +03:00
get_ v c p u _ p t r x1 , x0
2016-08-31 05:08:32 +03:00
mov x0 , #A R M _ E X C E P T I O N _ I R Q
2015-10-25 11:01:56 +03:00
b _ _ g u e s t _ e x i t
2016-09-06 16:02:04 +03:00
el1_error :
2017-10-08 18:01:56 +03:00
get_ v c p u _ p t r x1 , x0
2016-09-06 16:02:04 +03:00
mov x0 , #A R M _ E X C E P T I O N _ E L 1 _ S E R R O R
b _ _ g u e s t _ e x i t
2016-09-06 16:02:07 +03:00
el2_error :
2018-02-12 20:53:00 +03:00
ldp x0 , x1 , [ s p ] , #16
2016-09-06 16:02:07 +03:00
/ *
* Only t w o p o s s i b i l i t i e s :
* 1 ) Either w e c o m e f r o m t h e e x i t p a t h , h a v i n g j u s t u n m a s k e d
* PSTATE. A : c h a n g e t h e r e t u r n c o d e t o a n E L 2 f a u l t , a n d
* carry o n , a s w e ' r e a l r e a d y i n a s a n e s t a t e t o h a n d l e i t .
* 2 ) Or w e c o m e f r o m a n y w h e r e e l s e , a n d t h a t ' s a b u g : w e p a n i c .
*
* For ( 1 ) , x0 c o n t a i n s t h e o r i g i n a l r e t u r n c o d e a n d x1 d o e s n ' t
* contain a n y t h i n g m e a n i n g f u l a t t h a t s t a g e . W e c a n r e u s e t h e m
* as t e m p r e g i s t e r s .
* For ( 2 ) , w h o c a r e s ?
* /
mrs x0 , e l r _ e l 2
adr x1 , a b o r t _ g u e s t _ e x i t _ s t a r t
cmp x0 , x1
adr x1 , a b o r t _ g u e s t _ e x i t _ e n d
ccmp x0 , x1 , #4 , n e
b. n e _ _ h y p _ p a n i c
mov x0 , #( 1 < < A R M _ E X I T _ W I T H _ S E R R O R _ B I T )
eret
2015-10-25 18:21:52 +03:00
ENTRY( _ _ h y p _ d o _ p a n i c )
mov l r , #( P S R _ F _ B I T | P S R _ I _ B I T | P S R _ A _ B I T | P S R _ D _ B I T | \
PSR_ M O D E _ E L 1 h )
msr s p s r _ e l 2 , l r
ldr l r , =panic
msr e l r _ e l 2 , l r
eret
ENDPROC( _ _ h y p _ d o _ p a n i c )
2018-01-08 18:38:05 +03:00
ENTRY( _ _ h y p _ p a n i c )
2017-10-08 18:01:56 +03:00
get_ h o s t _ c t x t x0 , x1
2018-01-08 18:38:05 +03:00
b h y p _ p a n i c
ENDPROC( _ _ h y p _ p a n i c )
2015-10-25 18:21:52 +03:00
.macro invalid_vector label, t a r g e t = _ _ h y p _ p a n i c
2015-10-25 11:01:56 +03:00
.align 2
\ label :
b \ t a r g e t
ENDPROC( \ l a b e l )
.endm
/* None of these should ever happen */
invalid_ v e c t o r e l 2 t _ s y n c _ i n v a l i d
invalid_ v e c t o r e l 2 t _ i r q _ i n v a l i d
invalid_ v e c t o r e l 2 t _ f i q _ i n v a l i d
invalid_ v e c t o r e l 2 t _ e r r o r _ i n v a l i d
invalid_ v e c t o r e l 2 h _ s y n c _ i n v a l i d
invalid_ v e c t o r e l 2 h _ i r q _ i n v a l i d
invalid_ v e c t o r e l 2 h _ f i q _ i n v a l i d
invalid_ v e c t o r e l 1 _ f i q _ i n v a l i d
.ltorg
.align 11
2018-02-12 20:53:00 +03:00
.macro valid_vect target
.align 7
stp x0 , x1 , [ s p , #- 16 ] !
b \ t a r g e t
.endm
.macro invalid_vect target
.align 7
b \ t a r g e t
.endm
2015-10-25 16:58:00 +03:00
ENTRY( _ _ k v m _ h y p _ v e c t o r )
2018-02-12 20:53:00 +03:00
invalid_ v e c t e l 2 t _ s y n c _ i n v a l i d / / S y n c h r o n o u s E L 2 t
invalid_ v e c t e l 2 t _ i r q _ i n v a l i d / / I R Q E L 2 t
invalid_ v e c t e l 2 t _ f i q _ i n v a l i d / / F I Q E L 2 t
invalid_ v e c t e l 2 t _ e r r o r _ i n v a l i d / / E r r o r E L 2 t
invalid_ v e c t e l 2 h _ s y n c _ i n v a l i d / / S y n c h r o n o u s E L 2 h
invalid_ v e c t e l 2 h _ i r q _ i n v a l i d / / I R Q E L 2 h
invalid_ v e c t e l 2 h _ f i q _ i n v a l i d / / F I Q E L 2 h
valid_ v e c t e l 2 _ e r r o r / / E r r o r E L 2 h
valid_ v e c t e l 1 _ s y n c / / S y n c h r o n o u s 6 4 - b i t E L 1
valid_ v e c t e l 1 _ i r q / / I R Q 6 4 - b i t E L 1
invalid_ v e c t e l 1 _ f i q _ i n v a l i d / / F I Q 6 4 - b i t E L 1
valid_ v e c t e l 1 _ e r r o r / / E r r o r 6 4 - b i t E L 1
valid_ v e c t e l 1 _ s y n c / / S y n c h r o n o u s 3 2 - b i t E L 1
valid_ v e c t e l 1 _ i r q / / I R Q 3 2 - b i t E L 1
invalid_ v e c t e l 1 _ f i q _ i n v a l i d / / F I Q 3 2 - b i t E L 1
valid_ v e c t e l 1 _ e r r o r / / E r r o r 3 2 - b i t E L 1
2015-10-25 16:58:00 +03:00
ENDPROC( _ _ k v m _ h y p _ v e c t o r )