2013-06-21 11:57:56 +01:00
/ *
* Copyright ( C ) 2 0 1 2 ,2 0 1 3 - 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 / > .
* /
# include < l i n u x / l i n k a g e . h >
# include < l i n u x / i r q c h i p / a r m - g i c . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / m e m o r y . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / k v m . h >
# include < a s m / k v m _ a s m . h >
# include < a s m / k v m _ a r m . h >
# include < a s m / k v m _ m m u . h >
.text
.pushsection .hyp .text , " ax"
/ *
* Save t h e V G I C C P U s t a t e i n t o m e m o r y
* x0 : Register p o i n t i n g t o V C P U s t r u c t
* Do n o t c o r r u p t x1 ! ! !
* /
ENTRY( _ _ s a v e _ v g i c _ v2 _ s t a t e )
__save_vgic_v2_state :
/* Get VGIC VCTRL base into x2 */
ldr x2 , [ x0 , #V C P U _ K V M ]
kern_ h y p _ v a x2
ldr x2 , [ x2 , #K V M _ V G I C _ V C T R L ]
kern_ h y p _ v a x2
cbz x2 , 2 f / / d i s a b l e d
/* Compute the address of struct vgic_cpu */
add x3 , x0 , #V C P U _ V G I C _ C P U
/* Save all interesting registers */
ldr w5 , [ x2 , #G I C H _ V M C R ]
ldr w6 , [ x2 , #G I C H _ M I S R ]
ldr w7 , [ x2 , #G I C H _ E I S R 0 ]
ldr w8 , [ x2 , #G I C H _ E I S R 1 ]
ldr w9 , [ x2 , #G I C H _ E L R S R 0 ]
ldr w10 , [ x2 , #G I C H _ E L R S R 1 ]
ldr w11 , [ x2 , #G I C H _ A P R ]
CPU_ B E ( r e v w5 , w5 )
CPU_ B E ( r e v w6 , w6 )
CPU_ B E ( r e v w7 , w7 )
CPU_ B E ( r e v w8 , w8 )
CPU_ B E ( r e v w9 , w9 )
CPU_ B E ( r e v w10 , w10 )
CPU_ B E ( r e v w11 , w11 )
str w5 , [ x3 , #V G I C _ V 2 _ C P U _ V M C R ]
str w6 , [ x3 , #V G I C _ V 2 _ C P U _ M I S R ]
2014-09-28 16:04:26 +02:00
CPU_ L E ( s t r w7 , [ x3 , #V G I C _ V 2 _ C P U _ E I S R ] )
CPU_ L E ( s t r w8 , [ x3 , #( V G I C _ V 2 _ C P U _ E I S R + 4 ) ] )
CPU_ L E ( s t r w9 , [ x3 , #V G I C _ V 2 _ C P U _ E L R S R ] )
CPU_ L E ( s t r w10 , [ x3 , #( V G I C _ V 2 _ C P U _ E L R S R + 4 ) ] )
CPU_ B E ( s t r w7 , [ x3 , #( V G I C _ V 2 _ C P U _ E I S R + 4 ) ] )
CPU_ B E ( s t r w8 , [ x3 , #V G I C _ V 2 _ C P U _ E I S R ] )
CPU_ B E ( s t r w9 , [ x3 , #( V G I C _ V 2 _ C P U _ E L R S R + 4 ) ] )
CPU_ B E ( s t r w10 , [ x3 , #V G I C _ V 2 _ C P U _ E L R S R ] )
2013-06-21 11:57:56 +01:00
str w11 , [ x3 , #V G I C _ V 2 _ C P U _ A P R ]
/* Clear GICH_HCR */
str w z r , [ x2 , #G I C H _ H C R ]
/* Save list registers */
add x2 , x2 , #G I C H _ L R 0
ldr w4 , [ x3 , #V G I C _ C P U _ N R _ L R ]
add x3 , x3 , #V G I C _ V 2 _ C P U _ L R
1 : ldr w5 , [ x2 ] , #4
CPU_ B E ( r e v w5 , w5 )
str w5 , [ x3 ] , #4
sub w4 , w4 , #1
cbnz w4 , 1 b
2 :
ret
ENDPROC( _ _ s a v e _ v g i c _ v2 _ s t a t e )
/ *
* Restore t h e V G I C C P U s t a t e f r o m m e m o r y
* x0 : Register p o i n t i n g t o V C P U s t r u c t
* /
ENTRY( _ _ r e s t o r e _ v g i c _ v2 _ s t a t e )
__restore_vgic_v2_state :
/* Get VGIC VCTRL base into x2 */
ldr x2 , [ x0 , #V C P U _ K V M ]
kern_ h y p _ v a x2
ldr x2 , [ x2 , #K V M _ V G I C _ V C T R L ]
kern_ h y p _ v a x2
cbz x2 , 2 f / / d i s a b l e d
/* Compute the address of struct vgic_cpu */
add x3 , x0 , #V C P U _ V G I C _ C P U
/* We only restore a minimal set of registers */
ldr w4 , [ x3 , #V G I C _ V 2 _ C P U _ H C R ]
ldr w5 , [ x3 , #V G I C _ V 2 _ C P U _ V M C R ]
ldr w6 , [ x3 , #V G I C _ V 2 _ C P U _ A P R ]
CPU_ B E ( r e v w4 , w4 )
CPU_ B E ( r e v w5 , w5 )
CPU_ B E ( r e v w6 , w6 )
str w4 , [ x2 , #G I C H _ H C R ]
str w5 , [ x2 , #G I C H _ V M C R ]
str w6 , [ x2 , #G I C H _ A P R ]
/* Restore list registers */
add x2 , x2 , #G I C H _ L R 0
ldr w4 , [ x3 , #V G I C _ C P U _ N R _ L R ]
add x3 , x3 , #V G I C _ V 2 _ C P U _ L R
1 : ldr w5 , [ x3 ] , #4
CPU_ B E ( r e v w5 , w5 )
str w5 , [ x2 ] , #4
sub w4 , w4 , #1
cbnz w4 , 1 b
2 :
ret
ENDPROC( _ _ r e s t o r e _ v g i c _ v2 _ s t a t e )
.popsection