2012-11-21 18:34:01 -08:00
/ *
2013-08-01 13:22:33 -07:00
* This f i l e i s s u b j e c t t o t h e t e r m s a n d c o n d i t i o n s o f t h e G N U G e n e r a l P u b l i c
* License. S e e t h e f i l e " C O P Y I N G " i n t h e m a i n d i r e c t o r y o f t h i s a r c h i v e
* for m o r e d e t a i l s .
*
* Main e n t r y p o i n t f o r t h e g u e s t , e x c e p t i o n h a n d l i n g .
*
* Copyright ( C ) 2 0 1 2 M I P S T e c h n o l o g i e s , I n c . A l l r i g h t s r e s e r v e d .
* Authors : Sanjay L a l < s a n j a y l @kymasys.com>
* /
2012-11-21 18:34:01 -08:00
# include < a s m / a s m . h >
# include < a s m / a s m m a c r o . h >
# include < a s m / r e g d e f . h >
# include < a s m / m i p s r e g s . h >
# include < a s m / s t a c k f r a m e . h >
# include < a s m / a s m - o f f s e t s . h >
# define _ C _ L A B E L ( x ) x
# define M I P S X ( n a m e ) m i p s32 _ ## n a m e
# define C A L L F R A M E _ S I Z 3 2
/ *
* VECTOR
* exception v e c t o r e n t r y p o i n t
* /
# define V E C T O R ( x , r e g m a s k ) \
.ent _ C_ L A B E L ( x ) ,0 ; \
EXPORT( x ) ;
# define V E C T O R _ E N D ( x ) \
EXPORT( x ) ;
/* Overload, Danger Will Robinson!! */
# define P T _ H O S T _ A S I D P T _ B V A D D R
# define P T _ H O S T _ U S E R L O C A L P T _ E P C
# define C P 0 _ D D A T A _ L O $ 2 8 ,3
# define C P 0 _ E B A S E $ 1 5 ,1
# define C P 0 _ I N T C T L $ 1 2 ,1
# define C P 0 _ S R S C T L $ 1 2 ,2
# define C P 0 _ S R S M A P $ 1 2 ,3
# define C P 0 _ H W R E N A $ 7 ,0
/* Resume Flags */
# define R E S U M E _ F L A G _ H O S T ( 1 < < 1 ) / * R e s u m e h o s t ? * /
# define R E S U M E _ G U E S T 0
# define R E S U M E _ H O S T R E S U M E _ F L A G _ H O S T
/ *
* __kvm_mips_vcpu_run : entry p o i n t t o t h e g u e s t
* a0 : run
* a1 : vcpu
* /
2013-08-01 13:22:33 -07:00
.set noreorder
.set noat
2013-08-01 13:22:34 -07:00
FEXPORT( _ _ k v m _ m i p s _ v c p u _ r u n )
2013-08-01 13:22:33 -07:00
/* k0/k1 not being used in host kernel context */
2013-08-01 13:22:35 -07:00
INT_ A D D I U k 1 , s p , - P T _ S I Z E
2013-08-01 13:22:33 -07:00
LONG_ S $ 0 , P T _ R 0 ( k 1 )
LONG_ S $ 1 , P T _ R 1 ( k 1 )
LONG_ S $ 2 , P T _ R 2 ( k 1 )
LONG_ S $ 3 , P T _ R 3 ( k 1 )
LONG_ S $ 4 , P T _ R 4 ( k 1 )
LONG_ S $ 5 , P T _ R 5 ( k 1 )
LONG_ S $ 6 , P T _ R 6 ( k 1 )
LONG_ S $ 7 , P T _ R 7 ( k 1 )
LONG_ S $ 8 , P T _ R 8 ( k 1 )
LONG_ S $ 9 , P T _ R 9 ( k 1 )
LONG_ S $ 1 0 , P T _ R 1 0 ( k 1 )
LONG_ S $ 1 1 , P T _ R 1 1 ( k 1 )
LONG_ S $ 1 2 , P T _ R 1 2 ( k 1 )
LONG_ S $ 1 3 , P T _ R 1 3 ( k 1 )
LONG_ S $ 1 4 , P T _ R 1 4 ( k 1 )
LONG_ S $ 1 5 , P T _ R 1 5 ( k 1 )
LONG_ S $ 1 6 , P T _ R 1 6 ( k 1 )
LONG_ S $ 1 7 , P T _ R 1 7 ( k 1 )
LONG_ S $ 1 8 , P T _ R 1 8 ( k 1 )
LONG_ S $ 1 9 , P T _ R 1 9 ( k 1 )
LONG_ S $ 2 0 , P T _ R 2 0 ( k 1 )
LONG_ S $ 2 1 , P T _ R 2 1 ( k 1 )
LONG_ S $ 2 2 , P T _ R 2 2 ( k 1 )
LONG_ S $ 2 3 , P T _ R 2 3 ( k 1 )
LONG_ S $ 2 4 , P T _ R 2 4 ( k 1 )
LONG_ S $ 2 5 , P T _ R 2 5 ( k 1 )
2012-11-21 18:34:01 -08:00
2014-06-26 12:11:34 -07:00
/ *
* XXXKYMA k 0 / k 1 n o t s a v e d , n o t b e i n g u s e d i f w e g o t h e r e t h r o u g h
* an i o c t l ( )
* /
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
LONG_ S $ 2 8 , P T _ R 2 8 ( k 1 )
LONG_ S $ 2 9 , P T _ R 2 9 ( k 1 )
LONG_ S $ 3 0 , P T _ R 3 0 ( k 1 )
LONG_ S $ 3 1 , P T _ R 3 1 ( k 1 )
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* Save hi/lo */
mflo v0
LONG_ S v0 , P T _ L O ( k 1 )
mfhi v1
LONG_ S v1 , P T _ H I ( k 1 )
2012-11-21 18:34:01 -08:00
/* Save host status */
2013-08-01 13:22:33 -07:00
mfc0 v0 , C P 0 _ S T A T U S
LONG_ S v0 , P T _ S T A T U S ( k 1 )
2012-11-21 18:34:01 -08:00
/* Save host ASID, shove it into the BVADDR location */
2013-08-01 13:22:33 -07:00
mfc0 v1 , C P 0 _ E N T R Y H I
andi v1 , 0 x f f
LONG_ S v1 , P T _ H O S T _ A S I D ( k 1 )
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* Save DDATA_LO, will be used to store pointer to vcpu */
mfc0 v1 , C P 0 _ D D A T A _ L O
LONG_ S v1 , P T _ H O S T _ U S E R L O C A L ( k 1 )
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* DDATA_LO has pointer to vcpu */
mtc0 a1 , C P 0 _ D D A T A _ L O
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* Offset into vcpu->arch */
2013-08-01 13:22:35 -07:00
INT_ A D D I U k 1 , a1 , V C P U _ H O S T _ A R C H
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/ *
* Save t h e h o s t s t a c k t o V C P U , u s e d f o r e x c e p t i o n p r o c e s s i n g
* when w e e x i t f r o m t h e G u e s t
* /
LONG_ S s p , V C P U _ H O S T _ S T A C K ( k 1 )
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* Save the kernel gp as well */
LONG_ S g p , V C P U _ H O S T _ G P ( k 1 )
2012-11-21 18:34:01 -08:00
2014-06-26 12:11:34 -07:00
/ *
* Setup s t a t u s r e g i s t e r f o r r u n n i n g t h e g u e s t i n U M , i n t e r r u p t s
* are d i s a b l e d
* /
2013-08-01 13:22:33 -07:00
li k 0 , ( S T 0 _ E X L | K S U _ U S E R | S T 0 _ B E V )
mtc0 k 0 , C P 0 _ S T A T U S
ehb
/* load up the new EBASE */
LONG_ L k 0 , V C P U _ G U E S T _ E B A S E ( k 1 )
mtc0 k 0 , C P 0 _ E B A S E
/ *
* Now t h a t t h e n e w E B A S E h a s b e e n l o a d e d , u n s e t B E V , s e t
* interrupt m a s k a s i t w a s b u t m a k e s u r e t h a t t i m e r i n t e r r u p t s
* are e n a b l e d
* /
li k 0 , ( S T 0 _ E X L | K S U _ U S E R | S T 0 _ I E )
andi v0 , v0 , S T 0 _ I M
or k 0 , k 0 , v0
mtc0 k 0 , C P 0 _ S T A T U S
ehb
2012-11-21 18:34:01 -08:00
/* Set Guest EPC */
2013-08-01 13:22:33 -07:00
LONG_ L t 0 , V C P U _ P C ( k 1 )
mtc0 t 0 , C P 0 _ E P C
2012-11-21 18:34:01 -08:00
FEXPORT( _ _ k v m _ m i p s _ l o a d _ a s i d )
2013-08-01 13:22:33 -07:00
/* Set the ASID for the Guest Kernel */
2013-08-01 13:22:35 -07:00
INT_ S L L t 0 , t 0 , 1 / * w i t h k s e g 0 @ 0x40000000, kernel */
2013-08-01 13:22:33 -07:00
/* addresses shift to 0x80000000 */
bltz t 0 , 1 f / * I f k e r n e l * /
2013-08-01 13:22:35 -07:00
INT_ A D D I U t 1 , k 1 , V C P U _ G U E S T _ K E R N E L _ A S I D / * ( B D ) * /
INT_ A D D I U t 1 , k 1 , V C P U _ G U E S T _ U S E R _ A S I D / * e l s e u s e r * /
2012-11-21 18:34:01 -08:00
1 :
2014-06-26 12:11:34 -07:00
/* t1: contains the base of the ASID array, need to get the cpu id */
2013-08-01 13:22:33 -07:00
LONG_ L t 2 , T I _ C P U ( $ 2 8 ) / * s m p _ p r o c e s s o r _ i d * /
2013-08-01 13:22:35 -07:00
INT_ S L L t 2 , t 2 , 2 / * x4 * /
REG_ A D D U t 3 , t 1 , t 2
2013-08-01 13:22:33 -07:00
LONG_ L k 0 , ( t 3 )
andi k 0 , k 0 , 0 x f f
mtc0 k 0 , C P 0 _ E N T R Y H I
ehb
/* Disable RDHWR access */
mtc0 z e r o , C P 0 _ H W R E N A
/* Now load up the Guest Context from VCPU */
LONG_ L $ 1 , V C P U _ R 1 ( k 1 )
LONG_ L $ 2 , V C P U _ R 2 ( k 1 )
LONG_ L $ 3 , V C P U _ R 3 ( k 1 )
LONG_ L $ 4 , V C P U _ R 4 ( k 1 )
LONG_ L $ 5 , V C P U _ R 5 ( k 1 )
LONG_ L $ 6 , V C P U _ R 6 ( k 1 )
LONG_ L $ 7 , V C P U _ R 7 ( k 1 )
LONG_ L $ 8 , V C P U _ R 8 ( k 1 )
LONG_ L $ 9 , V C P U _ R 9 ( k 1 )
LONG_ L $ 1 0 , V C P U _ R 1 0 ( k 1 )
LONG_ L $ 1 1 , V C P U _ R 1 1 ( k 1 )
LONG_ L $ 1 2 , V C P U _ R 1 2 ( k 1 )
LONG_ L $ 1 3 , V C P U _ R 1 3 ( k 1 )
LONG_ L $ 1 4 , V C P U _ R 1 4 ( k 1 )
LONG_ L $ 1 5 , V C P U _ R 1 5 ( k 1 )
LONG_ L $ 1 6 , V C P U _ R 1 6 ( k 1 )
LONG_ L $ 1 7 , V C P U _ R 1 7 ( k 1 )
LONG_ L $ 1 8 , V C P U _ R 1 8 ( k 1 )
LONG_ L $ 1 9 , V C P U _ R 1 9 ( k 1 )
LONG_ L $ 2 0 , V C P U _ R 2 0 ( k 1 )
LONG_ L $ 2 1 , V C P U _ R 2 1 ( k 1 )
LONG_ L $ 2 2 , V C P U _ R 2 2 ( k 1 )
LONG_ L $ 2 3 , V C P U _ R 2 3 ( k 1 )
LONG_ L $ 2 4 , V C P U _ R 2 4 ( k 1 )
LONG_ L $ 2 5 , V C P U _ R 2 5 ( k 1 )
/* k0/k1 loaded up later */
LONG_ L $ 2 8 , V C P U _ R 2 8 ( k 1 )
LONG_ L $ 2 9 , V C P U _ R 2 9 ( k 1 )
LONG_ L $ 3 0 , V C P U _ R 3 0 ( k 1 )
LONG_ L $ 3 1 , V C P U _ R 3 1 ( k 1 )
/* Restore hi/lo */
LONG_ L k 0 , V C P U _ L O ( k 1 )
mtlo k 0
LONG_ L k 0 , V C P U _ H I ( k 1 )
mthi k 0
2012-11-21 18:34:01 -08:00
FEXPORT( _ _ k v m _ m i p s _ l o a d _ k 0 k 1 )
/* Restore the guest's k0/k1 registers */
2013-08-01 13:22:33 -07:00
LONG_ L k 0 , V C P U _ R 2 6 ( k 1 )
LONG_ L k 1 , V C P U _ R 2 7 ( k 1 )
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* Jump to guest */
2012-11-21 18:34:01 -08:00
eret
VECTOR( M I P S X ( e x c e p t i o n ) , u n k n o w n )
2014-06-26 12:11:34 -07:00
/* Find out what mode we came from and jump to the proper handler. */
2013-08-01 13:22:33 -07:00
mtc0 k 0 , C P 0 _ E R R O R E P C #01 : S a v e g u e s t k 0
ehb #02 :
mfc0 k 0 , C P 0 _ E B A S E #02 : G e t E B A S E
2013-08-01 13:22:35 -07:00
INT_ S R L k 0 , k 0 , 1 0 #03 : G e t r i d o f C P U N u m
INT_ S L L k 0 , k 0 , 1 0 #04
2013-08-01 13:22:33 -07:00
LONG_ S k 1 , 0 x30 0 0 ( k 0 ) #05 : S a v e k 1 @ offset 0x3000
2014-06-26 12:11:34 -07:00
INT_ A D D I U k 0 , k 0 , 0 x20 0 0 #06 : E x c e p t i o n h a n d l e r i s
# installed @ offset 0x2000
2013-08-01 13:22:33 -07:00
j k 0 #07 : j u m p t o t h e f u n c t i o n
nop #08 : b r a n c h d e l a y s l o t
2012-11-21 18:34:01 -08:00
VECTOR_ E N D ( M I P S X ( e x c e p t i o n E n d ) )
.end MIPSX( e x c e p t i o n )
/ *
* Generic G u e s t e x c e p t i o n h a n d l e r . W e e n d u p h e r e w h e n t h e g u e s t
* does s o m e t h i n g t h a t c a u s e s a t r a p t o k e r n e l m o d e .
* /
NESTED ( M I P S X ( G u e s t E x c e p t i o n ) , C A L L F R A M E _ S I Z , r a )
2013-08-01 13:22:33 -07:00
/* Get the VCPU pointer from DDTATA_LO */
mfc0 k 1 , C P 0 _ D D A T A _ L O
2013-08-01 13:22:35 -07:00
INT_ A D D I U k 1 , k 1 , V C P U _ H O S T _ A R C H
2013-08-01 13:22:33 -07:00
/* Start saving Guest context to VCPU */
LONG_ S $ 0 , V C P U _ R 0 ( k 1 )
LONG_ S $ 1 , V C P U _ R 1 ( k 1 )
LONG_ S $ 2 , V C P U _ R 2 ( k 1 )
LONG_ S $ 3 , V C P U _ R 3 ( k 1 )
LONG_ S $ 4 , V C P U _ R 4 ( k 1 )
LONG_ S $ 5 , V C P U _ R 5 ( k 1 )
LONG_ S $ 6 , V C P U _ R 6 ( k 1 )
LONG_ S $ 7 , V C P U _ R 7 ( k 1 )
LONG_ S $ 8 , V C P U _ R 8 ( k 1 )
LONG_ S $ 9 , V C P U _ R 9 ( k 1 )
LONG_ S $ 1 0 , V C P U _ R 1 0 ( k 1 )
LONG_ S $ 1 1 , V C P U _ R 1 1 ( k 1 )
LONG_ S $ 1 2 , V C P U _ R 1 2 ( k 1 )
LONG_ S $ 1 3 , V C P U _ R 1 3 ( k 1 )
LONG_ S $ 1 4 , V C P U _ R 1 4 ( k 1 )
LONG_ S $ 1 5 , V C P U _ R 1 5 ( k 1 )
LONG_ S $ 1 6 , V C P U _ R 1 6 ( k 1 )
LONG_ S $ 1 7 , V C P U _ R 1 7 ( k 1 )
LONG_ S $ 1 8 , V C P U _ R 1 8 ( k 1 )
LONG_ S $ 1 9 , V C P U _ R 1 9 ( k 1 )
LONG_ S $ 2 0 , V C P U _ R 2 0 ( k 1 )
LONG_ S $ 2 1 , V C P U _ R 2 1 ( k 1 )
LONG_ S $ 2 2 , V C P U _ R 2 2 ( k 1 )
LONG_ S $ 2 3 , V C P U _ R 2 3 ( k 1 )
LONG_ S $ 2 4 , V C P U _ R 2 4 ( k 1 )
LONG_ S $ 2 5 , V C P U _ R 2 5 ( k 1 )
/* Guest k0/k1 saved later */
LONG_ S $ 2 8 , V C P U _ R 2 8 ( k 1 )
LONG_ S $ 2 9 , V C P U _ R 2 9 ( k 1 )
LONG_ S $ 3 0 , V C P U _ R 3 0 ( k 1 )
LONG_ S $ 3 1 , V C P U _ R 3 1 ( k 1 )
2014-06-26 12:11:34 -07:00
/* We need to save hi/lo and restore them on the way out */
2013-08-01 13:22:33 -07:00
mfhi t 0
LONG_ S t 0 , V C P U _ H I ( k 1 )
mflo t 0
LONG_ S t 0 , V C P U _ L O ( k 1 )
/* Finally save guest k0/k1 to VCPU */
mfc0 t 0 , C P 0 _ E R R O R E P C
LONG_ S t 0 , V C P U _ R 2 6 ( k 1 )
/* Get GUEST k1 and save it in VCPU */
2013-08-01 13:22:35 -07:00
PTR_ L I t 1 , ~ 0 x2 f f
2013-08-01 13:22:33 -07:00
mfc0 t 0 , C P 0 _ E B A S E
and t 0 , t 0 , t 1
LONG_ L t 0 , 0 x30 0 0 ( t 0 )
LONG_ S t 0 , V C P U _ R 2 7 ( k 1 )
/* Now that context has been saved, we can use other registers */
/* Restore vcpu */
mfc0 a1 , C P 0 _ D D A T A _ L O
move s1 , a1
/* Restore run (vcpu->run) */
LONG_ L a0 , V C P U _ R U N ( a1 )
/* Save pointer to run in s0, will be saved by the compiler */
move s0 , a0
2014-06-26 12:11:34 -07:00
/ *
* Save H o s t l e v e l E P C , B a d V a d d r a n d C a u s e t o V C P U , u s e f u l t o
* process t h e e x c e p t i o n
* /
2013-08-01 13:22:33 -07:00
mfc0 k 0 ,C P 0 _ E P C
LONG_ S k 0 , V C P U _ P C ( k 1 )
mfc0 k 0 , C P 0 _ B A D V A D D R
LONG_ S k 0 , V C P U _ H O S T _ C P 0 _ B A D V A D D R ( k 1 )
mfc0 k 0 , C P 0 _ C A U S E
LONG_ S k 0 , V C P U _ H O S T _ C P 0 _ C A U S E ( k 1 )
mfc0 k 0 , C P 0 _ E N T R Y H I
LONG_ S k 0 , V C P U _ H O S T _ E N T R Y H I ( k 1 )
/* Now restore the host state just enough to run the handlers */
/* Swtich EBASE to the one used by Linux */
/* load up the host EBASE */
mfc0 v0 , C P 0 _ S T A T U S
.set at
or k 0 , v0 , S T 0 _ B E V
.set noat
mtc0 k 0 , C P 0 _ S T A T U S
ehb
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
LONG_ L k 0 , V C P U _ H O S T _ E B A S E ( k 1 )
mtc0 k 0 ,C P 0 _ E B A S E
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
.set at
and v0 , v0 , ~ ( S T 0 _ E X L | K S U _ U S E R | S T 0 _ I E )
or v0 , v0 , S T 0 _ C U 0
.set noat
mtc0 v0 , C P 0 _ S T A T U S
ehb
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* Load up host GP */
LONG_ L g p , V C P U _ H O S T _ G P ( k 1 )
/* Need a stack before we can jump to "C" */
LONG_ L s p , V C P U _ H O S T _ S T A C K ( k 1 )
/* Saved host state */
2013-08-01 13:22:35 -07:00
INT_ A D D I U s p , s p , - P T _ S I Z E
2013-08-01 13:22:33 -07:00
2014-06-26 12:11:34 -07:00
/ *
* XXXKYMA d o w e n e e d t o l o a d t h e h o s t A S I D , m a y b e n o t b e c a u s e t h e
2013-08-01 13:22:33 -07:00
* kernel e n t r i e s a r e m a r k e d G L O B A L , n e e d t o v e r i f y
* /
/* Restore host DDATA_LO */
LONG_ L k 0 , P T _ H O S T _ U S E R L O C A L ( s p )
mtc0 k 0 , C P 0 _ D D A T A _ L O
/* Restore RDHWR access */
2013-08-01 13:22:35 -07:00
PTR_ L I k 0 , 0 x20 0 0 0 0 0 F
2013-08-01 13:22:33 -07:00
mtc0 k 0 , C P 0 _ H W R E N A
/* Jump to handler */
2012-11-21 18:34:01 -08:00
FEXPORT( _ _ k v m _ m i p s _ j u m p _ t o _ h a n d l e r )
2014-06-26 12:11:34 -07:00
/ *
* XXXKYMA : not s u r e i f t h i s i s s a f e , h o w l a r g e i s t h e s t a c k ? ?
2013-08-01 13:22:33 -07:00
* Now j u m p t o t h e k v m _ m i p s _ h a n d l e _ e x i t ( ) t o s e e i f w e c a n d e a l
2014-06-26 12:11:34 -07:00
* with t h i s i n t h e k e r n e l
* /
2013-08-01 13:22:35 -07:00
PTR_ L A t 9 , k v m _ m i p s _ h a n d l e _ e x i t
2013-08-01 13:22:33 -07:00
jalr. h b t 9
2013-08-01 13:22:35 -07:00
INT_ A D D I U s p , s p , - C A L L F R A M E _ S I Z / * B D S l o t * /
2013-08-01 13:22:33 -07:00
/* Return from handler Make sure interrupts are disabled */
di
ehb
2014-06-26 12:11:34 -07:00
/ *
* XXXKYMA : k0 / k 1 c o u l d h a v e b e e n b l o w n a w a y i f w e p r o c e s s e d
2013-08-01 13:22:33 -07:00
* an e x c e p t i o n w h i l e w e w e r e h a n d l i n g t h e e x c e p t i o n f r o m t h e
* guest, r e l o a d k 1
* /
move k 1 , s1
2013-08-01 13:22:35 -07:00
INT_ A D D I U k 1 , k 1 , V C P U _ H O S T _ A R C H
2013-08-01 13:22:33 -07:00
2014-06-26 12:11:34 -07:00
/ *
* Check r e t u r n v a l u e , s h o u l d t e l l u s i f w e a r e r e t u r n i n g t o t h e
2013-08-01 13:22:33 -07:00
* host ( h a n d l e I / O e t c ) o r r e s u m i n g t h e g u e s t
* /
andi t 0 , v0 , R E S U M E _ H O S T
bnez t 0 , _ _ k v m _ m i p s _ r e t u r n _ t o _ h o s t
nop
2012-11-21 18:34:01 -08:00
__kvm_mips_return_to_guest :
2013-08-01 13:22:33 -07:00
/* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
mtc0 s1 , C P 0 _ D D A T A _ L O
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
/* Load up the Guest EBASE to minimize the window where BEV is set */
LONG_ L t 0 , V C P U _ G U E S T _ E B A S E ( k 1 )
/* Switch EBASE back to the one used by KVM */
mfc0 v1 , C P 0 _ S T A T U S
.set at
or k 0 , v1 , S T 0 _ B E V
.set noat
mtc0 k 0 , C P 0 _ S T A T U S
ehb
mtc0 t 0 , C P 0 _ E B A S E
/* Setup status register for running guest in UM */
.set at
or v1 , v1 , ( S T 0 _ E X L | K S U _ U S E R | S T 0 _ I E )
and v1 , v1 , ~ S T 0 _ C U 0
.set noat
mtc0 v1 , C P 0 _ S T A T U S
ehb
2012-11-21 18:34:01 -08:00
/* Set Guest EPC */
2013-08-01 13:22:33 -07:00
LONG_ L t 0 , V C P U _ P C ( k 1 )
mtc0 t 0 , C P 0 _ E P C
/* Set the ASID for the Guest Kernel */
2013-08-01 13:22:35 -07:00
INT_ S L L t 0 , t 0 , 1 / * w i t h k s e g 0 @ 0x40000000, kernel */
2013-08-01 13:22:33 -07:00
/* addresses shift to 0x80000000 */
bltz t 0 , 1 f / * I f k e r n e l * /
2013-08-01 13:22:35 -07:00
INT_ A D D I U t 1 , k 1 , V C P U _ G U E S T _ K E R N E L _ A S I D / * ( B D ) * /
INT_ A D D I U t 1 , k 1 , V C P U _ G U E S T _ U S E R _ A S I D / * e l s e u s e r * /
2012-11-21 18:34:01 -08:00
1 :
2013-08-01 13:22:33 -07:00
/* t1: contains the base of the ASID array, need to get the cpu id */
LONG_ L t 2 , T I _ C P U ( $ 2 8 ) / * s m p _ p r o c e s s o r _ i d * /
2013-08-01 13:22:35 -07:00
INT_ S L L t 2 , t 2 , 2 / * x4 * /
REG_ A D D U t 3 , t 1 , t 2
2013-08-01 13:22:33 -07:00
LONG_ L k 0 , ( t 3 )
andi k 0 , k 0 , 0 x f f
mtc0 k 0 ,C P 0 _ E N T R Y H I
ehb
/* Disable RDHWR access */
mtc0 z e r o , C P 0 _ H W R E N A
/* load the guest context from VCPU and return */
LONG_ L $ 0 , V C P U _ R 0 ( k 1 )
LONG_ L $ 1 , V C P U _ R 1 ( k 1 )
LONG_ L $ 2 , V C P U _ R 2 ( k 1 )
LONG_ L $ 3 , V C P U _ R 3 ( k 1 )
LONG_ L $ 4 , V C P U _ R 4 ( k 1 )
LONG_ L $ 5 , V C P U _ R 5 ( k 1 )
LONG_ L $ 6 , V C P U _ R 6 ( k 1 )
LONG_ L $ 7 , V C P U _ R 7 ( k 1 )
LONG_ L $ 8 , V C P U _ R 8 ( k 1 )
LONG_ L $ 9 , V C P U _ R 9 ( k 1 )
LONG_ L $ 1 0 , V C P U _ R 1 0 ( k 1 )
LONG_ L $ 1 1 , V C P U _ R 1 1 ( k 1 )
LONG_ L $ 1 2 , V C P U _ R 1 2 ( k 1 )
LONG_ L $ 1 3 , V C P U _ R 1 3 ( k 1 )
LONG_ L $ 1 4 , V C P U _ R 1 4 ( k 1 )
LONG_ L $ 1 5 , V C P U _ R 1 5 ( k 1 )
LONG_ L $ 1 6 , V C P U _ R 1 6 ( k 1 )
LONG_ L $ 1 7 , V C P U _ R 1 7 ( k 1 )
LONG_ L $ 1 8 , V C P U _ R 1 8 ( k 1 )
LONG_ L $ 1 9 , V C P U _ R 1 9 ( k 1 )
LONG_ L $ 2 0 , V C P U _ R 2 0 ( k 1 )
LONG_ L $ 2 1 , V C P U _ R 2 1 ( k 1 )
LONG_ L $ 2 2 , V C P U _ R 2 2 ( k 1 )
LONG_ L $ 2 3 , V C P U _ R 2 3 ( k 1 )
LONG_ L $ 2 4 , V C P U _ R 2 4 ( k 1 )
LONG_ L $ 2 5 , V C P U _ R 2 5 ( k 1 )
/* $/k1 loaded later */
LONG_ L $ 2 8 , V C P U _ R 2 8 ( k 1 )
LONG_ L $ 2 9 , V C P U _ R 2 9 ( k 1 )
LONG_ L $ 3 0 , V C P U _ R 3 0 ( k 1 )
LONG_ L $ 3 1 , V C P U _ R 3 1 ( k 1 )
2012-11-21 18:34:01 -08:00
FEXPORT( _ _ k v m _ m i p s _ s k i p _ g u e s t _ r e s t o r e )
2013-08-01 13:22:33 -07:00
LONG_ L k 0 , V C P U _ H I ( k 1 )
mthi k 0
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
LONG_ L k 0 , V C P U _ L O ( k 1 )
mtlo k 0
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
LONG_ L k 0 , V C P U _ R 2 6 ( k 1 )
LONG_ L k 1 , V C P U _ R 2 7 ( k 1 )
2012-11-21 18:34:01 -08:00
2013-08-01 13:22:33 -07:00
eret
2012-11-21 18:34:01 -08:00
__kvm_mips_return_to_host :
2013-08-01 13:22:33 -07:00
/* EBASE is already pointing to Linux */
LONG_ L k 1 , V C P U _ H O S T _ S T A C K ( k 1 )
2013-08-01 13:22:35 -07:00
INT_ A D D I U k 1 ,k 1 , - P T _ S I Z E
2013-08-01 13:22:33 -07:00
/* Restore host DDATA_LO */
LONG_ L k 0 , P T _ H O S T _ U S E R L O C A L ( k 1 )
mtc0 k 0 , C P 0 _ D D A T A _ L O
/* Restore host ASID */
LONG_ L k 0 , P T _ H O S T _ A S I D ( s p )
andi k 0 , 0 x f f
mtc0 k 0 ,C P 0 _ E N T R Y H I
ehb
/* Load context saved on the host stack */
LONG_ L $ 0 , P T _ R 0 ( k 1 )
LONG_ L $ 1 , P T _ R 1 ( k 1 )
2014-06-26 12:11:34 -07:00
/ *
* r2 / v0 i s t h e r e t u r n c o d e , s h i f t i t d o w n b y 2 ( a r i t h m e t i c )
* to r e c o v e r t h e e r r c o d e
* /
2013-08-01 13:22:35 -07:00
INT_ S R A k 0 , v0 , 2
2013-08-01 13:22:33 -07:00
move $ 2 , k 0
LONG_ L $ 3 , P T _ R 3 ( k 1 )
LONG_ L $ 4 , P T _ R 4 ( k 1 )
LONG_ L $ 5 , P T _ R 5 ( k 1 )
LONG_ L $ 6 , P T _ R 6 ( k 1 )
LONG_ L $ 7 , P T _ R 7 ( k 1 )
LONG_ L $ 8 , P T _ R 8 ( k 1 )
LONG_ L $ 9 , P T _ R 9 ( k 1 )
LONG_ L $ 1 0 , P T _ R 1 0 ( k 1 )
LONG_ L $ 1 1 , P T _ R 1 1 ( k 1 )
LONG_ L $ 1 2 , P T _ R 1 2 ( k 1 )
LONG_ L $ 1 3 , P T _ R 1 3 ( k 1 )
LONG_ L $ 1 4 , P T _ R 1 4 ( k 1 )
LONG_ L $ 1 5 , P T _ R 1 5 ( k 1 )
LONG_ L $ 1 6 , P T _ R 1 6 ( k 1 )
LONG_ L $ 1 7 , P T _ R 1 7 ( k 1 )
LONG_ L $ 1 8 , P T _ R 1 8 ( k 1 )
LONG_ L $ 1 9 , P T _ R 1 9 ( k 1 )
LONG_ L $ 2 0 , P T _ R 2 0 ( k 1 )
LONG_ L $ 2 1 , P T _ R 2 1 ( k 1 )
LONG_ L $ 2 2 , P T _ R 2 2 ( k 1 )
LONG_ L $ 2 3 , P T _ R 2 3 ( k 1 )
LONG_ L $ 2 4 , P T _ R 2 4 ( k 1 )
LONG_ L $ 2 5 , P T _ R 2 5 ( k 1 )
/* Host k0/k1 were not saved */
LONG_ L $ 2 8 , P T _ R 2 8 ( k 1 )
LONG_ L $ 2 9 , P T _ R 2 9 ( k 1 )
LONG_ L $ 3 0 , P T _ R 3 0 ( k 1 )
LONG_ L k 0 , P T _ H I ( k 1 )
mthi k 0
LONG_ L k 0 , P T _ L O ( k 1 )
mtlo k 0
/* Restore RDHWR access */
2013-08-01 13:22:35 -07:00
PTR_ L I k 0 , 0 x20 0 0 0 0 0 F
2013-08-01 13:22:33 -07:00
mtc0 k 0 , C P 0 _ H W R E N A
/* Restore RA, which is the address we will return to */
LONG_ L r a , P T _ R 3 1 ( k 1 )
j r a
nop
2012-11-21 18:34:01 -08:00
VECTOR_ E N D ( M I P S X ( G u e s t E x c e p t i o n E n d ) )
.end MIPSX( G u e s t E x c e p t i o n )
MIPSX( e x c e p t i o n s ) :
# # # #
# # # # # The e x c e p t i o n h a n d l e r s .
# # # # #
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 0
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 1
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 2
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 3
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 4
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 5
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 6
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 7
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 8
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 9
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 10
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 11
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 12
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 13
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 14
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 15
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 16
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 17
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 18
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 19
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 20
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 21
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 22
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 23
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 24
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 25
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 26
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 27
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 28
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 29
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 30
.word _ C_ L A B E L ( M I P S X ( G u e s t E x c e p t i o n ) ) # 31