リニアアドレス→物理アドレスの変換方式

セグメントディスクリプタのリニアアドレスの算出式を疑似コードで表現すると、

QWORD segment_desc
segment_desc := *(QWORD *)((gdtr AND 0xFFFFFFFF0000) + (segment_reg AND 0xFFF8))

上で求めたセグメントディスクリプタの値(segment_desc)から、飛び地で格納されたベース値を連結して、セグメントのベースアドレスのリニアアドレスを求めます。そのベースアドレスにオフセット値を加算して、論理アドレス上の目的のリニアアドレスを算出します。

32bitのリニアアドレスは、上位10bit・中10bit・下位12bitで以下の意味があります。

 31          22 21      12 11         0
+--------------+----------+------------+
| ディレクトリ | テーブル | オフセット |
+--------------+----------+------------+

CR3レジスタと、ページディレクトリ、ページテーブル、オフセット値の組み合わせで、リニアアドレスを段階的に物理アドレスに変換します。

  1. CR3レジスタに、ページディレクトリ(PD)のベースアドレスが格納される。
  2. リニアアドレスの上位10bitが、PD内のエントリのインデックス値を示す。
  3. PDは、4byteのPDE(構造体)を1024個格納した配列。
  4. 2^10=1024であるため、上位10bitで「0〜1023」の数、つまり任意のPDEのインデックス番号が表現可能である。
  5. CR3レジスタの値と、アドレス上位10bit(PDEのインデックス番号)の組み合わせで、任意のPDEを示す。
  6. PDEの下位12bitをマスクすると、ページテーブル(PT)のベースアドレスが取得できる。
  7. PTのベースアドレスと中10bit(PTEのインデックス番号)の組み合わせで、任意のPTEを示す。
  8. PTEの下位12bitをマスクすると、ページフレームのベースアドレスが取得できる。
  9. ページフレームのベースアドレスにオフセット(リニアアドレスの下位12bit)を加算することで、物理アドレスが示される。