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 >
2006-09-26 12:52:38 +04:00
# include < a s m / p a g e . h >
# include < a s m / k e x e c . 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 )
# define P A G E _ A L I G N E D ( 1 < < P A G E _ S H I F T )
# define P A G E _ A T T R 0 x63 / * _ 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 * /
.text
.align PAGE_ALIGNED
2005-06-26 01:58:02 +04:00
.code64
2006-09-26 12:52:38 +04:00
.globl relocate_kernel
relocate_kernel :
/ * % rdi i n d i r e c t i o n _ p a g e
* % rsi p a g e _ l i s t
* % rdx s t a r t a d d r e s s
* /
/* map the control page at its virtual address */
movq $ 0 x00 0 0 f f80 0 0 0 0 0 0 0 0 , % r10 / * m a s k * /
mov $ ( 3 9 - 3 ) , % c l / * b i t s t o s h i f t * /
movq P T R ( V A _ C O N T R O L _ P A G E ) ( % r s i ) , % r11 / * a d d r e s s t o m a p * /
movq % r11 , % r9
andq % r10 , % r9
shrq % c l , % r9
movq P T R ( V A _ P G D ) ( % r s i ) , % r8
addq % r8 , % r9
movq P T R ( P A _ P U D _ 0 ) ( % r s i ) , % r8
orq $ P A G E _ A T T R , % r8
movq % r8 , ( % r9 )
shrq $ 9 , % r10
sub $ 9 , % c l
movq % r11 , % r9
andq % r10 , % r9
shrq % c l , % r9
movq P T R ( V A _ P U D _ 0 ) ( % r s i ) , % r8
addq % r8 , % r9
movq P T R ( P A _ P M D _ 0 ) ( % r s i ) , % r8
orq $ P A G E _ A T T R , % r8
movq % r8 , ( % r9 )
shrq $ 9 , % r10
sub $ 9 , % c l
movq % r11 , % r9
andq % r10 , % r9
shrq % c l , % r9
movq P T R ( V A _ P M D _ 0 ) ( % r s i ) , % r8
addq % r8 , % r9
movq P T R ( P A _ P T E _ 0 ) ( % r s i ) , % r8
orq $ P A G E _ A T T R , % r8
movq % r8 , ( % r9 )
shrq $ 9 , % r10
sub $ 9 , % c l
movq % r11 , % r9
andq % r10 , % r9
shrq % c l , % r9
movq P T R ( V A _ P T E _ 0 ) ( % r s i ) , % r8
addq % r8 , % r9
movq P T R ( P A _ C O N T R O L _ P A G E ) ( % r s i ) , % r8
orq $ P A G E _ A T T R , % r8
movq % r8 , ( % r9 )
/* identity map the control page at its physical address */
movq $ 0 x00 0 0 f f80 0 0 0 0 0 0 0 0 , % r10 / * m a s k * /
mov $ ( 3 9 - 3 ) , % c l / * b i t s t o s h i f t * /
movq P T R ( P A _ C O N T R O L _ P A G E ) ( % r s i ) , % r11 / * a d d r e s s t o m a p * /
movq % r11 , % r9
andq % r10 , % r9
shrq % c l , % r9
movq P T R ( V A _ P G D ) ( % r s i ) , % r8
addq % r8 , % r9
movq P T R ( P A _ P U D _ 1 ) ( % r s i ) , % r8
orq $ P A G E _ A T T R , % r8
movq % r8 , ( % r9 )
shrq $ 9 , % r10
sub $ 9 , % c l
movq % r11 , % r9
andq % r10 , % r9
shrq % c l , % r9
movq P T R ( V A _ P U D _ 1 ) ( % r s i ) , % r8
addq % r8 , % r9
movq P T R ( P A _ P M D _ 1 ) ( % r s i ) , % r8
orq $ P A G E _ A T T R , % r8
movq % r8 , ( % r9 )
shrq $ 9 , % r10
sub $ 9 , % c l
movq % r11 , % r9
andq % r10 , % r9
shrq % c l , % r9
movq P T R ( V A _ P M D _ 1 ) ( % r s i ) , % r8
addq % r8 , % r9
movq P T R ( P A _ P T E _ 1 ) ( % r s i ) , % r8
orq $ P A G E _ A T T R , % r8
movq % r8 , ( % r9 )
shrq $ 9 , % r10
sub $ 9 , % c l
movq % r11 , % r9
andq % r10 , % r9
shrq % c l , % r9
movq P T R ( V A _ P T E _ 1 ) ( % r s i ) , % r8
addq % r8 , % r9
movq P T R ( P A _ C O N T R O L _ P A G E ) ( % r s i ) , % r8
orq $ P A G E _ A T T R , % r8
movq % r8 , ( % r9 )
2005-06-26 01:58:02 +04:00
relocate_new_kernel :
2006-09-26 12:52:38 +04:00
/ * % rdi i n d i r e c t i o n _ p a g e
* % rsi p a g e _ l i s t
2005-06-26 01:58:02 +04:00
* % rdx s t a r t a d d r e s s
* /
/* zero out flags, and disable interrupts */
pushq $ 0
popfq
2006-09-26 12:52:38 +04:00
/* get physical address of control page now */
/* this is impossible after page table switch */
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 */
movq P T R ( P A _ T A B L E _ P A G E ) ( % r s i ) , % r c x
2005-06-26 01:58:02 +04:00
2006-09-26 12:52:38 +04:00
/* switch to new set of page tables */
movq P T R ( P A _ P G D ) ( % r s i ) , % r9
movq % r9 , % c r3
/* setup a new stack at the end of the physical control page */
lea 4 0 9 6 ( % r8 ) , % r s p
/* 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 :
/* store the start address on the stack */
pushq % r d x
2005-06-26 01:58:02 +04:00
/ * Set c r0 t o a k n o w n s t a t e :
* 3 1 1 = = Paging e n a b l e d
* 1 8 0 = = Alignment c h e c k d i s a b l e d
* 1 6 0 = = Write p r o t e c t d i s a b l e d
* 3 0 = = No t a s k s w i t c h
* 2 0 = = Don' t d o F P s o f t w a r e e m u l a t i o n .
* 0 1 = = Proctected m o d e e n a b l e d
* /
movq % c r0 , % r a x
andq $ ~ ( ( 1 < < 1 8 ) | ( 1 < < 1 6 ) | ( 1 < < 3 ) | ( 1 < < 2 ) ) , % r a x
orl $ ( ( 1 < < 3 1 ) | ( 1 < < 0 ) ) , % e a x
movq % r a x , % c r0
/ * Set c r4 t o a k n o w n s t a t e :
* 1 0 0 = = xmm e x c e p t i o n s d i s a b l e d
* 9 0 = = xmm r e g i s t e r s i n s t r u c t i o n s d i s a b l e d
* 8 0 = = performance m o n i t o r i n g c o u n t e r d i s a b l e d
* 7 0 = = page g l o b a l d i s a b l e d
* 6 0 = = machine c h e c k e x c e p t i o n s d i s a b l e d
* 5 1 = = physical a d d r e s s e x t e n s i o n e n a b l e d
* 4 0 = = page s i z e e x t e n s i o n s d i s a b l e d
* 3 0 = = Debug e x t e n s i o n s d i s a b l e d
* 2 0 = = Time s t a m p d i s a b l e ( d i s a b l e d )
* 1 0 = = Protected m o d e v i r t u a l i n t e r r u p t s d i s a b l e d
* 0 0 = = VME d i s a b l e d
* /
movq $ ( ( 1 < < 5 ) ) , % r a x
movq % r a x , % c r4
jmp 1 f
1 :
/ * Switch t o t h e i d e n t i t y m a p p e d p a g e t a b l e s ,
* and f l u s h t h e T L B .
* /
movq % r c x , % c r3
/* Do the copies */
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
movq $ 5 1 2 , % r c x
rep ; movsq
jmp 0 b
3 :
/ * 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 all of the registers to known values */
/* leave %rsp alone */
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