Edited at

CPU のモード

More than 3 years have passed since last update.


概要

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

実際には次のような手続きが必要。


  1. GDT(Global Descriptor Table)の作成

  2. GDT レジスタに登録

  3. IDT(Interrupt Descriptor Table)の作成

  4. IDT レジスタに登録

  5. A20 のマスク解除

  6. 割り込みマスク

  7. CR0 レジスタに最下位 bit をセット

  8. パイプラインの内容をフラッシュ

  9. セグメント・レジスタを設定


protect -> real

Linux ではこのモード移行はない。


IA-32 -> IA-32e

EFER(Extended Feature Enable Register)の LME フラグによって切り替える。

IA-32e のページングは PAE を事前に有効化しておく必要がある。


  1. CR0 の最上位 bit をリセット(ページング無効化)

  2. PAE を有効にする

  3. ページングテーブルをロード

  4. IA32_EFER.LME をセット(IA-32e 有効化)

  5. CR0 の最上位ビットをセット(ページング有効化)

  6. 64bit コードセグメントにジャンプ

ジャンプ先のコードセグメントのフラグ種別に応じて 64bit or Compatible が決定。


IA-32e -> IA-32


  1. CR0 の最上位 bit をリセット(ページング無効化)

  2. ページングテーブルをロード

  3. IA32_EFER.LME をリセット(IA-32e 無効化)

  4. CR0 の最上位 bit をセット(ページング有効化)

  5. 32bit コードセグメントにジャンプ