2008-07-09 02:06:46 +04:00
/ *
Asm v e r s i o n s o f X e n p v - o p s , s u i t a b l e f o r e i t h e r d i r e c t u s e o r i n l i n i n g .
The i n l i n e v e r s i o n s a r e t h e s a m e a s t h e d i r e c t - u s e v e r s i o n s , w i t h t h e
pre- a n d p o s t - a m b l e c h o p p e d o f f .
This c o d e i s e n c o d e d f o r s i z e r a t h e r t h a n a b s o l u t e e f f i c i e n c y ,
with a v i e w t o b e i n g a b l e t o i n l i n e a s m u c h a s p o s s i b l e .
We o n l y b o t h e r w i t h d i r e c t f o r m s ( i e , v c p u i n p d a ) o f t h e o p e r a t i o n s
here; the indirect forms are better handled in C, since they're
generally t o o l a r g e t o i n l i n e a n y w a y .
* /
# include < l i n u x / l i n k a g e . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / p r o c e s s o r - f l a g s . h >
2008-07-09 02:07:14 +04:00
# include < a s m / e r r n o . h >
# include < a s m / s e g m e n t . h >
2008-07-09 02:06:46 +04:00
# include < x e n / i n t e r f a c e / x e n . h >
# define R E L O C ( x , v ) . g l o b l x ## _ r e l o c ; x # # _ r e l o c = v
# define E N D P A T C H ( x ) . g l o b l x ## _ e n d ; x # # _ e n d = .
/* Pseudo-flag used for virtual NMI, which we don't implement yet */
# define X E N _ E F L A G S _ N M I 0 x80 0 0 0 0 0 0
# if 0
# include < a s m / p e r c p u . h >
/ *
Enable e v e n t s . T h i s c l e a r s t h e e v e n t m a s k a n d t e s t s t h e p e n d i n g
event s t a t u s w i t h o n e a n d o p e r a t i o n . I f t h e r e a r e p e n d i n g
events, t h e n e n t e r t h e h y p e r v i s o r t o g e t t h e m h a n d l e d .
* /
ENTRY( x e n _ i r q _ e n a b l e _ d i r e c t )
/* Unmask events */
movb $ 0 , P E R _ C P U _ V A R ( x e n _ v c p u _ i n f o , X E N _ v c p u _ i n f o _ m a s k )
/ * Preempt h e r e d o e s n ' t m a t t e r b e c a u s e t h a t w i l l d e a l w i t h
any p e n d i n g i n t e r r u p t s . T h e p e n d i n g c h e c k m a y e n d u p b e i n g
run o n t h e w r o n g C P U , b u t t h a t d o e s n ' t h u r t . * /
/* Test for pending */
testb $ 0 x f f , P E R _ C P U _ V A R ( x e n _ v c p u _ i n f o , X E N _ v c p u _ i n f o _ p e n d i n g )
jz 1 f
2 : call c h e c k _ e v e n t s
1 :
ENDPATCH( x e n _ i r q _ e n a b l e _ d i r e c t )
ret
ENDPROC( x e n _ i r q _ e n a b l e _ d i r e c t )
RELOC( x e n _ i r q _ e n a b l e _ d i r e c t , 2 b + 1 )
/ *
Disabling e v e n t s i s s i m p l y a m a t t e r o f m a k i n g t h e e v e n t m a s k
non- z e r o .
* /
ENTRY( x e n _ i r q _ d i s a b l e _ d i r e c t )
movb $ 1 , P E R _ C P U _ V A R ( x e n _ v c p u _ i n f o , X E N _ v c p u _ i n f o _ m a s k )
ENDPATCH( x e n _ i r q _ d i s a b l e _ d i r e c t )
ret
ENDPROC( x e n _ i r q _ d i s a b l e _ d i r e c t )
RELOC( x e n _ i r q _ d i s a b l e _ d i r e c t , 0 )
/ *
( xen_ ) s a v e _ f l i s u s e d t o g e t t h e c u r r e n t i n t e r r u p t e n a b l e s t a t u s .
Callers e x p e c t t h e s t a t u s t o b e i n X 8 6 _ E F L A G S _ I F , a n d o t h e r b i t s
may b e s e t i n t h e r e t u r n v a l u e . W e t a k e a d v a n t a g e o f t h i s b y
making s u r e t h a t X 8 6 _ E F L A G S _ I F h a s t h e r i g h t v a l u e ( a n d o t h e r b i t s
in t h a t b y t e a r e 0 ) , b u t o t h e r b i t s i n t h e r e t u r n v a l u e a r e
undefined. W e n e e d t o t o g g l e t h e s t a t e o f t h e b i t , b e c a u s e
Xen a n d x86 u s e o p p o s i t e s e n s e s ( m a s k v s e n a b l e ) .
* /
ENTRY( x e n _ s a v e _ f l _ d i r e c t )
testb $ 0 x f f , P E R _ C P U _ V A R ( x e n _ v c p u _ i n f o , X E N _ v c p u _ i n f o _ m a s k )
setz % a h
addb % a h ,% a h
ENDPATCH( x e n _ s a v e _ f l _ d i r e c t )
ret
ENDPROC( x e n _ s a v e _ f l _ d i r e c t )
RELOC( x e n _ s a v e _ f l _ d i r e c t , 0 )
/ *
In p r i n c i p l e t h e c a l l e r s h o u l d b e p a s s i n g u s a v a l u e r e t u r n
from x e n _ s a v e _ f l _ d i r e c t , b u t f o r r o b u s t n e s s s a k e w e t e s t o n l y
the X 8 6 _ E F L A G S _ I F f l a g r a t h e r t h a n t h e w h o l e b y t e . A f t e r
setting t h e i n t e r r u p t m a s k s t a t e , i t c h e c k s f o r u n m a s k e d
pending e v e n t s a n d e n t e r s t h e h y p e r v i s o r t o g e t t h e m d e l i v e r e d
if s o .
* /
ENTRY( x e n _ r e s t o r e _ f l _ d i r e c t )
testb $ X 8 6 _ E F L A G S _ I F > > 8 , % a h
setz P E R _ C P U _ V A R ( x e n _ v c p u _ i n f o , X E N _ v c p u _ i n f o _ m a s k )
/ * Preempt h e r e d o e s n ' t m a t t e r b e c a u s e t h a t w i l l d e a l w i t h
any p e n d i n g i n t e r r u p t s . T h e p e n d i n g c h e c k m a y e n d u p b e i n g
run o n t h e w r o n g C P U , b u t t h a t d o e s n ' t h u r t . * /
/* check for unmasked and pending */
cmpw $ 0 x00 0 1 , P E R _ C P U _ V A R ( x e n _ v c p u _ i n f o , X E N _ v c p u _ i n f o _ p e n d i n g )
jz 1 f
2 : call c h e c k _ e v e n t s
1 :
ENDPATCH( x e n _ r e s t o r e _ f l _ d i r e c t )
ret
ENDPROC( x e n _ r e s t o r e _ f l _ d i r e c t )
RELOC( x e n _ r e s t o r e _ f l _ d i r e c t , 2 b + 1 )
/ *
Force a n e v e n t c h e c k b y m a k i n g a h y p e r c a l l ,
but p r e s e r v e r e g s b e f o r e m a k i n g t h e c a l l .
* /
check_events :
push % r a x
push % r c x
push % r d x
push % r s i
push % r d i
push % r8
push % r9
push % r10
push % r11
call f o r c e _ e v t c h n _ c a l l b a c k
pop % r11
pop % r10
pop % r9
pop % r8
pop % r d i
pop % r s i
pop % r d x
pop % r c x
pop % r a x
ret
# endif
2008-07-09 02:07:00 +04:00
ENTRY( x e n _ a d j u s t _ e x c e p t i o n _ f r a m e )
mov 8 + 0 ( % r s p ) ,% r c x
mov 8 + 8 ( % r s p ) ,% r11
ret $ 1 6
2008-07-09 02:07:14 +04:00
hypercall_ i r e t = h y p e r c a l l _ p a g e + _ _ H Y P E R V I S O R _ i r e t * 3 2
/ *
Xen6 4 i r e t f r a m e :
ss
rsp
rflags
cs
rip < - - s t a n d a r d i r e t f r a m e
flags
rcx }
r1 1 } < - - p u s h e d b y h y p e r c a l l p a g e
rsp - > r a x }
* /
2008-07-09 02:06:46 +04:00
ENTRY( x e n _ i r e t )
pushq $ 0
2008-07-09 02:07:14 +04:00
1 : jmp h y p e r c a l l _ i r e t
ENDPATCH( x e n _ i r e t )
RELOC( x e n _ i r e t , 1 b + 1 )
2008-07-09 02:06:46 +04:00
2008-07-09 02:07:14 +04:00
/ *
sysexit i s n o t u s e d f o r 6 4 - b i t p r o c e s s e s , s o i t ' s
only e v e r u s e d t o r e t u r n t o 3 2 - b i t c o m p a t u s e r s p a c e .
* /
2008-07-09 02:06:46 +04:00
ENTRY( x e n _ s y s e x i t )
2008-07-09 02:07:14 +04:00
pushq $ _ _ U S E R 3 2 _ D S
pushq % r c x
pushq $ X 8 6 _ E F L A G S _ I F
pushq $ _ _ U S E R 3 2 _ C S
pushq % r d x
pushq $ V G C F _ i n _ s y s c a l l
1 : jmp h y p e r c a l l _ i r e t
ENDPATCH( x e n _ s y s e x i t )
RELOC( x e n _ s y s e x i t , 1 b + 1 )
ENTRY( x e n _ s y s r e t 6 4 )
/ * We' r e a l r e a d y o n t h e u s e r m o d e s t a c k a t t h i s p o i n t , b u t s t i l l
with t h e k e r n e l g s , s o w e c a n e a s i l y s w i t c h b a c k * /
movq % r s p , % g s : p d a _ o l d r s p
movq % g s : p d a _ k e r n e l s t a c k ,% r s p
pushq $ _ _ U S E R _ D S
pushq % g s : p d a _ o l d r s p
pushq % r11
pushq $ _ _ U S E R _ C S
pushq % r c x
pushq $ V G C F _ i n _ s y s c a l l
1 : jmp h y p e r c a l l _ i r e t
ENDPATCH( x e n _ s y s r e t 6 4 )
RELOC( x e n _ s y s r e t 6 4 , 1 b + 1 )
ENTRY( x e n _ s y s r e t 3 2 )
/ * We' r e a l r e a d y o n t h e u s e r m o d e s t a c k a t t h i s p o i n t , b u t s t i l l
with t h e k e r n e l g s , s o w e c a n e a s i l y s w i t c h b a c k * /
movq % r s p , % g s : p d a _ o l d r s p
movq % g s : p d a _ k e r n e l s t a c k , % r s p
pushq $ _ _ U S E R 3 2 _ D S
pushq % g s : p d a _ o l d r s p
pushq % r11
pushq $ _ _ U S E R 3 2 _ C S
pushq % r c x
pushq $ V G C F _ i n _ s y s c a l l
1 : jmp h y p e r c a l l _ i r e t
ENDPATCH( x e n _ s y s r e t 3 2 )
RELOC( x e n _ s y s r e t 3 2 , 1 b + 1 )
/ *
Xen h a n d l e s s y s c a l l c a l l b a c k s m u c h l i k e o r d i n a r y e x c e p t i o n s ,
which m e a n s w e h a v e :
- kernel g s
- kernel r s p
- an i r e t - l i k e s t a c k f r a m e o n t h e s t a c k ( i n c l u d i n g r c x a n d r11 ) :
ss
rsp
rflags
cs
rip
r1 1
rsp- > r c x
In a l l t h e e n t r y p o i n t s , w e u n d o a l l t h a t t o m a k e i t l o o k
like a C P U - g e n e r a t e d s y s c a l l / s y s e n t e r a n d j u m p t o t h e n o r m a l
entrypoint.
* /
.macro undo_xen_syscall
mov 0 * 8 ( % r s p ) ,% r c x
mov 1 * 8 ( % r s p ) ,% r11
mov 5 * 8 ( % r s p ) ,% r s p
.endm
/* Normal 64-bit system call target */
ENTRY( x e n _ s y s c a l l _ t a r g e t )
undo_ x e n _ s y s c a l l
jmp s y s t e m _ c a l l _ a f t e r _ s w a p g s
ENDPROC( x e n _ s y s c a l l _ t a r g e t )
# ifdef C O N F I G _ I A 3 2 _ E M U L A T I O N
/* 32-bit compat syscall target */
ENTRY( x e n _ s y s c a l l 3 2 _ t a r g e t )
undo_ x e n _ s y s c a l l
jmp i a32 _ c s t a r _ t a r g e t
ENDPROC( x e n _ s y s c a l l 3 2 _ t a r g e t )
/* 32-bit compat sysenter target */
ENTRY( x e n _ s y s e n t e r _ t a r g e t )
undo_ x e n _ s y s c a l l
jmp i a32 _ s y s e n t e r _ t a r g e t
ENDPROC( x e n _ s y s e n t e r _ t a r g e t )
# else / * ! C O N F I G _ I A 3 2 _ E M U L A T I O N * /
ENTRY( x e n _ s y s c a l l 3 2 _ t a r g e t )
ENTRY( x e n _ s y s e n t e r _ t a r g e t )
lea 1 6 ( % r s p ) , % r s p / * s t r i p % r c x ,% r11 * /
mov $ - E N O S Y S , % r a x
pushq $ V G C F _ i n _ s y s c a l l
jmp h y p e r c a l l _ i r e t
ENDPROC( x e n _ s y s c a l l 3 2 _ t a r g e t )
ENDPROC( x e n _ s y s e n t e r _ t a r g e t )
# endif / * C O N F I G _ I A 3 2 _ E M U L A T I O N * /