x86 の仮想ページに Protection Key が付いた

忙しくて見落としていたのだが 4 月に Intel64 and IA-32 Architectures Software Developer's Manuals が version 054 に改訂されていた。この版には仮想メモリの保護方式に Protection Key 機能が追加された。

x86 はこれまでもページ単位に特権モード(supervisor-mode access)ではアクセス可能だが非特権モード(user-mode access)ではアクセスを禁止するという機能があった。これは x86 のページテーブルエントリの U/S ビットで制御し、このビットが 1 なら user-mode access 可能だが、0 なら supervisor-mode access のみ可能にできるものだった。User-mode か supervisor-mode は CPU の特権レベル(CPL)で決まる。x86 は 0〜3 の 4 段階を用意し、値が低いほど特権レベルが強い。ただし U/S ビットに関しては CPL が 3 なら user-mode access、0〜2 なら supervisor-mode になる。つまり CPL が 4 段階あるのに、ページテーブルエントリには 1 ビットしか用意されていないので実質 2 段階しか効果がない。
x86 以外のアーキテクチャではページテーブルに複数ビット分の特権モードビットがあるものがある。例えば IA-64 の場合、CPU の特権モードは 4 段階だが、ページテーブルエントリに 2 ビットを用意しているので、ページにも 4 段階の区別を設けることができる。ただしこの場合でも、CPU がある特権レベルを持てば、それよりも低い特権レベルのページには全てアクセスが可能になり細かい制御はできない。

仮想メモリのページに対してこれとは別のアプローチをとるものがある。System/370 の Key-controlled protection、PA-RISC 2.0 の Access ID & Protection ID、IA-64 の Protection Key Register などの仕組みである。仮想ページの情報を記録するページテーブルエントリ*1に、レベルではなくキーを設定する。CPUにはアクセス可能なキーを指示するレジスタがあり、両者が一致すればアクセス可能となる。キー長はアーキテクチャによって異なるが、キー長の範囲でページを色分けすることが可能になる。ただし CPU は同時に複数の「色」のページにアクセス可能とするため、CPU 側は複数のキーを持つことが可能になっている場合が多い。

この機能を使うと、同一メモリ空間の異なる属性のメモリ領域に別々のキーを与えることができ、例えばあるスレッドからはアクセス可能だが別のスレッドからはアクセス禁止というメモリ領域を設けることが可能になる。

System/370 IA-64 PA-RISC x86
ページ側のキー長 4ビット(16種類) 24ビット 15ビット(32ビットモード) or 31ビット(64ビットモード) 4ビット(16種類)
CPU側のキー数 1本 最低8本、実装上16本、仕様上はもっと多い 8本 16本全てをコントロール可能
マッチ条件 CPU側とページ側のキーが一致すること。ページ側のキー値0ならCPU側のキーに寄らず合致 存在するCPU側のキーのいずれかに一致すること CPU側のキーのいずれかに一致すること キーに対応するCPUの制御ビットが有効なこと

今回、x86 にも Protection Keys という名前で同種の機能が追加された。キー長は 4 ビットなので 0 〜 15 の 16 種類を採ることができる。

  • x86 の場合、ページテーブルエントリの最上位バイトは XD (execute-disable) ビットだが、続く 4 ビットに protection key を入れる。
  • PKRU(Protection key rights register for user pages)レジスタがアクセス可能なキーを制御する。16 種類しかキーがないので、1つのキーごとに2ビットづつの制御情報を持って 32 ビットの制御レジスタになっている。新設された RDPKRU と WRPKRU 命令で読み込み・変更する。各キーにアクセスを禁止・書き込みを禁止を設定できる。
  • Protection key 違反で #PF 例外が発生した場合、スタック上に積まれるエラーコードの 5 ビット目が PK ビットとなる。Protection-key が原因で #PF 例外が発生した場合、PK ビットが 1 となり protection-key violation であることが判明する。

*1:System/370 の場合は物理ページ単位で storage key に記録される