2005-06-26 01:58:02 +04:00
/ *
* relocate_ k e r n e l . S - p u t t h e k e r n e l i m a g e i n p l a c e t o b o o t
* Copyright ( C ) 2 0 0 2 - 2 0 0 5 E r i c B i e d e r m a n < e b i e d e r m @xmission.com>
*
* This s o u r c e c o d e i s l i c e n s e d u n d e r 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 ,
* Version 2 . S e e t h e f i l e C O P Y I N G f o r m o r e d e t a i l s .
* /
# include < l i n u x / l i n k a g e . h >
2009-02-13 22:14:01 +03:00
# include < a s m / p a g e _ t y p e s . h >
2006-09-26 12:52:38 +04:00
# include < a s m / k e x e c . h >
2008-03-23 00:00:08 +03:00
# include < a s m / p r o c e s s o r - f l a g s . h >
2009-02-13 22:14:01 +03:00
# include < a s m / p g t a b l e _ t y p e s . h >
2005-06-26 01:58:02 +04:00
2006-09-26 12:52:38 +04:00
/ *
* Must b e r e l o c a t a b l e P I C c o d e c a l l a b l e a s a C f u n c t i o n
* /
# define P T R ( x ) ( x < < 3 )
2008-03-23 00:00:09 +03:00
# define P A G E _ A T T R ( _ P A G E _ P R E S E N T | _ P A G E _ R W | _ P A G E _ A C C E S S E D | _ P A G E _ D I R T Y )
2006-09-26 12:52:38 +04:00
2009-03-10 05:57:16 +03:00
/ *
* control_ p a g e + K E X E C _ C O N T R O L _ C O D E _ M A X _ S I Z E
* ~ control_ p a g e + P A G E _ S I Z E a r e u s e d a s d a t a s t o r a g e a n d s t a c k f o r
* jumping b a c k
* /
# define D A T A ( o f f s e t ) ( K E X E C _ C O N T R O L _ C O D E _ M A X _ S I Z E + ( o f f s e t ) )
/* Minimal CPU state */
# define R S P D A T A ( 0 x0 )
# define C R 0 D A T A ( 0 x8 )
# define C R 3 D A T A ( 0 x10 )
# define C R 4 D A T A ( 0 x18 )
/* other data */
# define C P _ P A _ T A B L E _ P A G E D A T A ( 0 x20 )
# define C P _ P A _ S W A P _ P A G E D A T A ( 0 x28 )
# define C P _ P A _ B A C K U P _ P A G E S _ M A P D A T A ( 0 x30 )
2006-09-26 12:52:38 +04:00
.text
2008-03-21 23:12:14 +03:00
.align PAGE_SIZE
2005-06-26 01:58:02 +04:00
.code64
2006-09-26 12:52:38 +04:00
.globl relocate_kernel
relocate_kernel :
2009-03-10 05:56:57 +03:00
/ *
* % rdi i n d i r e c t i o n _ p a g e
2006-09-26 12:52:38 +04:00
* % rsi p a g e _ l i s t
* % rdx s t a r t a d d r e s s
2009-03-10 05:57:16 +03:00
* % rcx p r e s e r v e _ c o n t e x t
2006-09-26 12:52:38 +04:00
* /
2009-03-10 05:57:16 +03:00
/* Save the CPU context, used for jumping back */
pushq % r b x
pushq % r b p
pushq % r12
pushq % r13
pushq % r14
pushq % r15
pushf
movq P T R ( V A _ C O N T R O L _ P A G E ) ( % r s i ) , % r11
movq % r s p , R S P ( % r11 )
movq % c r0 , % r a x
movq % r a x , C R 0 ( % r11 )
movq % c r3 , % r a x
movq % r a x , C R 3 ( % r11 )
movq % c r4 , % r a x
movq % r a x , C R 4 ( % r11 )
2005-06-26 01:58:02 +04:00
/* zero out flags, and disable interrupts */
pushq $ 0
popfq
2009-03-10 05:56:57 +03:00
/ *
* get p h y s i c a l a d d r e s s o f c o n t r o l p a g e n o w
* this i s i m p o s s i b l e a f t e r p a g e t a b l e s w i t c h
* /
2006-09-26 12:52:38 +04:00
movq P T R ( P A _ C O N T R O L _ P A G E ) ( % r s i ) , % r8
/* get physical address of page table now too */
2009-03-10 05:57:16 +03:00
movq P T R ( P A _ T A B L E _ P A G E ) ( % r s i ) , % r9
/* get physical address of swap page now */
movq P T R ( P A _ S W A P _ P A G E ) ( % r s i ) , % r10
/* save some information for jumping back */
movq % r9 , C P _ P A _ T A B L E _ P A G E ( % r11 )
movq % r10 , C P _ P A _ S W A P _ P A G E ( % r11 )
movq % r d i , C P _ P A _ B A C K U P _ P A G E S _ M A P ( % r11 )
2005-06-26 01:58:02 +04:00
2009-02-03 09:22:48 +03:00
/* Switch to the identity mapped page tables */
2009-03-10 05:57:16 +03:00
movq % r9 , % c r3
2006-09-26 12:52:38 +04:00
/* setup a new stack at the end of the physical control page */
2008-03-23 00:00:07 +03:00
lea P A G E _ S I Z E ( % r8 ) , % r s p
2006-09-26 12:52:38 +04:00
/* jump to identity mapped page */
addq $ ( i d e n t i t y _ m a p p e d - r e l o c a t e _ k e r n e l ) , % r8
pushq % r8
ret
identity_mapped :
2011-07-14 05:34:37 +04:00
/* set return address to 0 if not preserving context */
pushq $ 0
2006-09-26 12:52:38 +04:00
/* store the start address on the stack */
pushq % r d x
2005-06-26 01:58:02 +04:00
2009-03-10 05:56:57 +03:00
/ *
* Set c r0 t o a k n o w n s t a t e :
2008-03-23 00:00:08 +03:00
* - Paging e n a b l e d
* - Alignment c h e c k d i s a b l e d
* - Write p r o t e c t d i s a b l e d
* - No t a s k s w i t c h
* - Don' t d o F P s o f t w a r e e m u l a t i o n .
* - Proctected m o d e e n a b l e d
2005-06-26 01:58:02 +04:00
* /
movq % c r0 , % r a x
2008-03-23 00:00:08 +03:00
andq $ ~ ( X 8 6 _ C R 0 _ A M | X 8 6 _ C R 0 _ W P | X 8 6 _ C R 0 _ T S | X 8 6 _ C R 0 _ E M ) , % r a x
orl $ ( X 8 6 _ C R 0 _ P G | X 8 6 _ C R 0 _ P E ) , % e a x
2005-06-26 01:58:02 +04:00
movq % r a x , % c r0
2009-03-10 05:56:57 +03:00
/ *
* Set c r4 t o a k n o w n s t a t e :
2008-03-23 00:00:08 +03:00
* - physical a d d r e s s e x t e n s i o n e n a b l e d
2005-06-26 01:58:02 +04:00
* /
2008-03-23 00:00:08 +03:00
movq $ X 8 6 _ C R 4 _ P A E , % r a x
2005-06-26 01:58:02 +04:00
movq % r a x , % c r4
jmp 1 f
1 :
2009-02-03 09:22:48 +03:00
/* Flush the TLB (needed?) */
2009-03-10 05:57:16 +03:00
movq % r9 , % c r3
movq % r c x , % r11
call s w a p _ p a g e s
/ *
* To b e c e r t a i n o f a v o i d i n g p r o b l e m s w i t h s e l f - m o d i f y i n g c o d e
* I n e e d t o e x e c u t e a s e r i a l i z i n g i n s t r u c t i o n h e r e .
* So I f l u s h t h e T L B b y r e l o a d i n g % c r3 h e r e , i t ' s h a n d y ,
* and n o t p r o c e s s o r d e p e n d e n t .
* /
movq % c r3 , % r a x
movq % r a x , % c r3
/ *
* set a l l o f t h e r e g i s t e r s t o k n o w n v a l u e s
* leave % r s p a l o n e
* /
testq % r11 , % r11
jnz 1 f
xorq % r a x , % r a x
xorq % r b x , % r b x
xorq % r c x , % r c x
xorq % r d x , % r d x
xorq % r s i , % r s i
xorq % r d i , % r d i
xorq % r b p , % r b p
xorq % r8 , % r8
xorq % r9 , % r9
xorq % r10 , % r9
xorq % r11 , % r11
xorq % r12 , % r12
xorq % r13 , % r13
xorq % r14 , % r14
xorq % r15 , % r15
ret
1 :
popq % r d x
leaq P A G E _ S I Z E ( % r10 ) , % r s p
call * % r d x
/* get the re-entry point of the peer system */
movq 0 ( % r s p ) , % r b p
call 1 f
1 :
popq % r8
subq $ ( 1 b - r e l o c a t e _ k e r n e l ) , % r8
movq C P _ P A _ S W A P _ P A G E ( % r8 ) , % r10
movq C P _ P A _ B A C K U P _ P A G E S _ M A P ( % r8 ) , % r d i
movq C P _ P A _ T A B L E _ P A G E ( % r8 ) , % r a x
movq % r a x , % c r3
lea P A G E _ S I Z E ( % r8 ) , % r s p
call s w a p _ p a g e s
movq $ v i r t u a l _ m a p p e d , % r a x
pushq % r a x
ret
virtual_mapped :
movq R S P ( % r8 ) , % r s p
movq C R 4 ( % r8 ) , % r a x
movq % r a x , % c r4
movq C R 3 ( % r8 ) , % r a x
movq C R 0 ( % r8 ) , % r8
movq % r a x , % c r3
movq % r8 , % c r0
movq % r b p , % r a x
popf
popq % r15
popq % r14
popq % r13
popq % r12
popq % r b p
popq % r b x
ret
2005-06-26 01:58:02 +04:00
/* Do the copies */
2009-03-10 05:57:16 +03:00
swap_pages :
2005-06-26 01:58:02 +04:00
movq % r d i , % r c x / * P u t t h e p a g e _ l i s t i n % r c x * /
xorq % r d i , % r d i
xorq % r s i , % r s i
jmp 1 f
0 : /* top, read another word for the indirection page */
movq ( % r b x ) , % r c x
addq $ 8 , % r b x
1 :
testq $ 0 x1 , % r c x / * i s i t a d e s t i n a t i o n p a g e ? * /
jz 2 f
movq % r c x , % r d i
andq $ 0 x f f f f f f f f f f f f f00 0 , % r d i
jmp 0 b
2 :
testq $ 0 x2 , % r c x / * i s i t a n i n d i r e c t i o n p a g e ? * /
jz 2 f
movq % r c x , % r b x
andq $ 0 x f f f f f f f f f f f f f00 0 , % r b x
jmp 0 b
2 :
testq $ 0 x4 , % r c x / * i s i t t h e d o n e i n d i c a t o r ? * /
jz 2 f
jmp 3 f
2 :
testq $ 0 x8 , % r c x / * i s i t t h e s o u r c e i n d i c a t o r ? * /
jz 0 b / * I g n o r e i t o t h e r w i s e * /
movq % r c x , % r s i / * F o r e v e r s o u r c e p a g e d o a c o p y * /
andq $ 0 x f f f f f f f f f f f f f00 0 , % r s i
2009-03-10 05:57:16 +03:00
movq % r d i , % r d x
movq % r s i , % r a x
movq % r10 , % r d i
2005-06-26 01:58:02 +04:00
movq $ 5 1 2 , % r c x
rep ; movsq
2009-03-10 05:57:16 +03:00
movq % r a x , % r d i
movq % r d x , % r s i
movq $ 5 1 2 , % r c x
rep ; movsq
2005-06-26 01:58:02 +04:00
2009-03-10 05:57:16 +03:00
movq % r d x , % r d i
movq % r10 , % r s i
movq $ 5 1 2 , % r c x
rep ; movsq
2005-06-26 01:58:02 +04:00
2009-03-10 05:57:16 +03:00
lea P A G E _ S I Z E ( % r a x ) , % r s i
jmp 0 b
3 :
2005-06-26 01:58:02 +04:00
ret
2009-03-10 05:57:16 +03:00
.globl kexec_control_code_size
.set kexec_ c o n t r o l _ c o d e _ s i z e , . - r e l o c a t e _ k e r n e l