2011-02-15 05:36:03 +03:00
# include < l i n u x / l i n k a g e . h >
# include < l i n u x / i n i t . h >
# include < a s m / s e g m e n t . h >
# include < a s m / p a g e _ t y p e s . h >
/ *
* The f o l l o w i n g c o d e a n d d a t a r e b o o t s t h e m a c h i n e b y s w i t c h i n g t o r e a l
* mode a n d j u m p i n g t o t h e B I O S r e s e t e n t r y p o i n t , a s i f t h e C P U h a s
* really b e e n r e s e t . T h e p r e v i o u s v e r s i o n a s k e d t h e k e y b o a r d
* controller t o p u l s e t h e C P U r e s e t l i n e , w h i c h i s m o r e t h o r o u g h , b u t
* doesn' t w o r k w i t h a t l e a s t o n e t y p e o f 4 8 6 m o t h e r b o a r d . I t i s e a s y
* to s t o p t h i s c o d e w o r k i n g ; hence the copious comments.
*
* This c o d e i s c a l l e d w i t h t h e r e s t a r t t y p e ( 0 = B I O S , 1 = A P M ) i n % e a x .
* /
2012-05-08 22:22:27 +04:00
.section " .text32 " , " ax"
2011-02-15 05:36:03 +03:00
.code32
2012-05-08 22:22:27 +04:00
.globl machine_real_restart_asm
2011-02-15 05:36:03 +03:00
2012-05-08 22:22:27 +04:00
.balign 16
machine_real_restart_asm :
2011-02-15 05:36:03 +03:00
/* Set up the IDT for real mode. */
2012-05-08 22:22:27 +04:00
lidtl p a _ m a c h i n e _ r e a l _ r e s t a r t _ i d t
2011-02-15 05:36:03 +03:00
/ *
* Set u p a G D T f r o m w h i c h w e c a n l o a d s e g m e n t d e s c r i p t o r s f o r r e a l
* mode. T h e G D T i s n o t u s e d i n r e a l m o d e ; it is just needed here to
* prepare t h e d e s c r i p t o r s .
* /
2012-05-08 22:22:27 +04:00
lgdtl p a _ m a c h i n e _ r e a l _ r e s t a r t _ g d t
2011-02-15 05:36:03 +03:00
/ *
* Load t h e d a t a s e g m e n t r e g i s t e r s w i t h 1 6 - b i t c o m p a t i b l e v a l u e s
* /
movl $ 1 6 , % e c x
movl % e c x , % d s
movl % e c x , % e s
movl % e c x , % f s
movl % e c x , % g s
movl % e c x , % s s
2012-05-08 22:22:27 +04:00
ljmpw $ 8 , $ 1 f
2011-02-15 05:36:03 +03:00
/ *
* This i s 1 6 - b i t p r o t e c t e d m o d e c o d e t o d i s a b l e p a g i n g a n d t h e c a c h e ,
* switch t o r e a l m o d e a n d j u m p t o t h e B I O S r e s e t c o d e .
*
* The i n s t r u c t i o n t h a t s w i t c h e s t o r e a l m o d e b y w r i t i n g t o C R 0 m u s t b e
* followed i m m e d i a t e l y b y a f a r j u m p i n s t r u c t i o n , w h i c h s e t C S t o a
* valid v a l u e f o r r e a l m o d e , a n d f l u s h e s t h e p r e f e t c h q u e u e t o a v o i d
* running i n s t r u c t i o n s t h a t h a v e a l r e a d y b e e n d e c o d e d i n p r o t e c t e d
* mode.
*
* Clears a l l t h e f l a g s e x c e p t E T , e s p e c i a l l y P G ( p a g i n g ) , P E
* ( protected- m o d e e n a b l e ) a n d T S ( t a s k s w i t c h f o r c o p r o c e s s o r s t a t e
* save) . F l u s h e s t h e T L B a f t e r p a g i n g h a s b e e n d i s a b l e d . S e t s C D a n d
* NW, t o d i s a b l e t h e c a c h e o n a 4 8 6 , a n d i n v a l i d a t e s t h e c a c h e . T h i s
* is m o r e l i k e t h e s t a t e o f a 4 8 6 a f t e r r e s e t . I d o n ' t k n o w i f
* something e l s e s h o u l d b e d o n e f o r o t h e r c h i p s .
*
* More c o u l d b e d o n e h e r e t o s e t u p t h e r e g i s t e r s a s i f a C P U r e s e t h a d
* occurred; hopefully real BIOSs don't assume much. This is not the
* actual B I O S e n t r y p o i n t , a n y w a y ( t h a t i s a t 0 x f f f f f f f0 ) .
*
* Most o f t h i s w o r k i s p r o b a b l y e x c e s s i v e , b u t i t i s w h a t i s t e s t e d .
* /
2012-05-08 22:22:27 +04:00
.text
2011-02-15 05:36:03 +03:00
.code16
2012-05-08 22:22:27 +04:00
.balign 16
machine_real_restart_asm16 :
2011-02-15 05:36:03 +03:00
1 :
xorl % e c x , % e c x
2012-05-08 22:22:27 +04:00
movl % c r0 , % e d x
andl $ 0 x00 0 0 0 0 1 1 , % e d x
orl $ 0 x60 0 0 0 0 0 0 , % e d x
movl % e d x , % c r0
2011-02-15 05:36:03 +03:00
movl % e c x , % c r3
movl % c r0 , % e d x
andl $ 0 x60 0 0 0 0 0 0 , % e d x / * I f n o c a c h e b i t s - > n o w b i n v d * /
jz 2 f
wbinvd
2 :
2012-05-08 22:22:27 +04:00
andb $ 0 x10 , % d l
movl % e d x , % c r0
2011-02-15 05:36:03 +03:00
.byte 0xea /* ljmpw */
2012-05-08 22:22:27 +04:00
.word 3f /* Offset */
.word real_mode_seg /* Segment */
2011-02-15 05:36:03 +03:00
2012-05-08 22:22:27 +04:00
3 :
testb $ 0 , % a l
jz b i o s
2011-02-15 05:36:03 +03:00
apm :
movw $ 0 x10 0 0 , % a x
movw % a x , % s s
movw $ 0 x f00 0 , % s p
movw $ 0 x53 0 7 , % a x
movw $ 0 x00 0 1 , % b x
movw $ 0 x00 0 3 , % c x
int $ 0 x15
2012-05-08 22:22:27 +04:00
/* This should never return... */
2011-02-15 05:36:03 +03:00
2012-05-08 22:22:27 +04:00
bios :
ljmpw $ 0 x f00 0 , $ 0 x f f f0
2011-02-15 05:36:03 +03:00
2012-05-08 22:22:27 +04:00
.section " .rodata " , " a"
.globl machine_ r e a l _ r e s t a r t _ i d t , m a c h i n e _ r e a l _ r e s t a r t _ g d t
2011-02-15 05:36:03 +03:00
.balign 16
machine_real_restart_idt :
.word 0xffff /* Length - real mode default value */
.long 0 /* Base - real mode default value */
.balign 16
2012-05-08 22:22:27 +04:00
machine_real_restart_gdt :
/* Self-pointer */
.word 0xffff /* Length - real mode default value */
.long pa_machine_real_restart_gdt
.word 0
/ *
* 1 6 - bit c o d e s e g m e n t p o i n t i n g t o r e a l _ m o d e _ s e g
* Selector v a l u e 8
* /
.word 0xffff /* Limit */
.long 0x9b000000 + pa_ r e a l _ m o d e _ b a s e
.word 0
2011-02-15 05:36:03 +03:00
/ *
* 1 6 - bit d a t a s e g m e n t w i t h t h e s e l e c t o r v a l u e 1 6 = 0 x10 a n d
* base v a l u e 0 x10 0 ; since this is consistent with real mode
* semantics w e d o n ' t h a v e t o r e l o a d t h e s e g m e n t s o n c e C R 0 . P E = 0 .
* /
.quad GDT_ E N T R Y ( 0 x00 9 3 , 0 x10 0 , 0 x f f f f )