2009-10-30 05:47:07 +00:00
/ *
* 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 ; if not, write to the Free Software
* Foundation, 5 1 F r a n k l i n S t r e e t , F i f t h F l o o r , B o s t o n , M A 0 2 1 1 0 - 1 3 0 1 , U S A .
*
* Copyright S U S E L i n u x P r o d u c t s G m b H 2 0 0 9
*
* Authors : Alexander G r a f < a g r a f @suse.de>
* /
# include < a s m / p p c _ a s m . h >
# include < a s m / k v m _ a s m . h >
# include < a s m / r e g . h >
# include < a s m / p a g e . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / e x c e p t i o n - 6 4 s . h >
2010-04-16 00:11:47 +02:00
# if d e f i n e d ( C O N F I G _ P P C _ B O O K 3 S _ 6 4 )
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
# define U L O N G _ S I Z E 8
# define F U N C ( n a m e ) G L U E ( . ,n a m e )
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
# define G E T _ S H A D O W _ V C P U ( r e g ) \
addi r e g , r13 , P A C A _ K V M _ S V C P U
# define D I S A B L E _ I N T E R R U P T S \
mfmsr r0 ; \
rldicl r0 ,r0 ,4 8 ,1 ; \
rotldi r0 ,r0 ,1 6 ; \
mtmsrd r0 ,1 ; \
# elif d e f i n e d ( C O N F I G _ P P C _ B O O K 3 S _ 3 2 )
# define U L O N G _ S I Z E 4
# define F U N C ( n a m e ) n a m e
# define G E T _ S H A D O W _ V C P U ( r e g ) \
lwz r e g , ( T H R E A D + T H R E A D _ K V M _ S V C P U ) ( r2 )
# define D I S A B L E _ I N T E R R U P T S \
mfmsr r0 ; \
rlwinm r0 ,r0 ,0 ,1 7 ,1 5 ; \
mtmsr r0 ; \
# endif / * C O N F I G _ P P C _ B O O K 3 S _ X X * /
# define V C P U _ G P R ( n ) ( V C P U _ G P R S + ( n * U L O N G _ S I Z E ) )
2010-01-04 22:19:25 +01:00
# define V C P U _ L O A D _ N V G P R S ( v c p u ) \
2010-04-16 00:11:47 +02:00
PPC_ L L r14 , V C P U _ G P R ( r14 ) ( v c p u ) ; \
PPC_ L L r15 , V C P U _ G P R ( r15 ) ( v c p u ) ; \
PPC_ L L r16 , V C P U _ G P R ( r16 ) ( v c p u ) ; \
PPC_ L L r17 , V C P U _ G P R ( r17 ) ( v c p u ) ; \
PPC_ L L r18 , V C P U _ G P R ( r18 ) ( v c p u ) ; \
PPC_ L L r19 , V C P U _ G P R ( r19 ) ( v c p u ) ; \
PPC_ L L r20 , V C P U _ G P R ( r20 ) ( v c p u ) ; \
PPC_ L L r21 , V C P U _ G P R ( r21 ) ( v c p u ) ; \
PPC_ L L r22 , V C P U _ G P R ( r22 ) ( v c p u ) ; \
PPC_ L L r23 , V C P U _ G P R ( r23 ) ( v c p u ) ; \
PPC_ L L r24 , V C P U _ G P R ( r24 ) ( v c p u ) ; \
PPC_ L L r25 , V C P U _ G P R ( r25 ) ( v c p u ) ; \
PPC_ L L r26 , V C P U _ G P R ( r26 ) ( v c p u ) ; \
PPC_ L L r27 , V C P U _ G P R ( r27 ) ( v c p u ) ; \
PPC_ L L r28 , V C P U _ G P R ( r28 ) ( v c p u ) ; \
PPC_ L L r29 , V C P U _ G P R ( r29 ) ( v c p u ) ; \
PPC_ L L r30 , V C P U _ G P R ( r30 ) ( v c p u ) ; \
PPC_ L L r31 , V C P U _ G P R ( r31 ) ( v c p u ) ; \
2010-01-04 22:19:25 +01:00
2009-10-30 05:47:07 +00:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Guest e n t r y / e x i t c o d e t h a t i s i n k e r n e l m o d u l e m e m o r y ( h i g h m e m ) *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * Registers :
* r3 : kvm_ r u n p o i n t e r
* r4 : vcpu p o i n t e r
* /
_ GLOBAL( _ _ k v m p p c _ v c p u _ e n t r y )
kvm_start_entry :
/* Write correct stack frame */
2010-04-16 00:11:47 +02:00
mflr r0
PPC_ S T L r0 ,P P C _ L R _ S T K O F F ( r1 )
2009-10-30 05:47:07 +00:00
/* Save host state to the stack */
2010-04-16 00:11:47 +02:00
PPC_ S T L U r1 , - S W I T C H _ F R A M E _ S I Z E ( r1 )
2009-10-30 05:47:07 +00:00
/* Save r3 (kvm_run) and r4 (vcpu) */
SAVE_ 2 G P R S ( 3 , r1 )
/* Save non-volatile registers (r14 - r31) */
SAVE_ N V G P R S ( r1 )
/* Save LR */
2010-04-16 00:11:47 +02:00
PPC_ S T L r0 , _ L I N K ( r1 )
2010-01-04 22:19:25 +01:00
/* Load non-volatile guest state from the vcpu */
VCPU_ L O A D _ N V G P R S ( r4 )
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
GET_ S H A D O W _ V C P U ( r5 )
2009-10-30 05:47:07 +00:00
/* Save R1/R2 in the PACA */
2010-04-16 00:11:47 +02:00
PPC_ S T L r1 , S V C P U _ H O S T _ R 1 ( r5 )
PPC_ S T L r2 , S V C P U _ H O S T _ R 2 ( r5 )
2010-01-08 02:58:03 +01:00
/* XXX swap in/out on load? */
2010-04-16 00:11:47 +02:00
PPC_ L L r3 , V C P U _ H I G H M E M _ H A N D L E R ( r4 )
PPC_ S T L r3 , S V C P U _ V M H A N D L E R ( r5 )
2009-10-30 05:47:07 +00:00
2010-01-08 02:58:03 +01:00
kvm_start_lightweight :
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
PPC_ L L r10 , V C P U _ S H A D O W _ M S R ( r4 ) / * r10 = v c p u - > a r c h . s h a d o w _ m s r * /
2009-10-30 05:47:07 +00:00
2010-01-08 02:58:03 +01:00
DISABLE_ I N T E R R U P T S
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
# ifdef C O N F I G _ P P C _ B O O K 3 S _ 6 4
2009-10-30 05:47:07 +00:00
/ * Some g u e s t s m a y n e e d t o h a v e d c b z s e t t o 3 2 b y t e l e n g t h .
*
* Usually w e e n s u r e t h a t b y p a t c h i n g t h e g u e s t ' s i n s t r u c t i o n s
* to t r a p o n d c b z a n d e m u l a t e i t i n t h e h y p e r v i s o r .
*
* If w e c a n , w e s h o u l d t e l l t h e C P U t o u s e 3 2 b y t e d c b z t h o u g h ,
* because t h a t ' s a l o t f a s t e r .
* /
2010-04-16 00:11:47 +02:00
PPC_ L L r3 , V C P U _ H F L A G S ( r4 )
2009-10-30 05:47:07 +00:00
rldicl. r3 , r3 , 0 , 6 3 / * C R = ( ( r3 & 1 ) = = 0 ) * /
beq n o _ d c b z 3 2 _ o n
mfspr r3 ,S P R N _ H I D 5
ori r3 , r3 , 0 x80 / * X X X H I D 5 _ d c b z 3 2 = 0 x80 * /
mtspr S P R N _ H I D 5 ,r3
no_dcbz32_on :
2010-04-16 00:11:47 +02:00
# endif / * C O N F I G _ P P C _ B O O K 3 S _ 6 4 * /
PPC_ L L r6 , V C P U _ R M C A L L ( r4 )
2010-01-08 02:58:06 +01:00
mtctr r6
2010-01-08 02:58:03 +01:00
2010-04-16 00:11:47 +02:00
PPC_ L L r3 , V C P U _ T R A M P O L I N E _ E N T E R ( r4 )
2010-01-08 02:58:06 +01:00
LOAD_ R E G _ I M M E D I A T E ( r4 , M S R _ K E R N E L & ~ ( M S R _ I R | M S R _ D R ) )
2010-01-08 02:58:03 +01:00
2010-04-16 00:11:47 +02:00
/* Jump to segment patching handler and into our guest */
2010-01-08 02:58:06 +01:00
bctr
2009-10-30 05:47:07 +00:00
/ *
* This i s t h e h a n d l e r i n m o d u l e m e m o r y . I t g e t s j u m p e d a t f r o m t h e
* lowmem t r a m p o l i n e c o d e , s o i t ' s b a s i c a l l y t h e g u e s t e x i t c o d e .
*
* /
.global kvmppc_handler_highmem
kvmppc_handler_highmem :
/ *
* Register u s a g e a t t h i s p o i n t :
*
2010-04-16 00:11:47 +02:00
* R1 = h o s t R 1
* R2 = h o s t R 2
* R1 2 = e x i t h a n d l e r i d
* R1 3 = P A C A
* SVCPU. * = g u e s t *
2009-10-30 05:47:07 +00:00
*
* /
2010-01-08 02:58:03 +01:00
/* R7 = vcpu */
2010-04-16 00:11:47 +02:00
PPC_ L L r7 , G P R 4 ( r1 )
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
# ifdef C O N F I G _ P P C _ B O O K 3 S _ 6 4
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
PPC_ L L r5 , V C P U _ H F L A G S ( r7 )
2009-10-30 05:47:07 +00:00
rldicl. r5 , r5 , 0 , 6 3 / * C R = ( ( r5 & 1 ) = = 0 ) * /
beq n o _ d c b z 3 2 _ o f f
2010-01-08 02:58:08 +01:00
li r4 , 0
2009-10-30 05:47:07 +00:00
mfspr r5 ,S P R N _ H I D 5
2010-01-08 02:58:08 +01:00
rldimi r5 ,r4 ,6 ,5 6
2009-10-30 05:47:07 +00:00
mtspr S P R N _ H I D 5 ,r5
no_dcbz32_off :
2010-04-16 00:11:47 +02:00
# endif / * C O N F I G _ P P C _ B O O K 3 S _ 6 4 * /
PPC_ S T L r14 , V C P U _ G P R ( r14 ) ( r7 )
PPC_ S T L r15 , V C P U _ G P R ( r15 ) ( r7 )
PPC_ S T L r16 , V C P U _ G P R ( r16 ) ( r7 )
PPC_ S T L r17 , V C P U _ G P R ( r17 ) ( r7 )
PPC_ S T L r18 , V C P U _ G P R ( r18 ) ( r7 )
PPC_ S T L r19 , V C P U _ G P R ( r19 ) ( r7 )
PPC_ S T L r20 , V C P U _ G P R ( r20 ) ( r7 )
PPC_ S T L r21 , V C P U _ G P R ( r21 ) ( r7 )
PPC_ S T L r22 , V C P U _ G P R ( r22 ) ( r7 )
PPC_ S T L r23 , V C P U _ G P R ( r23 ) ( r7 )
PPC_ S T L r24 , V C P U _ G P R ( r24 ) ( r7 )
PPC_ S T L r25 , V C P U _ G P R ( r25 ) ( r7 )
PPC_ S T L r26 , V C P U _ G P R ( r26 ) ( r7 )
PPC_ S T L r27 , V C P U _ G P R ( r27 ) ( r7 )
PPC_ S T L r28 , V C P U _ G P R ( r28 ) ( r7 )
PPC_ S T L r29 , V C P U _ G P R ( r29 ) ( r7 )
PPC_ S T L r30 , V C P U _ G P R ( r30 ) ( r7 )
PPC_ S T L r31 , V C P U _ G P R ( r31 ) ( r7 )
2009-10-30 05:47:07 +00:00
/* Restore host msr -> SRR1 */
2010-04-16 00:11:47 +02:00
PPC_ L L r6 , V C P U _ H O S T _ M S R ( r7 )
2009-10-30 05:47:07 +00:00
/ *
* For s o m e i n t e r r u p t s , w e n e e d t o c a l l t h e r e a l L i n u x
* handler, s o i t c a n d o w o r k f o r u s . T h i s h a s t o h a p p e n
* as i f t h e i n t e r r u p t a r r i v e d f r o m t h e k e r n e l t h o u g h ,
* so l e t ' s f a k e i t h e r e w h e r e m o s t s t a t e i s r e s t o r e d .
*
* Call L i n u x f o r h a r d w a r e i n t e r r u p t s / d e c r e m e n t e r
* r3 = a d d r e s s o f i n t e r r u p t h a n d l e r ( e x i t r e a s o n )
* /
2010-01-08 02:58:03 +01:00
cmpwi r12 , B O O K 3 S _ I N T E R R U P T _ E X T E R N A L
2009-10-30 05:47:07 +00:00
beq c a l l _ l i n u x _ h a n d l e r
2010-01-08 02:58:03 +01:00
cmpwi r12 , B O O K 3 S _ I N T E R R U P T _ D E C R E M E N T E R
2009-10-30 05:47:07 +00:00
beq c a l l _ l i n u x _ h a n d l e r
2010-04-20 02:49:47 +02:00
cmpwi r12 , B O O K 3 S _ I N T E R R U P T _ P E R F M O N
beq c a l l _ l i n u x _ h a n d l e r
2009-10-30 05:47:07 +00:00
2010-01-08 02:58:05 +01:00
/* Back to EE=1 */
mtmsr r6
2010-04-16 00:11:47 +02:00
sync
2010-01-08 02:58:05 +01:00
b k v m _ r e t u r n _ p o i n t
2009-10-30 05:47:07 +00:00
call_linux_handler :
/ *
* If w e l a n d h e r e w e n e e d t o j u m p b a c k t o t h e h a n d l e r w e
* came f r o m .
*
* We h a v e a p a g e t h a t w e c a n a c c e s s f r o m r e a l m o d e , s o l e t ' s
* jump b a c k t o t h a t a n d u s e i t a s a t r a m p o l i n e t o g e t b a c k i n t o t h e
* interrupt h a n d l e r !
*
* R3 s t i l l c o n t a i n s t h e e x i t c o d e ,
2010-01-08 02:58:05 +01:00
* R5 V C P U _ H O S T _ R E T I P a n d
* R6 V C P U _ H O S T _ M S R
2009-10-30 05:47:07 +00:00
* /
2010-01-08 02:58:05 +01:00
/* Restore host IP -> SRR0 */
2010-04-16 00:11:47 +02:00
PPC_ L L r5 , V C P U _ H O S T _ R E T I P ( r7 )
2010-01-08 02:58:05 +01:00
/ * XXX B e t t e r m o v e t o a s a f e f u n c t i o n ?
* What i f w e g e t a n H T A B f l u s h i n b e t w e e n m t s r r0 a n d m t s r r1 ? * /
2010-01-08 02:58:03 +01:00
mtlr r12
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
PPC_ L L r4 , V C P U _ T R A M P O L I N E _ L O W M E M ( r7 )
2010-01-08 02:58:03 +01:00
mtsrr0 r4
LOAD_ R E G _ I M M E D I A T E ( r3 , M S R _ K E R N E L & ~ ( M S R _ I R | M S R _ D R ) )
mtsrr1 r3
2009-10-30 05:47:07 +00:00
RFI
.global kvm_return_point
kvm_return_point :
/* Jump back to lightweight entry if we're supposed to */
/* go back into the guest */
2010-01-04 22:19:25 +01:00
/* Pass the exit number as 3rd argument to kvmppc_handle_exit */
2010-01-08 02:58:03 +01:00
mr r5 , r12
2010-01-04 22:19:25 +01:00
2009-10-30 05:47:07 +00:00
/* Restore r3 (kvm_run) and r4 (vcpu) */
REST_ 2 G P R S ( 3 , r1 )
2010-04-16 00:11:47 +02:00
bl F U N C ( k v m p p c _ h a n d l e _ e x i t )
2009-10-30 05:47:07 +00:00
2010-01-04 22:19:25 +01:00
/* If RESUME_GUEST, get back in the loop */
2009-10-30 05:47:07 +00:00
cmpwi r3 , R E S U M E _ G U E S T
2010-01-04 22:19:25 +01:00
beq k v m _ l o o p _ l i g h t w e i g h t
2009-10-30 05:47:07 +00:00
2010-01-04 22:19:25 +01:00
cmpwi r3 , R E S U M E _ G U E S T _ N V
beq k v m _ l o o p _ h e a v y w e i g h t
2009-10-30 05:47:07 +00:00
2010-01-04 22:19:25 +01:00
kvm_exit_loop :
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
PPC_ L L r4 , _ L I N K ( r1 )
2009-10-30 05:47:07 +00:00
mtlr r4
2010-01-04 22:19:25 +01:00
/* Restore non-volatile host registers (r14 - r31) */
REST_ N V G P R S ( r1 )
addi r1 , r1 , S W I T C H _ F R A M E _ S I Z E
blr
kvm_loop_heavyweight :
2009-10-30 05:47:07 +00:00
2010-04-16 00:11:47 +02:00
PPC_ L L r4 , _ L I N K ( r1 )
PPC_ S T L r4 , ( P P C _ L R _ S T K O F F + S W I T C H _ F R A M E _ S I Z E ) ( r1 )
2010-01-04 22:19:25 +01:00
/* Load vcpu and cpu_run */
2009-10-30 05:47:07 +00:00
REST_ 2 G P R S ( 3 , r1 )
2010-01-04 22:19:25 +01:00
/* Load non-volatile guest state from the vcpu */
VCPU_ L O A D _ N V G P R S ( r4 )
2009-10-30 05:47:07 +00:00
2010-01-04 22:19:25 +01:00
/* Jump back into the beginning of this function */
b k v m _ s t a r t _ l i g h t w e i g h t
2009-10-30 05:47:07 +00:00
2010-01-04 22:19:25 +01:00
kvm_loop_lightweight :
2009-10-30 05:47:07 +00:00
2010-01-04 22:19:25 +01:00
/* We'll need the vcpu pointer */
REST_ G P R ( 4 , r1 )
/* Jump back into the beginning of this function */
b k v m _ s t a r t _ l i g h t w e i g h t