2019-06-03 07:44:50 +02:00
/* SPDX-License-Identifier: GPL-2.0-only */
2015-10-25 08:01:56 +00:00
/ *
2018-04-10 11:36:45 +01:00
* Copyright ( C ) 2 0 1 5 - 2 0 1 8 - A R M L t d
2015-10-25 08:01:56 +00:00
* Author : Marc Z y n g i e r < m a r c . z y n g i e r @arm.com>
* /
2018-02-06 17:56:15 +00:00
# include < l i n u x / a r m - s m c c c . h >
2015-10-25 08:01:56 +00: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 >
2018-04-10 11:36:45 +01:00
# include < a s m / m m u . h >
2020-11-13 11:38:42 +00:00
# include < a s m / s p e c t r e . h >
2015-10-25 08:01:56 +00:00
2020-08-21 15:07:05 +01:00
.macro save_caller_saved_regs_vect
/* x0 and x1 were saved in the vector entry */
stp x2 , x3 , [ s p , #- 16 ] !
stp x4 , x5 , [ s p , #- 16 ] !
stp x6 , x7 , [ s p , #- 16 ] !
stp x8 , x9 , [ s p , #- 16 ] !
stp x10 , x11 , [ s p , #- 16 ] !
stp x12 , x13 , [ s p , #- 16 ] !
stp x14 , x15 , [ s p , #- 16 ] !
stp x16 , x17 , [ s p , #- 16 ] !
.endm
.macro restore_caller_saved_regs_vect
ldp x16 , x17 , [ s p ] , #16
ldp x14 , x15 , [ s p ] , #16
ldp x12 , x13 , [ s p ] , #16
ldp x10 , x11 , [ s p ] , #16
ldp x8 , x9 , [ s p ] , #16
ldp x6 , x7 , [ s p ] , #16
ldp x4 , x5 , [ s p ] , #16
ldp x2 , x3 , [ s p ] , #16
ldp x0 , x1 , [ s p ] , #16
.endm
2015-10-25 08:01:56 +00:00
.text
el1_sync : / / Guest t r a p p e d i n t o E L 2
2017-10-08 17:01:56 +02: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-30 21:08:32 -05:00
cmp x0 , #E S R _ E L x _ E C _ H V C 64
2018-02-06 17:56:15 +00:00
ccmp x0 , #E S R _ E L x _ E C _ H V C 32 , #4 , n e
2015-10-25 08:01:56 +00:00
b. n e e l 1 _ t r a p
2018-02-06 17:56:15 +00:00
/ *
* 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
2018-05-29 13:11:17 +01:00
cbz w1 , w a _ e p i l o g u e
/* ARM_SMCCC_ARCH_WORKAROUND_2 handling */
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 ^ \
ARM_ S M C C C _ A R C H _ W O R K A R O U N D _ 2 )
2018-02-06 17:56:15 +00:00
cbnz w1 , e l 1 _ t r a p
2018-05-29 13:11:17 +01:00
wa_epilogue :
mov x0 , x z r
2018-02-06 17:56:15 +00:00
add s p , s p , #16
eret
2018-06-14 11:23:38 +01:00
sb
2018-02-06 17:56:15 +00:00
2015-10-25 08:01:56 +00:00
el1_trap :
2017-10-08 17:01:56 +02:00
get_ v c p u _ p t r x1 , x0
2016-08-30 21:08:32 -05:00
mov x0 , #A R M _ E X C E P T I O N _ T R A P
2015-10-25 08:01:56 +00:00
b _ _ g u e s t _ e x i t
el1_irq :
2021-02-19 16:39:31 +00:00
el1_fiq :
2017-10-08 17:01:56 +02:00
get_ v c p u _ p t r x1 , x0
2016-08-30 21:08:32 -05:00
mov x0 , #A R M _ E X C E P T I O N _ I R Q
2015-10-25 08:01:56 +00:00
b _ _ g u e s t _ e x i t
2016-09-06 14:02:04 +01:00
el1_error :
2017-10-08 17:01:56 +02:00
get_ v c p u _ p t r x1 , x0
2016-09-06 14:02:04 +01: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
2018-10-17 20:21:16 +02:00
el2_sync :
2020-08-21 15:07:06 +01:00
/* Check for illegal exception return */
2018-10-17 20:21:16 +02:00
mrs x0 , s p s r _ e l 2
2020-08-21 15:07:06 +01:00
tbnz x0 , #20 , 1 f
2018-10-17 20:21:16 +02:00
2020-08-21 15:07:06 +01:00
save_ c a l l e r _ s a v e d _ r e g s _ v e c t
stp x29 , x30 , [ s p , #- 16 ] !
bl k v m _ u n e x p e c t e d _ e l 2 _ e x c e p t i o n
ldp x29 , x30 , [ s p ] , #16
restore_ c a l l e r _ s a v e d _ r e g s _ v e c t
eret
2018-10-17 20:21:16 +02:00
2020-08-21 15:07:06 +01:00
1 :
2018-10-17 20:21:16 +02:00
/* Let's attempt a recovery from the illegal exception return */
get_ v c p u _ p t r x1 , x0
mov x0 , #A R M _ E X C E P T I O N _ I L
b _ _ g u e s t _ e x i t
2016-09-06 14:02:07 +01:00
el2_error :
2020-08-21 15:07:05 +01:00
save_ c a l l e r _ s a v e d _ r e g s _ v e c t
stp x29 , x30 , [ s p , #- 16 ] !
bl k v m _ u n e x p e c t e d _ e l 2 _ e x c e p t i o n
ldp x29 , x30 , [ s p ] , #16
restore_ c a l l e r _ s a v e d _ r e g s _ v e c t
2018-02-12 17:53:00 +00:00
2016-09-06 14:02:07 +01:00
eret
2018-06-14 11:23:38 +01:00
sb
2016-09-06 14:02:07 +01:00
2020-09-15 11:46:34 +01:00
.macro invalid_vector label, t a r g e t = _ _ g u e s t _ e x i t _ p a n i c
2015-10-25 08:01:56 +00:00
.align 2
2021-02-22 16:49:56 +00:00
SYM_ C O D E _ S T A R T _ L O C A L ( \ l a b e l )
2015-10-25 08:01:56 +00:00
b \ t a r g e t
2020-02-18 19:58:37 +00:00
SYM_ C O D E _ E N D ( \ l a b e l )
2015-10-25 08:01:56 +00:00
.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 _ 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
.ltorg
.align 11
2019-06-18 16:17:34 +01:00
.macro check_preamble_length start, e n d
/* kvm_patch_vector_branch() generates code that jumps over the preamble. */
.if ( ( \ end- \ s t a r t ) ! = K V M _ V E C T O R _ P R E A M B L E )
.error " KVM v e c t o r p r e a m b l e l e n g t h m i s m a t c h "
.endif
.endm
2018-02-12 17:53:00 +00:00
.macro valid_vect target
.align 7
2019-06-18 16:17:34 +01:00
661 :
2019-06-18 16:17:36 +01:00
esb
2018-02-12 17:53:00 +00:00
stp x0 , x1 , [ s p , #- 16 ] !
2019-06-18 16:17:34 +01:00
662 :
2018-02-12 17:53:00 +00:00
b \ t a r g e t
2019-06-18 16:17:34 +01:00
check_ p r e a m b l e _ l e n g t h 6 6 1 b , 6 6 2 b
2018-02-12 17:53:00 +00:00
.endm
.macro invalid_vect target
.align 7
2019-06-18 16:17:34 +01:00
661 :
2019-06-18 16:17:36 +01:00
nop
2020-09-15 11:46:34 +01:00
stp x0 , x1 , [ s p , #- 16 ] !
2019-06-18 16:17:34 +01:00
662 :
2018-02-27 17:38:08 +00:00
b \ t a r g e t
2019-06-18 16:17:34 +01:00
check_ p r e a m b l e _ l e n g t h 6 6 1 b , 6 6 2 b
2018-02-12 17:53:00 +00:00
.endm
2020-02-18 19:58:37 +00:00
SYM_ C O D E _ S T A R T ( _ _ k v m _ h y p _ v e c t o r )
2018-02-12 17:53:00 +00: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
2018-10-17 20:21:16 +02:00
valid_ v e c t e l 2 _ s y n c / / S y n c h r o n o u s E L 2 h
2018-02-12 17:53:00 +00:00
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
2021-02-19 16:39:31 +00:00
valid_ v e c t e l 1 _ f i q / / F I Q 6 4 - b i t E L 1
2018-02-12 17:53:00 +00:00
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
2021-02-19 16:39:31 +00:00
valid_ v e c t e l 1 _ f i q / / F I Q 3 2 - b i t E L 1
2018-02-12 17:53:00 +00:00
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
2020-02-18 19:58:37 +00:00
SYM_ C O D E _ E N D ( _ _ k v m _ h y p _ v e c t o r )
2018-04-10 11:36:45 +01:00
2020-11-13 11:38:44 +00:00
.macro spectrev2_smccc_wa1_smc
sub s p , s p , #( 8 * 4 )
stp x2 , x3 , [ s p , #( 8 * 0 ) ]
stp x0 , x1 , [ s p , #( 8 * 2 ) ]
mov w0 , #A R M _ S M C C C _ A R C H _ W O R K A R O U N D _ 1
smc #0
ldp x2 , x3 , [ s p , #( 8 * 0 ) ]
add s p , s p , #( 8 * 2 )
.endm
.macro hyp_ventry indirect, s p e c t r e v2
.align 7
2019-06-18 16:17:36 +01:00
1 : esb
2020-11-13 11:38:44 +00:00
.if \ spectrev2 ! = 0
spectrev2 _ s m c c c _ w a1 _ s m c
.else
2019-06-18 16:17:35 +01:00
stp x0 , x1 , [ s p , #- 16 ] !
2020-11-13 11:38:44 +00:00
.endif
.if \ indirect ! = 0
alternative_ c b k v m _ p a t c h _ v e c t o r _ b r a n c h
/ *
2020-11-13 11:38:45 +00:00
* For A R M 6 4 _ S P E C T R E _ V 3 A c o n f i g u r a t i o n s , t h e s e N O P s g e t r e p l a c e d w i t h :
2020-11-13 11:38:44 +00:00
*
* movz x0 , #( a d d r & 0xffff )
* movk x0 , #( ( a d d r > > 16 ) & 0 x f f f f ) , l s l #16
* movk x0 , #( ( a d d r > > 32 ) & 0 x f f f f ) , l s l #32
* br x0
*
* Where :
* addr = k e r n _ h y p _ v a ( _ _ k v m _ h y p _ v e c t o r ) + v e c t o r - o f f s e t + K V M _ V E C T O R _ P R E A M B L E .
* See k v m _ p a t c h _ v e c t o r _ b r a n c h f o r d e t a i l s .
* /
2018-04-10 11:36:45 +01:00
nop
nop
nop
2020-11-13 11:38:44 +00:00
nop
alternative_ c b _ e n d
.endif
b _ _ k v m _ h y p _ v e c t o r + ( 1 b - 0 b + K V M _ V E C T O R _ P R E A M B L E )
2018-04-10 11:36:45 +01:00
.endm
2020-11-13 11:38:44 +00:00
.macro generate_vectors indirect, s p e c t r e v2
2018-04-10 11:36:45 +01:00
0 :
.rept 16
2020-11-13 11:38:44 +00:00
hyp_ v e n t r y \ i n d i r e c t , \ s p e c t r e v2
2018-04-10 11:36:45 +01:00
.endr
.org 0b + SZ_ 2 K / / S a f e t y m e a s u r e
.endm
.align 11
2020-02-18 19:58:38 +00:00
SYM_ C O D E _ S T A R T ( _ _ b p _ h a r d e n _ h y p _ v e c s )
2020-11-13 11:38:44 +00:00
generate_ v e c t o r s i n d i r e c t = 0 , s p e c t r e v2 = 1 / / H Y P _ V E C T O R _ S P E C T R E _ D I R E C T
generate_ v e c t o r s i n d i r e c t = 1 , s p e c t r e v2 = 0 / / H Y P _ V E C T O R _ I N D I R E C T
generate_ v e c t o r s i n d i r e c t = 1 , s p e c t r e v2 = 1 / / H Y P _ V E C T O R _ S P E C T R E _ I N D I R E C T
2020-02-18 19:58:38 +00:00
1 : .org _ _ b p _ h a r d e n _ h y p _ v e c s + _ _ B P _ H A R D E N _ H Y P _ V E C S _ S Z
.org 1b
SYM_ C O D E _ E N D ( _ _ b p _ h a r d e n _ h y p _ v e c s )