OSDN Git Service

442ec0b78de2b4754c7d2b251999519d2788c4c3
[tryos/TryOS.git] / Boot / Source / SwitchMode.S
1 /** @file SwitchMode.S
2  *
3  */
4
5
6 #include "Common.h"
7
8 //セグメント
9 //SEG_REG                       = 0x6000
10 KERNEL_CS                       = 0x0008                        //カーネル用コード・セグメント
11 KERNEL_DS                       = 0x0010                        //カーネル用データ・セグメント
12 BOOT_CS                         = 0x0008                        //ブートローダ用コード・セグメント(カーネル実行時には、このディスクリプタは削除する。)
13
14
15 CR0_PE                  = 0x00000001            //プロテクト・イネーブル・フラグ
16 //CR0_PG                        = 0x80000000            //ページング・フラグ
17
18 .section .text
19 .code16
20
21 /**
22  * プロテクトモード切り替え
23  *
24  * 汎用レジスタは破壊されます。
25  * スタックは初期化されます。
26  * CS は0x08がセットされます。
27  * DS, ES, SS には0x10がセットされます。
28  * FS, GS には、0x00がセットされます。
29  */
30 .global switchProtectMode
31 switchProtectMode:
32
33         xorl    %ebx, %ebx
34         popw    %bx // 戻りアドレス
35
36
37 /*
38        1. 割り込みをディスエーブルにする。CLI 命令によってマスク可能ハードウェア割り込み
39           がディスエーブルになる。NMI 割り込みは、外部回路によってディスエーブルにでき
40           る。 (ソフトウェアは、モード切り替えの動作中に例外または割り込みが発生しないよ
41           うに保証する必要がある。     )
42 */
43         // NMI割り込み禁止
44         call    disableNMI
45
46
47
48 /*
49        2. LGDT 命令を実行して、GDTR レジスタに GDT のベースアドレスをロードする。
50 */
51         // GDT読み込み
52         lgdt    tempGDTR
53
54
55 /*
56        3. 制御レジスタ CR0 の PE フラグ(またオプションで PG フラグ)を設定する MOV CR0
57           命令を実行する。
58 */
59
60         // プロテクトモード移行
61         movl    %cr0, %eax
62         orl             $CR0_PE, %eax
63         movl    %eax, %cr0
64
65
66 /*
67        4. MOV CR0 命令のすぐ後で、far JMP 命令または far CALL 命令を実行する。    (この操作
68           は通常、命令ストリーム内の次の命令への far ジャンプまたは far コールになる。          )
69 */
70         // パイプラインフラッシュ
71         jmp             pipelineFlush
72 pipelineFlush:
73
74 /*
75        5. MOV CR0 命令の直後に JMP 命令または CALL 命令を実行すると、実行の流れが変化
76           し、プロセッサが順次処理される。
77 */
78         // 32bit移行
79 .code32
80         .byte   0x66
81         ljmp    $0x08, $setCodeSegment
82 setCodeSegment:
83
84
85 /*
86        6. ページングがイネーブルな場合、      MOV CR0 命令のコードと、    JMP 命令または CALL 命
87           令のコードは、アイデンティティ・マッピングされたページから得たものでなければ
88           ならない(つまり、ジャンプ前のリニアアドレスが、ページングと保護モードがイネー
89           ブルになった後の物理アドレスと同一でなければならない) JMP 命令または CALL 命
90                                                   。
91           令のターゲット命令は、アイデンティティ・マッピングされる必要はない。
92 */
93
94
95 /*
96        7. ローカル ディスクリプタ テーブルを使用する場合には、           LLDT 命令を実行して LDTR
97                 ・         ・
98           レジスタに LDT のセグメント・セレクタをロードする。
99 */
100
101
102 /*
103        8. LTR 命令を実行して、  セグメント・セレクタ付きタスクレジスタを初期保護モード・タ
104           スクへロードする。またはタスクスイッチに関する TSS 情報を保存できるメモリの書
105           き込み可能領域へロードする。
106 */
107
108
109 /*
110        9. 保護モードに移行した後、セグメント・レジスタは実アドレスモードで保持していた
111           内容をそのまま保持し続ける。操作手順 4 の JMP 命令または CALL 命令が CS レジス
112               タをリセットする。以下のどれかを実行して、残りのセグメント・レジスタの内容を
113               更新する。
114               - DS、SS、ES、FS、GS の各セグメント・レジスタを再ロードする。ES、FS、GS の
115                  各レジスタのなかで使用しないものがある場合、そのレジスタにヌルセレクタを
116                  ロードする。
117               - JMP 命令または CALL 命令を新しいタスクに対して実行する。これによって、セグ
118                  メント・レジスタの値がリセットされ、新しいコード・セグメントに分岐する。
119 */
120
121         // データ・セグメント初期化
122         movw    $0x10, %ax
123         movw    %ax, %ds
124         movw    %ax, %es
125         movw    %ax, %ss
126         // FS, GS は使わない。
127         xorl    %eax, %eax
128         movw    %ax, %fs
129         movw    %ax, %gs
130
131
132 /*
133           10. LIDT 命令を実行して、IDTR レジスタに保護モード IDT のアドレスとリミットをロー
134               ドする。
135 */
136
137
138 /*
139           11. STI 命令を実行して、マスク可能ハードウェア割り込みをイネーブルにし、また必要な
140               ハードウェア動作を実行して NMI 割り込みをイネーブルにする。
141           上記の手順 3 と手順 4 の間に他の命令が存在すると、不規則な障害が発生することが
142           ある。システム管理モードで、メモリを参照する命令が手順 3 と手順 4 の間に挿入さ
143           れたときのような状況では、障害は直ちに認識される。
144 */
145         // NMI割り込み許可
146         call    enableNMI
147
148
149
150         // 呼び出し元に戻る
151         pushl   %ebx
152         ret
153