概要
Linux のブートプロセスに関連する内容について
各モードの概説
real-address mode
メモリ空間:20bit, 1MB(0x00000 - 0xFFFFF)
8086 のアドレスバスが20本のため。
ブートローダは最初 real-address mode で動き途中から protect mode へ切り替える。
protect mode
メモリ空間:32bit, 4GB(0x00000000 - 0xFFFFFFFF)
アクセス保護があり違反すると割り込みを発生させて OS に通知。
virtual 8086 mode
protect mode で動く仮想的な real-address mode。
8086 用のプログラムを real-address mode で動かすと挙動によっては OS に戻ってこれなくなるため用いる。
Linux のブートプロセスでは利用されない。
64bit mode
protect mode のアドレスサイズが 64bit になったもの。
現在の CPU ではアドレスバスが40本しかないのでアドレス空間は下位 40bit しか使われない。
40bit だと 1TB までアドレッシング可能。
EM64T の上限は 52bit なので 1PB まで。
仮想アドレスで扱えるのは下位 48bit で 256TB まで。
Compatibility mode
IA-32e モードのサブモードとして提供される。
virtual 8086 mode のようなもので 64bit OS の上で 32bit アプリのバイナリを動かせるようになる。
32bit 環境でアドレスサイズを拡張する PAE(Physical Address Extention) もサポートされる。
モード移行
real -> protect
モード切り替え自体は CR0 レジスタ最下位 bit で制御する。
1 == protect, 0 == real
実際には次のような手続きが必要。
- GDT(Global Descriptor Table)の作成
- GDT レジスタに登録
- IDT(Interrupt Descriptor Table)の作成
- IDT レジスタに登録
- A20 のマスク解除
- 割り込みマスク
- CR0 レジスタに最下位 bit をセット
- パイプラインの内容をフラッシュ
- セグメント・レジスタを設定
protect -> real
Linux ではこのモード移行はない。
IA-32 -> IA-32e
EFER(Extended Feature Enable Register)の LME フラグによって切り替える。
IA-32e のページングは PAE を事前に有効化しておく必要がある。
- CR0 の最上位 bit をリセット(ページング無効化)
- PAE を有効にする
- ページングテーブルをロード
- IA32_EFER.LME をセット(IA-32e 有効化)
- CR0 の最上位ビットをセット(ページング有効化)
- 64bit コードセグメントにジャンプ
ジャンプ先のコードセグメントのフラグ種別に応じて 64bit or Compatible が決定。
IA-32e -> IA-32
- CR0 の最上位 bit をリセット(ページング無効化)
- ページングテーブルをロード
- IA32_EFER.LME をリセット(IA-32e 無効化)
- CR0 の最上位 bit をセット(ページング有効化)
- 32bit コードセグメントにジャンプ