レガシーガジェット研究所

気になったことのあれこれ。

Linux Kernel ~ ページング(物理機構) x86編 ~

概要

「詳解Linux Kernel」を参考にVersion 2.6.11のソースコードリーディングをしていく。CPUのアーキテクチャは書籍に沿ってIntelx86とする。 (今回に関してはハードウェアに関連する事項が多いので説明だけとなる)

今回の内容は前回の「ページング」の続きとなっている。ページング機構の中でもハードウェアに強く依存している部分について見ていく。

拡張ページング(Page Size Extension)

Pentium以降のプロセッサでは拡張ページング機構を導入している。ページフレームの大きさを4KBから4MBにする機能である。ページフレームが大きくなることでエントリ数が減り、メモリの節約にもなる。拡張ページングでは32bitのリニアアドレスを以下のように区切る。

  • ページディレクトリのオフセット: 上位10bit
  • ページフレーム内のオフセット: 下位22bit

ページエントリ内のページ長フラグ(PS)が1となる。cr4制御レジスタPSEフラグをセットすることで4KBと4MBのページを混在させることができる。

物理アドレス拡張ページング機構(Physical Address Extension)

Intel386から古い型のPentiumまではアドレスピンが32本しか存在せず最大4GBまでのRAMしか扱えなかった。しかしサーバなどの高いスペックを要するホストはそれ以上のRAMが必要だったため、Intelはアドレスピンを32本から36本まで拡張し最大64GBまでRAMを扱えるようにした。それに伴いLinux Kernelは32bitのリニアアドレスを36bitの物理アドレスに変換するPAE(Physical Address Extension)を導入した。

制御レジスタであるcr4のPAEフラグをセットすることで有効となる。またPAEが有効の場合にページエントリのページ長フラグ(PS)がセットされている場合にはページサイズは2MBとなる。

ハードウェアキャッシュ

CPUとRAMの速度の差異を埋めるためのもので命令やデータを各CPU内のメモリに保存するもの。制御レジスタであるcr0のCDフラグで有効無効が切り替えられる。

局所参照性原理(locality principle)に基づいており、一度参照したアドレス付近は高い確率で再び参照するというものである。キャッシュは"ライン"と言うサブセットに分割され、キャッシュラインは数バイトの連続するバイトを保持できる。キャッシュラインの方式には以下の3種類が存在する。

  • Fully Set Associative(完全連想キャッシュ):

    任意の場所にデータをキャッシュする方式。データを検索する際に全てのキャッシュラインを走査する。

  • Direct Mapped(ダイレクト・マップト):

    アドレスからタグ(キャッシュを一意に認識するIDのようなもの)を算出し、対象のキャッシュラインにデータを保存する。

  • N-way Set Associative(Nウェイセット連想キャッシュ):

    Direct Mappedの場合はあるタグに対して単一のデータを保持したが、当該方式の場合はあるタグに対して"N"個分のデータを保持できる。

キャッシュの書き込み時には以下の2種類のモードがある。切り替え時には制御レジスタであるcr4のNWフラグで切り替えを行う。

  • ライトスルー:

    キャッシュに書き込んだ内容をそのままメモリにも書き込む方式。事実上キャッシュは機能しない状態となる。

  • ライトバック:

    キャッシュラインだけに書き込み、フラッシュ信号が発生した際にのみメモリを更新する。

キャッシュを更新する際には他のCPUが同一のキャッシュを保持している場合があり、その場合他のCPUに更新を知らせることをキャッシュ・スヌーピングと呼ぶ。

キャッシュ管理方式はページフレーム毎に設定でき、ページエントリにはページキャッシュを無効にするPCD(Page Cache Disable)フラグやライトスルー方式を有効にするPWT(Page Write Through)フラグを保持している。Linuxでは両方ともを0にしているため常にページキャッシュが有効で、書き込みの際はライトバック方式が取られている。

x86プロセッサではハードウェアキャッシュを自動的に同期する。よってLinuxカーネルはハードウェアキャッシュのフラッシュ処理を行わないが、キャッシュの同期処理を行わないプロセッサのためのインターフェースは保持している。

アドレス変換バッファ(TLB)

汎用的なハードウェアキャッシュの他にx86ではリニアアドレス変換を高速化する目的で作られたTLB(Translation Lookaside Buffer)と呼ばれるキャッシュを保持している。

特定のリニアアドレスに初めてアクセスする際に行ったページウォークの結果(ページエントリ)をキャッシュし、リニアアドレス変換を高速化する。マルチコアプロセッサでは各CPU毎にローカルなTLBを保持しているが、ハードウェアキャッシュとは異なり基本的に内容を同期する必要はない。なぜなら各プロセッサでは実行しているプロセスのリニアアドレス変換の結果は、同じリニアドレスを用いていても結果は異なるからである。プロセスの切り替えなどで制御レジスタであるcr3(ページディレクトリの物理アドレスを保持)が更新された際には当該ページディレクトリに対応するプロセスのTLBは無効化される。TLBの無効化を省略する場合は以下2通り。

  • 同一のページテーブルを用いている通常プロセス間でプロセスの切り替えが行われた場合。
  • 通常プロセスとカーネルスレッド間でプロセスの切り替えが行われた場合。カーネルスレッドは固有のページテーブルを持っておらず直前に動作していたプロセスのページテーブルをそのまま利用する。

参考文献