2009-10-30 08:47:09 +03: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 >
2010-04-16 02:11:46 +04:00
# ifdef C O N F I G _ P P C _ B O O K 3 S _ 6 4
2009-10-30 08:47:09 +03:00
# include < a s m / e x c e p t i o n - 6 4 s . h >
2010-04-16 02:11:46 +04:00
# endif
2009-10-30 08:47:09 +03:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Real M o d e h a n d l e r s t h a t n e e d t o b e i n l o w p h y s i c a l m e m o r y *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2010-04-16 02:11:46 +04: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 )
2011-01-20 09:50:21 +03:00
# define L O A D _ S H A D O W _ V C P U ( r e g ) G E T _ P A C A ( r e g )
2010-04-16 02:11:46 +04:00
# define S H A D O W _ V C P U _ O F F P A C A _ K V M _ S V C P U
# define M S R _ N O I R Q M S R _ K E R N E L & ~ ( M S R _ I R | M S R _ D R )
# define F U N C ( n a m e ) G L U E ( . ,n a m e )
2011-06-29 04:18:26 +04:00
kvmppc_skip_interrupt :
/ *
* Here a l l G P R s a r e u n c h a n g e d f r o m w h e n t h e i n t e r r u p t h a p p e n e d
* except f o r r13 , w h i c h i s s a v e d i n S P R G _ S C R A T C H 0 .
* /
mfspr r13 , S P R N _ S R R 0
addi r13 , r13 , 4
mtspr S P R N _ S R R 0 , r13
GET_ S C R A T C H 0 ( r13 )
rfid
b .
kvmppc_skip_Hinterrupt :
/ *
* Here a l l G P R s a r e u n c h a n g e d f r o m w h e n t h e i n t e r r u p t h a p p e n e d
* except f o r r13 , w h i c h i s s a v e d i n S P R G _ S C R A T C H 0 .
* /
mfspr r13 , S P R N _ H S R R 0
addi r13 , r13 , 4
mtspr S P R N _ H S R R 0 , r13
GET_ S C R A T C H 0 ( r13 )
hrfid
b .
2010-04-16 02:11:46 +04:00
2011-06-29 04:18:26 +04:00
# 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 )
2010-04-16 02:11:46 +04:00
# define S H A D O W _ V C P U _ O F F 0
# define M S R _ N O I R Q M S R _ K E R N E L
# define F U N C ( n a m e ) n a m e
2009-10-30 08:47:09 +03:00
.macro INTERRUPT_TRAMPOLINE intno
.global kvmppc_ t r a m p o l i n e _ \ i n t n o
kvmppc_ t r a m p o l i n e _ \ i n t n o :
2011-06-29 04:18:26 +04:00
mtspr S P R N _ S P R G _ S C R A T C H 0 , r13 / * S a v e r13 * /
2009-10-30 08:47:09 +03:00
/ *
* First t h i n g t o d o i s t o f i n d o u t i f w e ' r e c o m i n g
* from a K V M g u e s t o r a L i n u x p r o c e s s .
*
2010-04-16 02:11:46 +04:00
* To d i s t i n g u i s h , w e c h e c k a m a g i c b y t e i n t h e P A C A / c u r r e n t
2009-10-30 08:47:09 +03:00
* /
2011-06-29 04:18:26 +04:00
mfspr r13 , S P R N _ S P R G _ T H R E A D
lwz r13 , T H R E A D _ K V M _ S V C P U ( r13 )
/* PPC32 can have a NULL pointer - let's check for that */
mtspr S P R N _ S P R G _ S C R A T C H 1 , r12 / * S a v e r12 * /
2009-10-30 08:47:09 +03:00
mfcr r12
2011-06-29 04:18:26 +04:00
cmpwi r13 , 0
bne 1 f
2 : mtcr r12
mfspr r12 , S P R N _ S P R G _ S C R A T C H 1
mfspr r13 , S P R N _ S P R G _ S C R A T C H 0 / * r13 = o r i g i n a l r13 * /
b k v m p p c _ r e s u m e _ \ i n t n o / * G e t b a c k o r i g i n a l h a n d l e r * /
1 : tophys( r13 , r13 )
2010-04-16 02:11:46 +04:00
stw r12 , ( S H A D O W _ V C P U _ O F F + S V C P U _ S C R A T C H 1 ) ( r13 )
2011-06-29 04:18:26 +04:00
mfspr r12 , S P R N _ S P R G _ S C R A T C H 1
stw r12 , ( S H A D O W _ V C P U _ O F F + S V C P U _ S C R A T C H 0 ) ( r13 )
2010-04-16 02:11:46 +04:00
lbz r12 , ( S H A D O W _ V C P U _ O F F + S V C P U _ I N _ G U E S T ) ( r13 )
2010-01-08 04:58:04 +03:00
cmpwi r12 , K V M _ G U E S T _ M O D E _ N O N E
2009-10-30 08:47:09 +03:00
bne . . k v m p p c _ h a n d l e r _ h a s m a g i c _ \ i n t n o
/* No KVM guest? Then jump back to the Linux handler! */
2010-04-16 02:11:46 +04:00
lwz r12 , ( S H A D O W _ V C P U _ O F F + S V C P U _ S C R A T C H 1 ) ( r13 )
2011-06-29 04:18:26 +04:00
b 2 b
2009-10-30 08:47:09 +03:00
/* Now we know we're handling a KVM guest */
. .kvmppc_handler_hasmagic_ \ intno :
2010-01-08 04:58:04 +03:00
/* Should we just skip the faulting instruction? */
cmpwi r12 , K V M _ G U E S T _ M O D E _ S K I P
beq k v m p p c _ h a n d l e r _ s k i p _ i n s
2009-10-30 08:47:09 +03:00
/* Let's store which interrupt we're handling */
li r12 , \ i n t n o
/* Jump into the SLB exit code that goes to the highmem handler */
b k v m p p c _ h a n d l e r _ t r a m p o l i n e _ e x i t
.endm
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ S Y S T E M _ R E S E T
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ M A C H I N E _ C H E C K
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ D A T A _ S T O R A G E
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ I N S T _ S T O R A G E
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ E X T E R N A L
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ A L I G N M E N T
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ P R O G R A M
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ F P _ U N A V A I L
INTERRUPT_ T R A M P O L I N E 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
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ S Y S C A L L
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ T R A C E
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ P E R F M O N
INTERRUPT_ T R A M P O L I N E B O O K 3 S _ I N T E R R U P T _ A L T I V E C
2010-04-16 02:11:46 +04:00
2010-01-08 04:58:04 +03:00
/ *
* Bring u s b a c k t o t h e f a u l t i n g c o d e , b u t s k i p t h e
* faulting i n s t r u c t i o n .
*
* This i s a g e n e r i c e x i t p a t h f r o m t h e i n t e r r u p t
* trampolines a b o v e .
*
* Input R e g i s t e r s :
*
2010-04-16 02:11:46 +04:00
* R1 2 = f r e e
* R1 3 = S h a d o w V C P U ( P A C A )
* SVCPU. S C R A T C H 0 = g u e s t R 1 2
* SVCPU. S C R A T C H 1 = g u e s t C R
* SPRG_ S C R A T C H 0 = g u e s t R 1 3
2010-01-08 04:58:04 +03:00
*
* /
kvmppc_handler_skip_ins :
/* Patch the IP to the next instruction */
mfsrr0 r12
addi r12 , r12 , 4
mtsrr0 r12
/* Clean up all state */
2010-04-16 02:11:46 +04:00
lwz r12 , ( S H A D O W _ V C P U _ O F F + S V C P U _ S C R A T C H 1 ) ( r13 )
2010-01-08 04:58:04 +03:00
mtcr r12
2010-04-16 02:11:46 +04:00
PPC_ L L r12 , ( S H A D O W _ V C P U _ O F F + S V C P U _ S C R A T C H 0 ) ( r13 )
2011-04-05 07:59:58 +04:00
GET_ S C R A T C H 0 ( r13 )
2010-01-08 04:58:04 +03:00
/* And get back into the code */
RFI
2011-06-29 04:18:26 +04:00
# endif
2010-01-08 04:58:04 +03:00
2009-10-30 08:47:09 +03:00
/ *
* This t r a m p o l i n e b r i n g s u s b a c k t o a r e a l m o d e h a n d l e r
*
* Input R e g i s t e r s :
*
2010-01-08 04:58:03 +03:00
* R5 = S R R 0
* R6 = S R R 1
2009-10-30 08:47:09 +03:00
* LR = r e a l - m o d e I P
*
* /
.global kvmppc_handler_lowmem_trampoline
kvmppc_handler_lowmem_trampoline :
2010-01-08 04:58:03 +03:00
mtsrr0 r5
mtsrr1 r6
2009-10-30 08:47:09 +03:00
blr
kvmppc_handler_lowmem_trampoline_end :
2010-01-08 04:58:06 +03:00
/ *
* Call a f u n c t i o n i n r e a l m o d e
*
* Input R e g i s t e r s :
*
* R3 = f u n c t i o n
* R4 = M S R
2010-04-16 02:11:46 +04:00
* R5 = s c r a t c h r e g i s t e r
2010-01-08 04:58:06 +03:00
*
* /
_ GLOBAL( k v m p p c _ r m c a l l )
2010-04-16 02:11:46 +04:00
LOAD_ R E G _ I M M E D I A T E ( r5 , M S R _ N O I R Q )
mtmsr r5 / * D i s a b l e r e l o c a t i o n a n d i n t e r r u p t s , s o m t s r r
2010-01-08 04:58:06 +03:00
doesn' t g e t i n t e r r u p t e d * /
2010-04-16 02:11:46 +04:00
sync
2010-01-08 04:58:06 +03:00
mtsrr0 r3
mtsrr1 r4
RFI
2010-04-16 02:11:46 +04:00
# if 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 S T A C K _ L R I N T _ F R A M E _ S I Z E + 4
2010-07-29 17:04:20 +04:00
/* load_up_xxx have to run with MSR_DR=0 on Book3S_32 */
# define M S R _ E X T _ S T A R T \
PPC_ S T L r20 , _ N I P ( r1 ) ; \
mfmsr r20 ; \
LOAD_ R E G _ I M M E D I A T E ( r3 , M S R _ D R | M S R _ E E ) ; \
andc r3 ,r20 ,r3 ; /* Disable DR,EE */ \
mtmsr r3 ; \
sync
# define M S R _ E X T _ E N D \
mtmsr r20 ; /* Enable DR,EE */ \
sync; \
PPC_ L L r20 , _ N I P ( r1 )
2010-04-16 02:11:46 +04:00
# elif d e f i n e d ( C O N F I G _ P P C _ B O O K 3 S _ 6 4 )
# define S T A C K _ L R _ L I N K
2010-07-29 17:04:20 +04:00
# define M S R _ E X T _ S T A R T
# define M S R _ E X T _ E N D
2010-04-16 02:11:46 +04:00
# endif
2010-01-15 16:49:10 +03:00
/ *
* Activate c u r r e n t ' s e x t e r n a l f e a t u r e ( F P U / A l t i v e c / V S X )
* /
2010-04-16 02:11:46 +04:00
# define d e f i n e _ l o a d _ u p ( w h a t ) \
\
_ GLOBAL( k v m p p c _ l o a d _ u p _ ## w h a t ) ; \
PPC_ S T L U r1 , - I N T _ F R A M E _ S I Z E ( r1 ) ; \
mflr r3 ; \
PPC_ S T L r3 , S T A C K _ L R ( r1 ) ; \
2010-07-29 17:04:20 +04:00
MSR_ E X T _ S T A R T ; \
2010-04-16 02:11:46 +04:00
\
bl F U N C ( l o a d _ u p _ ## w h a t ) ; \
\
2010-07-29 17:04:20 +04:00
MSR_ E X T _ E N D ; \
2010-04-16 02:11:46 +04:00
PPC_ L L r3 , S T A C K _ L R ( r1 ) ; \
mtlr r3 ; \
addi r1 , r1 , I N T _ F R A M E _ S I Z E ; \
2010-01-15 16:49:10 +03:00
blr
define_ l o a d _ u p ( f p u )
# ifdef C O N F I G _ A L T I V E C
define_ l o a d _ u p ( a l t i v e c )
# endif
# ifdef C O N F I G _ V S X
define_ l o a d _ u p ( v s x )
# endif
2010-04-16 02:11:48 +04:00
# include " b o o k 3 s _ s e g m e n t . S "