Intelが発表したX86S Revision 1.1について(1/2) – 詳細編

はじめに

先日、IntelがX86-64(Intel 64 / AMD 64)を現代に合わせて変更(モダン化)した仕様「X86-S(X86S)」を提案する内容のドキュメントを発表しました。本サイトにおいても以下のメモで取り上げました:

これについて新たにIntelが内容を更新したRevision 1.1を公開しました。初期に公開されたRevision 1.0とは異なる部分が多数あり、より明確にX86Sというものを描き出しています。その内容について、前回と同様に「さかきけい」の理解で日本語化をしてみたものを本メモ「詳細編」として公開したいと思います。前回の提案から追加されたもののもあれば、変更されたもの、あるいは削減されたものもあります。

そして、私の所感については別のメモ「分析編」としてお届けしたいと思います。というわけで、今回は2回の連載となる予定です。なお、「概要編」に相当する部分については今回ほぼ更新されていませんので割愛します。

お願い

もしもIntelの関係者で、私がこの日本語ドキュメントを公開することが何らかのライセンスや法的問題があるとお考えであるならば、メールにてご連絡をいただければと思います。その際は、私がメールの送付主がIntel関係者であることを認識できるようにIntel社内からメールを送信し、所属・肩書き等を添えてください。

英語版の資料をベースにしているこの日本語ドキュメントはIntelの著作権が及ぶ範囲内にあります。その上で、この日本語ドキュメントには“さかきけい”の著作権が発生しています。“さかきけい”はすべての著作権法上の権利を留保します(詳しくは「ご利用上の注意とお願い」を参照ください)。

免責の表明

この日本語ドキュメントはIntel Corporationが公開している「X86S ISA External Architectural Specification」に記載されている情報を元に、“さかきけい”の理解で作成したものです。このためIntel Corporationには何らこの日本語ドキュメントに対する責任はありませんので、この日本語ドキュメントに関連する問い合わせをIntel Corporationに対して行うことを禁止します。

また、この日本語ドキュメントを作成した“さかきけい”も何ら責任を負いません。この日本語ドキュメントの内容は、利用者自身の責任においてのみ使用することができます。

使用上の注意

  • Intelによる法的な意味合いを持つと考えられる記述は英文のままとしています。これは、日本語にすることで意味合いが変化することを防ぐ目的のものです。しかし、その部分は英語原文に付属する部分であることを前提としなければなりません。したがって、本日本語ドキュメントではなく、文脈としては原書に付属することになります。本日本語ドキュメントにおいては、Intelが免責を宣言する部分はその通りですが、何らかの権利や許可を与える部分についてはすべて無効であるとご理解ください。※1今回は前回に引き続いて提案書であるということを鑑み、日本語参考訳を付記していますが、状況としては前述のとおりです。
  • 複数の英単語によって構成される語は、単語間に「・」を入れて表現しています。例:ルート・ファイル・システム※2
  • 原則として単語末の長音記号「ー」は省略しない方針で編集しています。例:プロセッサー※3
  • 気づいたTypoや編集ミスなどは明確であると考えられる場合に若干修正しています。
  • 日本語での記述におかしいと思われる個所がある場合には原書をあたってください。
  • 技術的などの理由で記載内容にわからない事項がある場合には別途調べてください(“さかきけい”に質問のメールを送るのはご遠慮ください※4)。
  • 明らかな誤訳がある場合には具体的なご指摘をメールまたはコメントでお知らせいただけると助かります。
  • 記述内容に誤りがある場合にもお知らせいただけると嬉しく思います。ただし、原書も間違っている場合には特に日本語ドキュメントを修正することはせずに、訳注を追加するだけとするかもしれません。
  • 前述の内容と被りますが、“さかきけい”は何ら責任や義務を負うものではありません。

文書についてのご指摘をいただける方へのお願い

  • なるべく平坦でかつ理解しやすい程度に周辺情報を含む、日本語でのご指摘をお願いします。
  • “さかきけい”の主観において、いただいた情報の適用を行わないことがあることをあらかじめご理解ください。

X86S
外部設計仕様書

Rev. 1.1
2023年11月
ドキュメント番号: 351407-001

Notice: This document contains information on products in the design phase of development. The information here is subject to change without notice. Do not finalize a design with this information.

Intel technologies may require enabled hardware, software or service activation.

No computer system can be absolutely secure. Intel does not assume any liability for lost or stolen data or systems or any damages resulting from such losses.

Your costs and results may vary.

You may not use or facilitate the use of this document in connection with any infringement or other legal analysis concerning Intel products described herein. You agree to grant Intel a non-exclusive, royalty-free license to any patent claim thereafter drafted which includes subject matter disclosed herein.

No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document.

All product plans and roadmaps are subject to change without notice.

The products described may contain design defects or errors known as errata which may cause the product to deviate from published specifications. Current characterized errata are available on request.

Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade.

Copies of documents which have an order number and are referenced in this document may be obtained by calling 1-800-548-4725 or by visiting www.intel.com/design/literature.htm.

Copyright © 2023, Intel Corporation. Intel, the Intel logo, and other Intel marks are trademarks of Intel Corporation or its subsidiaries. Other names and brands may be claimed as the property of others.

告知:このドキュメントには開発・設計フェーズの製品に関する情報が含まれています。この情報は予告なしで変更されることがあります。この情報で設計を確定させないでください。

Intelの技術は、有効にするためのハードウェア、ソフトウェア、またはサービス・アクティベーションが必要となることがあります。

どのようなコンピューター・システムも絶対的にセキュアであるはずがありません。Intelはそのような損失から生じる喪失、またはデータまたはシステムの略取またはその他の損害に対して一切の責任を負いません。

あなたの費用と結果は釣り合わないことがあります。

あなたは、ここで説明されるIntel製品に関して、どのような侵害あるいは他の法的分析を目的として、本ドキュメントの使用または援用をすることはできません。あなたは、ここで明らかにされた内容を含む、その後に作成されたどのような特許請求の範囲に対しても、非排他的で、ロイヤルティーの発生しないライセンスをIntelに与えることに同意します。

全ての知的所有権への(禁反言またはそれ以外、明示または暗示による)ライセンスが、このドキュメントによって与えられることはありません。

すべての製品計画およびロードマップは、告知なく変更されることがあります。

説明した製品には、発表された仕様から逸脱するエラッタとして知られている設計上の欠陥あるいはエラーを含むことがあります。現状の判明済みエラッタについては(その内容を)請求することができます。

無制限な市場向けの暗黙的な保証、特定目的への適合性、および非侵害性を含む、履行の過程、取引の過程、または貿易における取り扱いから生じる、すべての保証と同様に、Intelはすべての明示的および暗黙的な保証を放棄します。

注文番号および本ドキュメントから参照されるドキュメントのコピーは、電話番号1-800-548-4725またはwww.intel.com/design/literature.htmから入手できるものがあります。

Copyright © 2023, Intel Corporation.
Intel、Intelロゴ、および他のIntelマークはIntel Corporationまたはその子会社の商標です。他の名称とブランドは他のものの所有権が設定されていることがあります。

目次

図の一覧

表の一覧

1 このドキュメントについて

1.1 対象とする読者

このドキュメントはX86S ISA用のソフトウェア開発のためを意図しています。

フィードバックは電子メールでx86s_feedback@intel.comまでお送りください※5

1.2 文書の更新履歴

本ドキュメントの改定履歴

改定番号 改定詳細 改定日付
1.0 初期リリース 2023年4月
1.1 名称をX86Sに変更した。
SMXのセクションを追加した。
限定的なセグメンテーションのための状態とチェックを簡素化した。
VMEntryとVMExitに関する詳細を追加した。
CPUIDとMSR番号を追加した。
ERETUはフォールバックしない。
FITへの参照をするinitとresetの記述を削除した。
疑似コードとそれに関する説明文に対する様々な修正を行った。
5レベルの(ページ)スイッチを削除した。
64ビットのSIPIとINITの説明を整理した。
アドレス・サイズ・オーバーライドの振る舞いを明確にした。
いくつかのRPLのチェックを再度加えた。
ディスクリプター型のための表を追加した。
IA32_SIPI_ENTRY_STRUCT_PTRの定義を修正した。
様々な内容の明確化を行った。
2023年11月

2 はじめに

X86Sは過去の時代の実行モードとオペレーティング・システム用ISAを取り除いた「レガシーを削減したOS用のISA(legacy-reduced-OS ISA)」です。

X86S ISAの存在は将来のCPUIDフィールドにおけるメインCPUID機能ビットの1つ、CPUID 7.1.ECX[2]のLEGACY_REDUCED_OS_ISAによって示されます。このビットは本ドキュメントで説明しているすべてのISAの削除を意味します。新たに、個別の64ビットの“スタートアップ”プロセッサー間割り込み(SIPI : Start-up Inter-Processorr Interrupt)用のCPUID機能ビットが設けられます。

X86S ISAによる変更点は以下の通りです:

  • CPUは常にページ化モードであるように制限する。
  • 32ビットのリング0および仮想86モードを削除する。
  • リング1とリング2を削除する。
  • 16ビットのリアル・モードおよびプロテクト・モードを削除する。
  • 16ビットのアドレッシングを削除する。
  • 固定MTRRを削除する。
  • ユーザーレベル入出力およびストリング入出力を削除する。
  • CR0ライトスルー・モードを削除する。
  • CR0のレガシーFPU制御ビットを削除する。
  • リング3の割り込みフラグ制御を削除する。
  • CRアクセス命令を削除する。
  • INIT/SIPIを再設計する。
  • XAPICを削除し、X2APICのみをサポートする。
  • APICから8259のサポートを削除する。
  • EFER MSR内のNXまたはSYSCALLまたはロング・モードの無効化を削除する。
  • #SSおよび#NP例外を削除する。
  • 以下の条件でセグメンテーション設計のサブセットをサポートする:
    • IDTイベント・デリバリーをFREDによる制限が実装された形でサブセットに制限する。
    • 32ビットのコンパチビリティー・モードに64ビットのセグメンテーションが適用される:
      • FS、GSのbaseのみ。
      • GDT、IDT、LDT、およびTSSのbaseとlimit。
      • (64ビットと同様に)32ビット・モードにおけるコードとデータのフェッチにlimitが存在しない。
    • すべてのモードにおいて、CS、DS、ES、FS、およびGSにおけるデータまたはコードのフェッチについて、アクセス権または使用不可能なセレクターの検査をしない。
    • far call、far return、far jump、およびIRETのサポートを制限する(FREDのように)。
    • IRETにできるのは現在のリングにとどまるか、リング0からリング3への変更のみである。
    • 制限されたセグメンテーション状態で動作する。VMX entry/exitにおけるロードおよびストアについてサブセットの状態に制限する。
    • ディスクリプターのロードにおけるチェックを簡略化する。
    • ディスクリプターのアクセス・ビットは設定しない。
    • TSSディスクリプターのBusyビットは使用せず、またチェックをしない。

3 設計変更

3.1 32ビットのリング0を削除

32ビットのリング0は今後サポートせず、(32ビットのリング0に)入ることはできません。

3.2 リング1およびリング2の削除

リング1およびリング2は今後サポートせず、(リング1とリング2に)入ることはできません。

3.3 16ビットおよび32ビットのプロテクト・モードの削除

16ビットおよび32ビットのプロテクト・モードは今後サポートせず、(それぞれのモードに)入ることはできません。CPUは常にロング・モードで動作します。32ビット・サブモードはIntel64(コンパチビリティー・モード)として依然存在しています。CS.L==0およびCS.D==0となっているディスクリプターをCSにロードする試みは#GP(sel)例外を生成します。

3.4 16ビットのアドレッシングおよびアドレス・サイズを示すオーバーライドの削除

32ビット・コンパチビリティー・モードにおいて、マスクされていないメモリー参照を伴う16ビットのアドレス・サイズ・オーバーライド・プリフィクス(0x67)は#GP(0)例外のトリガーとなります。#GP例外は他のメモリー関連の例外に対して優先します。ジャンプは以下で明示する異なった規則を適用します。

かつてのジャンプ命令によってRIPが16ビットへと切り取られる(キャストされる)場合(Jump Short 0x7*、Jump Near 0x0f 8*、 LOOP 0xE0-2、JECZ 0xE3、JMP near 0xE9および0xEB、CALL 相対 0xE8、JMP near 0xFF/4、 CALL 間接 near 0xff/2、RET near 0xC2-3、JMP far 0xEAおよび0xFF/5、CALL 間接 far 0xFF/3、CALL far 0x9A、RET far 0xCA-B)には#UD例外となります。

0x67をプリフィクスに持つジャンプ命令によって16ビット(CALL 相対 near mem 0xff/2 mem、JMP far 0xeaおよび0xff /5、CALL 相対 far 0xff /3)へと切り取られる(キャストされる)場合には#GP(0)となります。

LEAまたNOPのようなメモリーの変更またはジャンプを行わない操作は非フォルトの存在であることに注意が必要です。

コンパチビリティー・モードにおいて、SS.B==0 (16ビット・データ・セグメント)の設定されたディスクリプターを持つSSからロードする試みは#GP(0)例外を生成します。

3.5 CPUID

CPUID 7.1.ECX[2]によって示されるLEGACY_REDUCED_OS_ISA機能ビットは本ドキュメントが解説するすべてのISAを削除することを示すCPUIDです。

CPUID.7.1.ECX[4]によるSIPI64は64ビットのSIPIをサポートすることを意味します。また、LEGACY_REDUCED_OS_ISAを示すプロセッサーはSIPI64を示します。

3.6 制限されたサブセットのセグメンテーション

X86Sはセグメンテーションのサブセットをサポートします:

  • GDT/LDTにおいてゲートをサポートしない; サポートはデータ・セグメント、コード・セグメント、LDT、および(GDT内における)TSSに限定して行う。
  • baseについてはFS、GS、GDT、IDT、LDT、およびTSSレジスターのためにサポートされる; 32ビット・モードのためのCS、DS、ES、およびSSのbaseは64ビット・モードと同様に無効(ゼロとして扱われる)となる。プロセッサーはCS、DS、ES、SSのbaseは保存しない。これらはVMENTRY/VMEXITあるいはSMI/RSMで保存されず、また復元されない。
  • limitのサポートはGDT、IDT、LDT、およびTSSに対してのみ行われる; CS、DS、ES、FS、GS、およびSSのためのlimitは無制限として扱われる。プロセッサーはCS、DS、ES、FS、GS、SSの状態は保存しない。
  • limitフィールドはVMENTRY/VMEXITあるいはSMI/RSMで保存されず、また復元されない。

    CSとSSはアクセス権が設定できるディスクリプターである。これらに関し、CS.L、SS.B、およびSS.DPLフィールドが実行時において存在している。しかしながら、他のいくつかのビットは最初にディスクリプターへのロード時にチェックすることができる。他のすべてのディスクリプターのアクセス権は、VMENTRY/VMEXITあるいはSMI/RSMにおいて保存を行わず、また復元を行わない。常にコアのCPLはSS.DPLとなる。アクセス権は型とDPLをチェックし、limit(適切であるなら)とD(適切であるなら)を作成するためにディスクリプターのロード時にチェックを行う。

  • 下方伸長、コンフォーミング、および使用不可能なセグメントはサポートしない – これらは根本的に無視されて基本型へ戻される。これまでコンフォーミング・コード・セグメントとして解釈されていたものはコード・セグメントとして扱われる。データおよびコード・セグメントは常に読み出し可能で書き込み可能となる。
  • descriptor.DPLフィールドおよびselector.RPLは0または3でなければならない; そしてセレクターのRPLはDPLと一致しなければならない(データ・セグメントまたは例外のエントリーを除く)。
  • ロード/ストアにおいて、R/W権限とNULLは無視される。
  • IRETはリング0から3に切り替えるか、現在のリングにとどまることはできるが、タスク・スイッチを引き起こすことはできず、仮想8086モードに入ることはできない。
  • LAR命令を通してアクセス済みと設定されているように見える以外には、ディスクリプターのアクセス済みビットはメモリーにセットされない。
  • TSSのBusyビットはサポートされない。これは、メモリーに対してLTRで設定されることもなく、VMENTRYでチェックすることもない。
  • #SS例外は削除され、代わりに#GPを通知する。
  • #NP例外は削除され、代わりに#GPを通知する。
  • LMSW命令は削除され、#UD例外を通知する。

表1に示している3つのオペレーティング・モードをサポートします。

表1. サポートするオペレーティング・モード

  CPL=0 CPL=3
LMA=1 CS.L=0 サポートしない リング3のコンパチビリティー・モード
LMA=1 CS.L=1 リング0の64ビット・モード リング3の64ビット・モード

3.7 新しいセグメント・レジスターへのロード時チェック

VM Entry/Exit以外の手順において、セグメント・レジスターをロードする際には以下の条件でチェックを行います:

  • CSおよびSS.DPLは0または3であること。
  • 一般にDPLはCS/SSのためのCPLと等しくなければならない。例外は、IRETおよびERETUによってスタックから呼び出されるCSディスクリプターである。SS以外のデータ・セグメントに対するDPLは無視する。
  • コード・ディスクリプターはコード型であり、すべてのリングにおいて16ビットではなく、またはDPL=0の32ビットであってはならない。。
  • システム型とデータ・ディスクリプターについては必ずしも一致しない。

これらの条件が満たされなければ、#GP(sel)例外を通知します。システム・セグメント以外においてlimitとbaseは無視します。

第4章で変更後の命令の疑似コードを見ることができます。

3.7.1 コードとデータのセグメントの型

コードおよびデータ・セグメントの内容を解説する図です。[

コードおよびデータ・セグメントのディスクリプターにおいて無視するビットが[10.8]に存在します。現状では2つの型があります。データ・セグメントおよびコード・セグメントにおける、それぞれ8つのエンコードです。コード・セグメントは実行可能で、データとコードのセグメントの両方が読み書きが可能です。

Typeフィールド 11 10 9 8 タイプ ロード時の振る舞い 使用時の振る舞い
0 0 0 0 0 データ データのロード用 読み出し / 書き込み
1 0 0 0 1 データ データのロード用 読み出し / 書き込み
2 0 0 1 0 データ データのロード用 読み出し / 書き込み
3 0 0 1 1 データ データのロード用 読み出し / 書き込み
4 0 1 0 0 データ データのロード用 読み出し / 書き込み
5 0 1 0 1 データ データのロード用 読み出し / 書き込み
6 0 1 1 0 データ データのロード用 読み出し / 書き込み
7 0 1 1 1 データ データのロード用 読み出し / 書き込み
8 1 0 0 0 コード コードとデータのロード用 実行 / 読み出し / 書き込み
9 1 0 0 1 コード コードとデータのロード用 実行 / 読み出し / 書き込み
10 1 0 1 0 コード コードとデータのロード用 実行 / 読み出し / 書き込み
11 1 0 1 1 コード コードとデータのロード用 実行 / 読み出し / 書き込み
12 1 1 0 0 コード コードとデータのロード用 実行 / 読み出し / 書き込み
13 1 1 0 1 コード コードとデータのロード用 実行 / 読み出し / 書き込み
14 1 1 1 0 コード コードとデータのロード<用/th>

実行 / 読み出し / 書き込み
15 1 1 1 1 コード コードとデータのロード用 実行 / 読み出し / 書き込み

3.7.2 システム・セグメント・タイプ(S=1)

64ビットTSSにおけるBit[9] (BUSY)を無視します。X86SはBUSYとそうではないTSSを使用可能かの判定において区別しません。両者のエンコードは同じ方法で取り扱います。

64ビットのコール・ゲートは削除されました。

現在、このグループには以下に示す4つのタイプがあります: LDT、インタラプト・ゲート、トラップ・ゲート(1つのエンコード化されたもの)、およびTSS(2つのエンコード化されたもの)。

Typeフィールド 内容 CR4.FRED=0 CR4.FRED=1
0 予約済み #GP #GP
1 16ビットTSS #GP #GP
2 LDT LLDTによるロードまたは#GP LLDTによるロードまたは#GP
3 Busy状態の16ビットTSS #GP #GP
4 16ビット・コール・ゲート #GP #GP
5 タスク・ゲート #GP #GP
6 16ビット割り込みゲート #GP #GP
7 16ビット・トラップ・ゲート #GP #GP
8 予約済み #GP #GP
9 使用可能なTSS LTRによるロードまたは#GP LTRによるロードまたは#GP
10 予約済み #GP #GP
11 Busy状態の32ビットTSS LTRによるロードまたは#GP LTRによるロードまたは#GP
12 32ビット・コール・ゲート #GP #GP
13 予約済み #GP #GP
14 割り込みゲート IDTにおけるフォローあるいは#GP #GP
15 トラップ・ゲート IDTにおけるフォローあるいは#GP #GP

3.8 #SSおよび#NP例外の削除

全ての失敗するスタック・セグメントの参照、明示的および暗黙的の両方において、今後は#SS例外を引き起こすことはありません。代わりに、#GP例外を生成します。全てのディスクリプターのロード時にdesc.P==0である場合には、(今後は#NP例外ではなく)#GP(sel)例外を生成します。

3.9 固定されたモードのビット

CPUは常にIntel 64の64ビット・サブモードで動作します。リアル・モード、プロテクト・モード、または仮想86モードを有効にすることはできません。

3.9.1 固定されたCR0のビット

CR0レジスターのすべてのビットを図1に示します。この図のTS、WP、AM、およびCDビット以外は固定されます。ETは1に固定されていますが、入力時に無視されます。不適切な値を固定ビットに設定すると#GP(0)例外を生成しますが、CR0 exitingが構成されたVM exitが引き起こされた後に限られます。CR0 exitingからのVM exitによる変更が行われていない場合には、読み出しは常に可変ビットの現行値と固定ビットに基づく値を返します。

CR0レジスターの内容について説明する表です。

CR0ビット 固定値 ビット 意味内容
PE 1 0 保護有効: 常にプロテクト・モードとなる。
MP 1 1 コプロセッサーの監視: 常に有効となる。
EM 0 2 FPエミュレーション。
TS 3 タスク・スイッチ。FPU無効。このビットは依然として可変である。
ET 1 4 拡張タイプ(入力は無視される)。※6
NE 1 5 数値演算エラー。
WP 16 書き込み禁止ページ・テーブル。このビットは依然として可変である。
AM 18 RFLAGS.ACによるアライメント・チェックが有効となる。このビットは依然として可変である。
NW 0 29 キャッシュ・ライト・スルーは常に無効である。
CD 30 キャッシュ無効。このビットは依然として可変である。
PG 1 31 ページングは常に有効である。

図1. CR0レジスター

3.9.2 固定されたCR4ビット

図2に示すCR4レジスター内の固定ビットは以下の通りです。これらのために、いかなる他の値(VMEの任意の値を除く)を書き込むと、CR4 exitingからのVM-exitという結果でなければ#GP(0)例外が生成されます。

CR4レジスターの内容について説明する図です。

CR4ビット 固定値 ビット 意味内容
PVI 0 1 プロテクト・モード仮想割り込みをサポートしない。
PAE 1 5 8バイトPTE。常に64ビット・モードが有効となる。

図2. CR4レジスター

3.9.3 固定されたEFERビット

表2にEFER MSR内の固定されたビットのリストを示します。他の値をEFERに書き込むと#GP例外を生成しますが、LMAは対象外で無視されます。

表2. 固定されたEFERビット

EFERビット 固定値 ビット 意味内容
SCE 1 0 SYSCALLは常に有効となる。
LME 1 8 常にロング・モードとなる。
LMA 1 10 常にロング・モード、しかし変更は無視される。
NXE 1 11 ページ・テーブルにあるNXビットは常に有効となる。

3.9.4 削除されたRFLAGS

図3にRFLAGSレジスターのビットを示します。IOPL、VM、VIF、およびVIPビットは常にゼロです。表3の規則が適用されます。

図3. RFLAGSレジスター

RFLAGSレジスターの内容について説明する図です。

表3. 旧式のRFLAGSの振る舞い

操作 newIOPL != 0における操作 newVIF != 0またはnewVIP != 0における操作 newVM!=0における操作
POPF CPL3 無視 無視 無視
POPF CPL0 無視 無視 無視
SYSRET #GP(0) #GP(0) N/A (常にクリアされている)
IRET CPL3→CPL3 無視 無視 無視
IRET CPL0 #GP(0) #GP(0) 無視
ERETU #GP(0) #GP(0) #GP(0)
ERETS #GP(0) #GP(0) #GP(0)
VMEntry 不正なゲスト状態エラー 不正なゲスト状態エラー 不正なゲスト状態エラー
SEAMRET 不正なゲスト状態エラー 不正なゲスト状態エラー 不正なゲスト状態エラー
RSM 強制的に0 強制的に0 強制的に0

3.9.5 ステータス・レジスター命令の削除

LMSW命令は削除され、#UDフォルトを引き起こします。

3.9.6 リング3 入出力ポート命令の削除

(もうこれ以上)ユーザー・モードにおける入出力ポートへのアクセスの構想はありません、そしてリング3でINB/INW/INL/INQ/OUTB/OUTW/OUTL/OUTQを使用すると常に#GP(0)例外につながります。#GPチェックはVM実行チェックまたは入出力許可ビットマップのチェックの前に行われます。これは入出力許可ビットマップからのロードを全く行わないということを含意します。

3.9.7 ストリング入出力命令の削除

INS/OUTSはサポート外となり、#UD例外を引き起こします。この対象にはINS/OUTS命令のREPありを含みます。

3.10 64ビットSIPI

64ビットSIPIはアーキテクチュラル・パッケージ・スコープIA32_SIPI_ENTRY_STRUCT_PTR MSRを定義し、これにはメモリー上のエントリー構造体へのフィジカル・ポインターが含まれます。ページ化64ビット・モードにおけるアプリケーション・プロセッサーが起動するために構造体は定義されます。

64ビットSIPIのトリガーとなるように、メモリー上のエントリー構造体の機能フィールドのようにIA32_SIPI_ENTRY_STRUCT_PTR MSRの有効ビットをセットし、そしてX2APIC ICRレジスターを使用することでSIPIをトリガーします。

レガシーSIPIはサポートしません。

64ビットSIPIの存在はCPUID.7.1.ECX[4] SIPI64 CPUID機能ビットにより通知されます。

3.10.1 IA32_SIPI_ENTRY_STRUCT_PTR

表4に示すIA32_SIPI_ENTRY_STRUCT_PTR (0x3C)パッケージ・スコープMSRを表4に示します。これはSIPIメッセージを受け取った後のターゲットCPUの実行コンテキストを定義します。これはメモリー上のエントリー構造体をポイントしています。

BIOS_DONE MSRビットをセットした後のMSRは読み出し専用です。

表4. IA32_SIPI_ENTRY_STRUCT_PTR MSR(アドレス 0x3c)

ビット フィールド 属性 初期値 内容説明
63:MAXPA 予約 NA 0
MAXPA-1:12 SIPI_ENTRY_STRUCT_PTR RW 0 SIPI_ENTRY_STRUCTへのフィジカル・ポインター
11:1 予約 NA 0
0 ENABLED RW 0 64ビットSIPI有効

INITの後に、ERETS/ERETU/IRETによって明示的にブロックが解除されるまでNMIはブロックされます。

SIPIを受け取ると、ターゲットCPUはエントリー構造体からレジスター状態をロードして、指定されたRIPから実行を開始します。INITメッセージからのベクターをR10で受け付けます。INIT IPIメッセージのベクター・フィールドによって提供されたベクターは無視します。

3.10.2 SIPI_ENTRY_STRUCTの定義

表5に示すエントリー構造体メモリー・テーブルは、SIPIを受け取ったCPUの実行コンテキストを定義します。

表5. SIPI_ENTRY_STRUCT メモリー内の構造体

オフセット
(ビット)
サイズ
(ビット)
名称 内容説明
0 8 FEATURES Bit 0 – 有効ビット (0 – シャットダウン)。その他のビットは予約。
8 8 RIP SIPIの後に実行する新しい命令ポインター。新しいCR4における有効値。
16 8 CR3 新しいCR3の値。新しいCR4.PCIDEと整合し、予約ビットはセットしてはならない。
24 8 CR0 新しいCR0の値。変更不可ビットは固定値と一致していなければらなず、そしてどのような予約ビットもセットしてはならない。
32 8 CR4 新しいCR4の値。変更不可ビットは固定値と一致していなければならない。新しいCR3、新しいRIP、新しいCR0と整合していなければならず、そして予約ビットはセットしてはならない。

SIPI_ENTRY_STRUCTにおけるどのような整合性検査の失敗も、ターゲットCPUにおけるシャットダウンにつながります。

3.10.3 非ブロック状態でINITを受け取った場合における疑似コード

IF ゲスト・モード中 THEN
    トリガーを抜ける
FI
RFLAGS = 2 # RFLAGS内の変更可能ビットをすべてクリアする
CR0のPE=1, MP=1, ET=1, NE=1, NW=0, PG=1に設定しCR0.CDを保護する
CR4のPAE=1に設定する
CR3をクリアする
CR2をクリアする
CSのSelector = 0とし、 CS.L = 1とする
SS, DS, ESのSelector = 0とする
FS, GSのSelector = 0とし、Base = 0とする
GDTR/IDTRにBase = 0, Limit = 0xffffをセットする
LDTR, TRにSelector = 0, Base = 0, Limit = 0xffffをセットする
FS/GS BASE MSRに0をセットする
EFERのLMA=1, LME=1, NX=1, SC=1をセットする // Intel64においてのみ関連する
RDXに0x000n06xxxに(nは拡張モデル値、xはステッピング番号)をセットする
全ての汎用レジスターをクリアする
DR0/DR1/DR2/DR3をクリアする
DR6に0xffff0ff0をセットする
DR7に0x400をセットする
x87 FPU 制御ワード0x37fをセットする
x87 FPU ステータス・ワードに0をセットする
x87 FPU タグ・ワードに0xffffをセットする
全てのTLBをフラッシュする
IF IA32_APICBASE.BSP = 1 THEN
    リセットのように64ビットSupervisorモードを強制する
    リセットからのCR3/RIP値を使用して64ビットのリセット・ベクターを実行する
ELSE
    SIPI状態待ちに入る
FI

3.10.4 SIPIを受け取った場合の疑似コード

IF IA32_SIPI_ENTRY_STRUCT_PTR.ENABLED = 0 THEN
  Shutdown // 非X86Sでは従来のSIPIに戻る
FI
// 範囲レジスターと許可を尊重する通常のリング0としてTDXではなくMKTMEキーを許容しながら以下のメモリー読み出しはフィジカルとして完了する。、
ENTRY_STRUCT = IA32_SIPI_ENTRY_STRUCT_PTR[12:MAXPA]
IF ENTRY_STRUCT->FEATURES != 1 THEN
  トリプル・フォルトではないシャットダウン // 非X86Sでは従来のSIPIに戻る
FI
# これらにはチェック事項が定義されていないことに注意すること
newCR4 = ENTRY_STRUCT->CR4 # entry_struct.CR4から読み出す
newRIP = ENTRY_STRUCT->RIP # entry_struct.RIPから読み出す
newCR0 = ENTRY_STRUCT->CR0 # entry_struct.CR0から読み出す
newCR3 = ENTRY_STRUCT->CR3 # entry_struct.CR3から読み出す
IF newCR4.PVI != 0 OR
  OR newCR4.PAE != 1 OR
  newCR4の予約ビットがセットされている OR // MOV CR4のいくつかのルールに従う
  newCR0.PE != 1 OR
  newCR0.MP != 1 OR
  newCR0.EM != 0 OR
  newCR0.NE != 1 OR
  newCR0.NW != 0 OR
  newCR0.PG != 1 OR
  newCR3の予約ビットがセットされている OR // MOV CR3のいくつかのルールに従う
  newCR4.LA57に関連してnewRIPがキャノニカルではない THEN
    停止不可能なシャットダウン
FI
IF LEGACY_REDUCED_OS_ISA CPUIDがクリア THEN
  // X86Sに相当するように状態を初期化する
  CS = Selector=0, Base=0, Limit=0xffffff, AR=Present, R/W, DPL=0, Type=3, S=1, G=1, L=1
  SS/ES/FS/GS/DS = Selector = 0, Base = 0, Limit = 0xffffff, AR = Present, R/W, DPL=0, Type=3, S=1, G=1
  EFER = LMA=1, LME=1, SC=1, NX=1
  GDTR/TR.limit = 0
FI
newCR0.ET = 1
CR4 = newCR4 ; CR3 = newCR3 ; CR0 = newCR0
受け付けたSIPIベクターをゼロ拡張してR10へ代入する
NMIをブロックする
RIP = newRIP

3.11 64ビットのリセット

CPUがリセットされた後には4レベルページ・テーブルを伴った64ビットのページ化モードで実行を開始します。リセット状態のX86Sに固定のRIPおよびCR3状態が存在するのであれば、どのようなFirmware Interface Table(FIT)も必要ではありません。固定リセットRIPの標準リセット・ベクターは0xFFFFFFF0で、64ビットでも同じ値が入力されます。固定リセットCR3の値は0xFFFFE000です。

表6にリセット時のレジスターの状態を示します。

表6.リセット時のレジスターの状態

レジスター Intel 64初期値 X86S初期値
EFLAGS 00000002H 00000002H
RIP/EIP 0000FFF0H FFFFFFF0H
CR0 00000000H 80000033H
CR2 00000000H 00000000H
CR3 00000000H FFFFE000H
CR4 00000000H 00000020H
CS Selector=F000H
Base=FFFF0000H
Limit=FFFFH
AR=Present, R/W, Accessed, Type=3
Selector=0H Base=n/a
Limit=n/a
AR=L=1
SS Selector=F000H
Base=FFFF0000H
Limit=FFFFH
AR=Present, R/W, Accessed, Type=3
Selector= 8
Base= n/a
Limit= n/a
AR=DPL=0, B=0, rest n/a
DS,ES Selector=0000H
Base=00000000H
Limit=FFFFH
AR=Present, R/W, Accessed, P=1,S=1 Type=3
Selector= 0
Base= n/a
Limit= n/a
AR=n/a
FS,GS Selector=0000H
Base=00000000H
Limit=FFFFH
AR=Present, R/W, Accessed, P=1,S=1 Type=3
Selector= 0
Base= 00000000H
Limit= n/a AR= n/a
EFER 0 LMA=1,LME1=,SC=1,NX=1
LDT Base=0,Limit=0,P=0 Base=0,Limit=0
TR Base=0, Limit=0xffff Base=0, Limit=0
IDTR Base=0,Limit=0xffff Base=0, Limit=0
GDTR Base=0,Limit=0xffff Base=0, Limit=0

3.12 固定MTRRの削除

今後は固定MTRRをサポートしません。固定ビット、IA32_MTRRCAPレジスター内のbit[8]はクリアーされ、すべてのMTRR_FIX_* MSRは実装されません。MTRR_DEF_TYPE bit[10]は予約されます。

表7に固定MTRR MSRから削除された内容を示します。

表7. 削除されたMTRR MSR

対象
IA32_MTRR_FIX64_00000
IA32_MTRR_FIX16_80000
IA32_MTRR_FIX16_a0000
IA32_MTRR_FIX4_c0000
IA32_MTRR_FIX4_c8000
IA32_MTRR_FIX4_d0000
IA32_MTRR_FIX4_d8000
IA32_MTRR_FIX4_e0000
IA32_MTRR_FIX4_e8000
IA32_MTRR_FIX4_f0000
IA32_MTRR_FIX4_f8000

3.13 XAPICとExtINTの削除

X2APICへアクセスする唯一の方法はMSRを経由したアクセスです。仮想XAPICはVMXを経由して依然としてサポートされます。

CPUは常にX2APICモード(IA32_APIC_BASE[EXTD]が1)で、そして有効です。APICを無効にするため、またはX2APICモードを離脱するために、IA32_APIC_BASEへ書き込みを試みると#GP(0)例外を引き起こします。

これはIA32_XAPIC_DISABLE_STATUS[LEGACY_XAPIC_DISABLED] MSRビットを1にすることを通じてソフトウェアに示します。

さらに詳しい内容についてはこちらを参照してください:https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/cpuid-enumeration-and-architectural-msrs.html

ローカルAPIC内のExtINTデコードは削除されました。

3.14 仮想化の変更

このセクションでは仮想化状態の変更について説明します。

“固定”フィールドは整合性が確認され、もし固定値と一致しないとVM entryは失敗します。

3.14.1 VMCSゲスト状態

ゲストVMCSフィールドの変更点を表8に示します。

VMEntryにおいて、削除されたセグメンテーション状態における一貫性の確認は行われません。

表8. VMCSフィールドの変更点 (ゲスト状態)

VMCSフィールド インデックス 変更点 理由
ゲストのアクティビティー状態中のWFSエンコーディング   0固定 64ビットSIPIをサポートしていない。
ゲストESのlimit 0x00004800 無視 限定されたセグメンテーション状態
ゲストCSのlimit 0x00004802 無視 限定されたセグメンテーション状態
ゲストSSのlimit 0x00004804 無視 限定されたセグメンテーション状態
ゲストDSのlimit 0x00004806 無視 限定されたセグメンテーション状態
ゲストFSのlimit 0x00004808 無視 限定されたセグメンテーション状態
ゲストGSのlimit 0x0000480a 無視 限定されたセグメンテーション状態
ゲストESのアクセス権 0x00004814 無視 限定されたセグメンテーション状態
ゲストDSのアクセス権 0x0000481A 無視 限定されたセグメンテーション状態
ゲストFSのアクセス権 0x0000481C 無視 限定されたセグメンテーション状態
ゲストGSのアクセス権 0x0000481E 無視 限定されたセグメンテーション状態
ゲストLDTRのアクセス権 0x00004820 無視 限定されたセグメンテーション状態
ゲストTRのアクセス権 0x00004822 無視 限定されたセグメンテーション状態
ゲストCSのアクセス権 0x00004816 LとDがセーブとロードの対象となる; Entryでは無視され、0を書き込むとExitとなる。 限定されたセグメンテーション状態
ゲストSSのアクセス権 0x00004818 DPLとBがセーブとロードの対象となる; Entryでは無視され、0を書き込むとExitとなる。 限定されたセグメンテーション状態
ゲストESのbase 0x00006806 無視 限定されたセグメンテーション状態
ゲストCSのbase 0x00006808 無視 限定されたセグメンテーション状態
ゲストSSのbase 0x0000680A 無視 限定されたセグメンテーション状態
ゲストDSのbase 0x0000680C 無視 限定されたセグメンテーション状態
ゲストPDPTE0 0x0000280A 無視 IA32eモードは常に有効
ゲストPDPTE1 0x0000280A※7 無視 IA32eモードは常に有効
ゲストPDPTE2 0x0000280A※8 無視 IA32eモードは常に有効
ゲストPDPTE3 0x0000280A※9 無視 IA32eモードは常に有効

3.14.2 VMCS Exit制御

VM Exit制御の変更点を表9に示します。

表9. VMCS Exit制御の変更点

VMCSフィールド 変更点 理由
ホスト・アドレス空間サイズ
(Host Address Space Size: HASS)
1固定 ホストは常に64ビットSupervisorモードであるため。

3.14.3 VMCS Entry制御

VM Entry制御の変更点を表10に示します。

表10. VMCS Entry制御の変更点

VMCSフィールド 変更点 理由
IA-32eモードのゲスト 1固定 ゲストは常にロング・モードであるため。

3.14.4 VMCSセカンダリー・プロセッサーベースの実行制御

変更点を表11に示します。

表11. セカンダリー・プロセッサーベースの実行制御の変更点

VMCSフィールド 変更点 理由
無制限ゲスト 0固定 無制限ゲストをサポートしないため。

3.14.5 VMXに関連するMSRの変更点

表12にVMXに関連するMSRの変更点を示します。

表12. VMXに関連するMSRの変更点

MSR ビット 対応フィールド 注記
IA32_VMX_EXIT_CTLS 9, 41 ホスト・アドレス空間サイズ 1 EFER LMEとLMAは1に固定される。
IA32_VMX_TRUE_EXIT_CTLS
IA32_VMX_ENTRY_CTLS 9, 41 IA-32eモードのゲスト 1 ゲストは常にロング・モード。
IA32_VMX_TRUE_ENTRY_CTLS
IA32_VMX_PROCBASED_CTLS2 39 無制限ゲスト 0 非無制限ゲスト。
IA32_VMX_MISC 8 アクティビティー状態のサポート:SIPIの待機 0 サポートしない。
IA32_VMX_CR0_FIXED0 0 PE: プロテクト・モード有効 1
(レガシー)
常にロング・モードでレガシーFPUモードではない。0に固定。※10
1 MP: コプロセッサーの監視 1
5 NE: 数値演算エラー 1
(レガシー)
31 PG: ページ化有効 1
(レガシー)
IA32_VMX_CR0_FIXED1 2 EM: FPエミュレーション 0 これらのCR0ビットは0に固定。
29 NW: ライト・スルーではない 0
IA32_VMX_CR4_FIXED0       変更なし。
IA32_VMX_CR4_FIXED1 1 PVI: プロテクトモード仮想割り込み 0 プロテクトモード仮想割り込みはサポートしない。

3.15 SMXの変更

X86SのためにGETSEC命令の以下のサブ・リーフの挙動、ENTERACCS/SENTER、EXITACと同様にRLP WAKEUPが変更されます。認証済みのコード・モジュールを受け入れた後の環境がX86S対応となるため、命令はその挙動の変化を反映します。本セクションではそれらの変化について詳細を説明します。

3.15.1 X86SにおけるSMXへの変更の概要

以下の変更が行われました:

  1. 全体的な変更:
    1. ACBASEはCPUにより0FEB00000hを設定する。メモリー上のポインターからCPUはACMイメージをロードする。そして、内部メモリーの位置0FEB00000hへコピーする。
    2. ACMの位置するリージョンのメモリー・タイプがWBでなければならないという要求事項はない。
  2. ENTERACCS/SENTERに対する変更:
    1. CodeControlフィールドを削除し、CodeControlチェックを削除する。
    2. 事前エントリーCR3、CR4、RIP、RSP、およびFRED MSRは内部構造体に保存する。
    3. CR3、RIP、およびFRED CONFIG MSRはACMヘッダーからロードする。
    4. 全てのセグメントの状態は変更しない。
    5. CR4、FRED_SKTLVLS、およびRSPは固定値が強制される。FREDは強制的に1とする。
  3. EXITAC
    CR3、CR4、RIP、およびFRED状態はR8が指定するストレージ構造体からロードする。
  4. WAKEUP
    1. CR3、CR4、およびRIPはJOIN構造体からロードする。
    2. セグメントの状態は変更しない。
  5. SEXIT

    SEXIT自体への変更はない。しかし、X86SではRLPがLT_WFS(SENTER_SLEEP)の中にあり、NEWSIPIが有効ではないと、INITは結果としてシャットダウンとなる。

3.15.2 ENTERACCS/SENTER状態後への変更の概要

表13に変更点を示します。

これらはX86S準拠環境を提供するための変化です。

表13. ENTERACCS/SENTER状態の後への変更点

レジスター状態 ENTERACCS後の値 – レガシー ENTERACCS後の値 – X86S
CR0 PG=0, AM=0, WP=0: 他の変更はない PG=1, AM=0, WP=1: 他の変更はない
CR4 MCE=0, CET=0, PCIDE=0: 他の変更はない PAE=1, FRED=1; SMXE=1; その他は0
IA32_EFER 0H 変更しない(EFERにはX86Sによる固定値がある)
EIP AC.base + EntryPoint ACMHeader[RIP]
[E|R]BX 事前ENTERACCS状態:GETSEC[ENTERACCS]に先立つ次の[E|R]IP 変更しない
ECX 事前ENTERACCS状態:[31:16]=GDTR.limit;[15:0]=CS.sel 変更しない
[E|R]DX 事前ENTERACCS状態:GDTR base 変更しない
EBP AC.base 変更しない
CS Sel=[SegSel], base=0, limit=FFFFFh, G=1, D=1, AR=9BH 0FEB00400h
DS Sel=[SegSel] +8, base=0, limit=FFFFFh, G=1, D=1, AR=93H 変更しない
GDTR Base= AC.base (EBX) + [GDTBasePtr],Limit=[GDTLimit] 変更しない
CR3 変更しない ACMHeader[CR3]
FRED_CONFIG 変更しない ACMHeader[FRED_CONFIG]
FRED_STKLVLS 変更しない 0

3.15.3 X86SにおけるENTERACCS/SENTERの疑似コード

(* 内部フラグACMODEFLASGの状態は命令境界を横断して維持される *)
IF (CR4.SMXE=0)
         THEN #UD;
ELSIF (VMXにおける非rootオペレーション)
         THEN VM Exit (reason=”GETSEC 命令”);
ELSIF (GETSECリーフをサポートしない)
         THEN #UD;
ELSIF ((VMXにおけるオペレーション) or
         (CR0.CD=1) or (CPL>0) or (IA32_APIC_BASE.BSP=0) or
         (TXT チップセットが存在しない) or (ACMODEFLAG=1) or (IN_SMM=1))
THEN #GP(0);
IF (GETSEC[PARAMETERS].Parameter_Type = 5, MCA_Handling (bit 6) = 0)
         FOR I = 0 to IA32_MCG_CAP.COUNT-1 DO
                  IF (IA32_MC[I]_STATUS = 回復不可能なエラー)
                  THEN #GP(0);
         OD;
FI;
IF (IA32_MCG_STATUS.MCIP=1) or (IERR ピンがアサートされている)
         THEN #GP(0);
ACBASE := EBX;
ACSIZE := ECX;
IF (((ACBASE MOD 4096) ≠ 0) or ((ACSIZE MOD 64 ) ≠ 0 ) or (ACSIZE < 最小モジュール・サイズ) OR (ACSIZE > 認証済み RAM 容量)) or ((ACBASE+ACSIZE) > (2^32 -1)))
         THEN #GP(0);
IF (副次スレッドが CR0.CD = 1) or ((副次スレッドがSIPI待ちではない) and
(副次スレッドが SENTER スリープ・ステートではない)
         THEN #GP(0);
SMI、INIT、A20M、およびNMI外部ピンによるイベントをマスク;※11
IA32_MISC_ENABLE := (IA32_MISC_ENABLE & MASK_CONST*)
(* MASK_CONSTの16進数値はプロセッサーの実装によって異なることがある *)
IA32_DEBUGCTL := 0;
不正なプロセッサー TLB;
外向けのトランザクションを排出する; ACMODEFLAG := 1;
SignalTXTMessage(ProcessorHold);
ACRAM空間全体をセットアップし、ACモジュール・サイズに基づいてACBASEからFEB00000hの内部ACRAMへロードを実行する;
Set ACBASE := 0FEB00000h;
IF (サポートしていないACモジュール・ヘッダーのバージョン) OR (ACRAM[ModuleType] ≠ 2)
         THEN TXT-SHUTDOWN(#UnsupportedACM);
(* ACモジュールの認証がエラーによって失敗するならシャットダウンする *)
KEY := GETKEY(ACRAM, ACBASE);
KEYHASH := HASH(KEY);
CSKEYHASH := READ(TXT.PUBLIC.KEY);
IF (KEYHASH ≠ CSKEYHASH)
         THEN TXT-SHUTDOWN(#AuthenticateFail);
SIGNATURE := DECRYPT(ACRAM, ACBASE, KEY);
(* SIGNATURE_LEN_CONSTの値は実装に依存する *)
FOR I=0 to SIGNATURE_LEN_CONST - 1 DO
         ACRAM[SCRATCH.I] := SIGNATURE[I];
COMPUTEDSIGNATURE := HASH(ACRAM, ACBASE, ACSIZE);
FOR I=0 to SIGNATURE_LEN_CONST - 1 DO
         ACRAM[SCRATCH.SIGNATURE_LEN_CONST+I] := COMPUTEDSIGNATURE[I];
IF (SIGNATURE ≠ COMPUTEDSIGNATURE)
         THEN TXT-SHUTDOWN(#AuthenticateFail);
IF (ACRAM[StateSaveAddress] MOD 64) ≠ 0)
  THEN TXT-SHUTDOWN(#BadACMFormat);
If (ACRAM[IA32_FRED_CONFIG]の予約ビットがセットされている)
  THEN TXT-SHUTDOWN(#BadACMFormat);
(* 状態をStateSaveAreaへ保存する *)
SSAddr[FRED_CONFIG] := IA32_FRED_CONFIG
SSAddr[FRED_STKLVLS] := IA32_FRED_STKLVLS
SSAddr[CR4] := CR4[63:0]
SSAddr[CR3] := CR3[63:0]
SSAddr[RIP] := 事前ENTERACCSによる次のRIP
SSAddr[RSP] := RSP
CR0.[AM] := 0;
CR0.[PG.WP] := 1;
CR4[FRED,PAE,SMXE]=1; 左記以外はCR4=0とする
EFLAGS := 00000002h;
RSP := 0FEB00400h;
CR3 := ZX(ACRAM[CR3], 64);
IA32_FRED_STKLVLS = 0;
IA32_FRED_CONFIG = ZX(ACRAM[IA32_FRED_CONFIG], 64);

DR7 := 00000400h;
IA32_DEBUGCTL := 0;
SignalTXTMsg(OpenPrivate);
SignalTXTMsg(OpenLocality3);
EIP := ACEntryPoint;
END;

3.15.4 X86SにおけるEXITACの疑似コード

(* 内部フラグACMODEFLASGとSENTERFLAGの状態は命令境界を横断して維持される *)
IF (CR4.SMXE=0)
         THEN #UD;
ELSIF (VMXにおける非rootオペレーション)
         THEN VM Exit (reason=”GETSEC 命令”);
ELSIF (GETSECリーフをサポートしない)
         THEN #UD;
ELSIF ((VMXオペレーション中) or ( (64ビット・モード中) and (RBXがキャノニカルではない) ) or
(CR0.PE=0) or (CPL>0) or (EFLAGS.VM=1) or (ACMODEFLAG=0) or (IN_SMM=1)) or (EDX ≠ 0))
         THEN #GP(0);
(* StateSaveのアドレスが適正であることをチェックする *)
SSAddr := R8
IF ((SSAddr MOD 64) ≠ 0 or MAX_PAを超える)
  THEN #GP(0);

TempRIP := SSAddr[RIP]
TempRSP := SSAddr[RSP]
TempCR4 := SSAddr[CR4]
TempCR3 := SSAddr[CR3]
TempFredConfig := SSAddr[FRED_CONFIG]
TempFredSTKLVLS := SSAddr[FRED_STKLVLS]

(* SSAの状態に対してチェックを実行する *)
IF ((TempCR3の予約ビットがセットされている) or
  (TempCR4.LA57によってTempRIPまたはTempRSPがキャノニカルではない) or
  (TempCR4 & CR4_MASK_CONST ≠ 0 ) or
  (TempFREDConfigの予約ビットがセットされているかキャノニカルでない)
THEN #GP(0);

ACRAMの内容を無効化;
プロセッサーのTLBの無効化;
外向けのトランザクションを排出する;

SignalTXTMsg(CloseLocality3);
SignalTXTMsg(LockSMRAM);
SignalTXTMsg(ProcessorRelease);
INITのマスクを解除;
IF (SENTERFLAG=0)
         THEN SMI, INIT, NMI, および A20M ピンによるイベントのマスクを解除;
ELSEIF (IA32_SMM_MONITOR_CTL[0] = 0)
         THEN SMI ピンによるイベントのマスクを解除;
ACMODEFLAG := 0;
CR3 := TempCR3;
CR4 := TempCR4;
RIP := TempRIP;
RSP := TempRSP;
IA32_FRED_CONFIG := TempFredConfig;
IA32_FRED_STKLVLS := TempFredSTKLVLS;

END;

3.15.5 X86SにおけるRLP_SIPI_WAKEUP_FROM_SENTER_ROUTINE(RLP限定)

WHILE (SignalWAKEUP イベントが発生しない);
IF (IA32_SMM_MONITOR_CTL[0] ≠ ILP.IA32_SMM_MONITOR_CTL[0])
	THEN TXT-SHUTDOWN(#IllegalEvent)
IF (IA32_SMM_MONITOR_CTL[0] = 0)
	THEN SMIピンによるイベントのマスク解除;
ELSE
	SMIピンによるイベントのマスク;
A20M、およびNMIピンによる外部イベントのマスク(INITのマスク解除);
SignalWAKEUPイベントのマスク;
プロセッサーのTLBの無効化;
外向けのトランザクションを排出する;
TempRIP := LOAD (LT.MLE.JOIN+0);
TempCR3 := LOAD (LT.MLE.JOIN+8);
TempCR4 := LOAD (LT.MLE.JOIN+16);
If (TempCR3の予約ビットがセットされている) or
  (TempRIPはキャノニカルではない) or
  (TempCR4 & CR4_RESERVED_BIT_MASK ≠ 0 )
  THEN TXT-SHUTDOWN(#BadJOINFormat);

3.16 削除対象のまとめ

表14に削除対象のまとめについて示します。

表14. 削除対象のまとめ

削除対象 代替 暗黙的な意味
セグメントbase(FS/GS/GDT/IDT/LDT/TSSを除く)、limit(GDT/IDT/TSS/LDTを除く)、セグメント権限 (CS.LとSS.Bを除く)、使用不可能なチェック(SS/CS/TRを除く) 限定されたセグメンテーション
リアル・モード(ビッグおよび16ビット) 64ビット・ページ化モード、64ビットSIPI
16ビット・プロテクト・モード
他のモードにおいてアドレスを参照するときの16ビット・アドレス・オーバーライド
32ビットのリング0に含まれる2または3レベル・ページ化モード 64ビット・リング0
CR0.MPを通じたFPUの無効化
レガシー数値エラーの取り扱い
仮想86モード 16ビット・モードの削除
プロテクトモード仮想割り込み(PVI: Protected-mode Virtual Interrupts)
クリアすることでページ・テーブル・エントリーのNXビットを無効にするために存在しているEFER.NXEの無効化
EFER.SCEを通じたSYSCALLの無効化
FAR JMP/RET/CALLによるリングの変更 SYSCALL、INT 限定されたセグメンテーション
IRET/SYSCALL/SYSRETによる16ビット・モード、仮想86モードまたはコンフォーミング・セグメントへの遷移。STARではないセグメントのERETUによるサポート。 16ビット・モードの削除および限定されたセグメンテーション
固定MTRR 可変MTRRおよびページ・テーブル内のPAT
MMIOベースのXAPICアクセス MSRを通じたX2APICへのアクセス
APICのExtINTの削除
リング1、リング2の削除
リング3による入出力ポートへのアクセス(IOPL、(TSS32の)入出力ビットマップ) リング0による入出力ポートへのアクセス
INSおよびOUTS命令 ループによるINおよびOUT命令
#SS例外 #GP(0)例外 限定されたセグメンテーション
#NP例外 #GP(0)例外 限定されたセグメンテーション
VMCSによるエントリーにおけるINIT/SIPIのサポート 64ビット SIPI
VMCSにおける無制限ゲストのサポート 16ビット・モードの削除、ページ化は常に有効
VMCSによる32ビット・リング0のサポート 32ビット・リング0の削除

3.17 追加事項のまとめ

アーキテクチャーへ新たに追加する内容を表15に示します。

表15. 追加事項のまとめ

追加内容 理由 要求事項
64ビットのSIPIとINIT 64ビット・ページ化モードにおけるAPの起動 リアル・モードの削除

3.18 変更された命令

以下の解説は命令の新しい振る舞いのみに関係します。セグメンテーションに関連する命令についてのより長いリストは変更された振る舞いが、もしあればセクション4.3に示されています。細かな変更に伴う命令が概要に記録されるのみです。

これまでの振る舞いについては「Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D and 4.」を参照ください。

3.18.1 SYSRET

SYSRETによってゼロではない値がRFLAGS.IOPL、RFLAGS.VIP、またはRFLAGS.VIFにロードされると#GP(0)例外が生成されます。

3.18.2 IRET

IRETは16ビットのモード、タスク・ゲートにジャンプすることはできません。リング0の時にゼロではない値をRFLAGS.IOPL、RFLAGS.VIP、またはRFLAGS.VIFにロードすると、IRETは#GP(0)例外を生成します。IRET命令の詳細については、セクション4.2.6の疑似コードによって示しています。

3.18.3 POPF – スタックからRFLAGSレジスターへ

オペコード 命令 Op/ En 64ビット・モード コンパチビリティー/レガシー・モード 内容説明
9D POPFD ZO 実行不可※12 有効 スタックの先頭からPOPしてEFLAGSへ代入
9D POPFQ ZO 有効 実行不可 スタックの先頭からPOPしてゼロ拡張をしてRFLAGSへ代入

POPFは現在のオペランド・サイズ属性が32ビットであれば、先頭からDWORD(POPFD)をポップし、ELFAGSレジスターに値を保存します。また、スタックのオペランド・サイズ属性が16ビットであれば、(先頭からWORD※13でポップし)それをEFLAGSレジスターの下位16ビットに保存します(すなわち、それはFLAGSレジスターです)。これらの命令はPUSHF/PUSHFD/PUSHFQ命令の操作を逆転させるものです。

IOPL、VM、VIP、およびVIF フラグは常にゼロであり、POPでは無視されます。

POPF命令は#SS例外を決して引き起こしません、#GP(0)または#PF例外のみです。

表16に変更されたRFLAGSを示します。

表16. POPF命令によるRFLAGSの変更

モード オペラント・サイズ CPL フラグ
21 20 19 18 17 16 14 13:12 11 10 9 8 7 6 4 2 0
ID VIP VIF AC VM RF NT IOPL OF DF IF TF SF ZF AF PF CF
リング3およびリング0モード 32、64 * S N N S N 0 S N S S N S S S S S S
キー
S スタックからの更新
N 値は変更しない
0 値はクリアされる

疑似コード:

tempFlags = POP // 32/64ビットのオペランド・サイズに従う
IF CPL = 0 THEN
    // RF、IOPL、VIP VIF、VMを除き、“tempFlags”から予約されたフラグ以外を変更する。
    // RFはクリアする。
    // オペランド・サイズによってPOPされないフラグは変更してはならない。
ELSE
    // RF、IOPL、VIP VIF、VM、IFを除き、“tempFlags”から予約されたフラグ以外を変更する。
    // RFはクリアする。
    // オペランド・サイズによってPOPされないフラグは変更してはならない。
FI

表17に削除された命令のまとめを示します。

表17. 削除された命令

命令 使用することができるレガシーにおけるリング 代替
INS / OUTS リング3、1、2、0 IN、OUT
64ビットの間接far jumpで0x67プリフィクスによって16ビットのオペランドに変化する場合は#UDとなる。
32ビットのnear ret、far call、far ret、far jmpに0x67プリフィクスが付与されることで16ビットのオペランドに変化する場合は#UDとなる。
32ビットのnear jmp、jCC、JECX*、near ret、near call、loop*、far jmpに0x67プリフィクスが付与されることで16ビットのオペランドに変化する場合は#UDとなる。
ジャンプではない32ビットのすべての命令においてメモリーを参照する場合に0x67プリフィクスが伴うことで16ビットのオペランドに変化する場合は#GPとなる。
リング3、1、2、0 32ビット/64ビットのメモリー参照
LMSW リング3、1、2、0 MOV CR0

3.19 変更された命令のまとめ

表18に変更された命令のまとめを示します。

表18. 命令の変更

命令 リング 変更
ERETU 0 STARではないセグメントのサポートを行わない。RFLAGS IOPL、VM、VIF、VIPビットはゼロでなければならない。
ERETS 0 RFLAGS IOPL、VM、VIF、VIPビットはゼロでなければならない。
IRET 3、0 16ビットのモードまたは仮想86モードまたはゲートまたはリング1あるいは2をサポートしない。リングは現状にとどまるかリング0からリング3へと移行しなければならない。RFLAGS IOPL、VM、VIF、VIPビットはゼロでなければならない。簡易化されたチェックをする。
SYSRET 0 RFLAGS IOPL、VM、VIF、VIPビットはゼロでなければならない。
FAR CALL 3、0 リングを変更することはできない。16ビットのオペランド・サイズは#UDとなる。32ビット・モードの間接において0x67が伴うと#UDとなる。
FAR JMP 3、0 リングを変更することはできない。16ビットのオペランド・サイズは#UDとなる。32ビット・モードにおいて0x67が伴うと#UDとなる。
POPF 3、0 RFLAGS IOPL、VM、VIF、VIPビットはゼロでなければならない。
FAR RET 3、0 リングを変更することはできない。16ビットのオペランド・サイズとなる場合には#UDとなる。
STI 3、0 VM86/PVIを経由したリング3による変更はサポートしない。
CLI 3、0 VM86/PVIを経由したリング3による変更はサポートしない。
VERW、VERR、セレクターへのMOV、セレクターからのMOV、PUSH sel、POP sel、LAR、LGS、LFS、LES、LFS、LGS、LSS、LDS、LKGS 3、0 簡易化されたチェック。
IN*、OUT* 3 リング3における入出力ポートの廃止。
JMP short、JMP、LOOP、JECX、CALL、RET、JMP 3、0 32ビット・モードにおいて16ビットのオペランド・サイズになる場合には#UD。

3.20 ソフトウェアの互換性に関する注記

3.20.1 リング3における入出力ポートへのアクセスのエミュレーション

TSS入出力ポート・ビットマップを使用するリング3入出力ポート・アクセスあるいはIOPLによるレガシー用途であれば、リング0において#GP(0)ハンドラーを通じて入出力をエミュレートすることが可能です。#UDハンドラーにて、適切なエミュレーション・ルーチンにおいてINS/OUTSをエミュレートすることができます。

3.20.2 64ビットSIPI

制御をOSに渡すまでは、BIOSはSIPI_ENTRY_STRUCT ENABLESフィールドにおいて常に64ビットSIPIを無効にすべきです。BIOSはすべてのパッケージでIA32_SIPI_ENTRY_STRUCT_PTR MSRを初期化して有効にしなければなりません。Intel 64では、これによってレガシーOSがレガシーSIPIを使用することを確実にします。OSは64-bit-SIPI-awareを有効にすることができます。X86SにおいてはレガシーSIPIを使用することはできませんが、一方でOSは一貫性のために64ビットのSIPIを行うようにすることができます。

3.20.3 64ビットのリセット

リセットはIntel 64と同じエントリー・ポイントを使用しますが、(X86Sは)ページ化されたモードを使用します。エントリー・コードはX86SによってセットされるCR0.PGをチェックすることにより、Intel 64による互換性のあるモードであるかどうかを判定することができます。

3.20.4 レガシーOSの仮想化

VMMはVM Exitの失敗がVMMによるレガシーの振る舞いのエミュレートが必要となる場合のために、適切にシステム状態とVMCSをセットアップすることに責任があります。VMMがVM entryを実行することを試みることがない場合もありますが、サポートされたゲスト状態に到達するまで、代わりにエミュレートを行います。例えば16ビットまたは32ビットのリング0のコードへ到達する場合のようなケースです。

もし、ゲストが互換性を必要とするのであれば、VMMには(a)例外ビットマップを設定し、それによって#UDと#GPはVM Exitを引き起こし、(b)適切な応答をするために、例外の原因を調査してエミュレートを行う責任があります。いくつかの例:

  • CLIのいくつかの変種がもっともらしく#GP(0)を意図している。例えば、レガシー・ゲストがリング3においてRFLAGS.IOPL==3でCLIを実行した場合である。常にRFLAGS.IOPLはゼロであるので、このリング3のCLIは常に#GP(0)となる。ゲストがこれらのIOPLセマンティクスを必要とするのであれば、エミュレートされたレガシー・ゲストのRFLAGS.IOPLの値でこの命令をエミュレートするかどうかはVMMの責任による。後に議論するゼロではないIOPLの仮想化できない側面があることに注意が必要である。
  • #SSと#NPは#GPに変換される。ゲストが#SS/#NPを必要とする場合にはVMMは#GPが#SSと#NPのいずれかが原因となっているかを検出し、ゲストに対してそれらを注入する必要がある。

いくつかのゲストのCR値はVMENTRYにおいて無視されます(それは固定値および一貫性が確認されていないものです)。ゲストが必要とするなら、VMMはこの違いを仮想化することができます。それらについては以下で説明します:

  • CR0.MPは1に固定されている。VMMは偽フォルトの内容を分析してエミュレートすべきである。
  • CR4.PVIは0に固定されている。VMMはSTI/CLIによる#GPを分析して、ゲストが想定する振る舞いをエミュレートすることができる。
  • CR4.DEは1に固定されている。VMMは偽フォルトの内容を分析してエミュレートすることができる。
  • CR4.PSEとCR4.PAEは固定されている。レガシー・ページ化モードはシャドウ・ページングまたはエミュレーションを必要とする。
  • EFER.LMEは1に固定されている。ゲストが32ビットのCPL0モードであり、VMMがVMentryをすることを求めるのであれば、それはエミュレーションを使用すべきである。
  • RFLAGS:
    • IOPLは0に固定されている。
    • VIF、VIPは0に固定されている。これに関連していくつかのCLI/STIは#GP(0)となる。ゲストがこの機能を必要とするのであれば、適切にこれらを扱うためにエミュレートすることができる。

VMMは必要に応じてレガシーの機能をエミュレートすることを選択することができます:

  1. メインストリームのIntel64ゲストがレガシーSIPIまたは非64ビットによる起動を使用するのであればVMMの変更が必要である:
    1. 16ビット・モードのエミュレート(リアル・モード、仮想8086モード)
    2. 非ページ化モードのエミュレート
    3. レガシーINIT/SIPIのエミュレート
  2. 珍しいケースを取り扱うための任意のVMMの変更:
    1. IOPL != 0(ゲストがリング3で入出力ポートへのアクセスあるいはリング3でCLI/STIの実行を想定している場合)
      1. CPL3におけるCLI #GPをキャッチしてエミュレートする。
      2. CPL3におけるSTI #GPをキャッチしてエミュレートする。
      3. CPL3におけるIN/OUT #GPをキャッチしてエミュレートする。
      4. CPL0におけるIRETによってIOPLを変更することを試みると発生する#GPをキャッチしてエミュレートする。

      次のセクションで説明する、ゼロではないIOPLの仮想化できない側面があることに注意すること。

    2. INS/OUTS命令の削除: #UDをキャッチしてエミュレートする。
    3. コール・ゲート: VMMは関連する#GPをキャッチしてエミュレートする必要がある。
    4. #SSの削除: VMMは関連する#GPをキャッチしてゲストに#SSとして通知することができる。
    5. #NPの削除: VMMは関連する#GPをキャッチしてゲストに#NPとして通知することができる。
    6. CR4.PVIは関連する#GPをキャッチしてエミュレートする。
    7. 16ビット・アドレッシングによる#GP/#UDをキャッチしてエミュレートする。
    8. CR4.VME、RFLAGS.VM: 仮想8086モードのエミュレートをする。
    9. 32ビット・リング0のエミュレートと、レガシー・ページ化モードにおけるシャドウ・ページングを伴った32ビット・リング3の実行。
    10. サポートされていない下方伸長のようにあまり知られていないセグメンテーションの機能または非コンフォーミング・コード・セグメント※14のサポート: #GPをキャッチすることでエミュレートすることができる。
  3. 処理コストのかかる切り替え対策が必要な珍しいケース:
    1. CPL1/2は部分的なエミュレーションを必要とする。
    2. フラットではないCS/DS/ES/SSセグメントまたはメモリー内のディスクリプターのアクセス・ビットの設定は、Descriptor Table ExitingとGDT/LDT limitにゼロを設定(またはGDT/LDT読み出し/書き込み保護)することをトリガーとしてセグメンテーション命令をキャッチする、完全なエミュレーションを必要とする。
    3. EFER.NXEがクリアされているなら、PTE内のNXビットのセットはシャドウ・ページングが必要となる。
    4. ロード/ストア/実行におけるセグメンテーション権限チェック: 完全なエミュレーションを必要とするだろう。
  4. 仮想化ができないケース:
    1. RFLAGS.IOPL != 0: ほとんどの場合、IOPLがゼロではないことによる振る舞いが典型的に変更されているため、代わりに#GPをVMMがキャッチ/エミュレートすることができる(すなわち、多くのケースにおいて仮想化をすることができる)。問題が発生すると思われるIntel 64のケースは以下の通りである。
      1. リング0にはIOPLを3にしてリング3に変更することができる権限がある。リング3への切り替えをPUSHFまたはSYSCALLを実行することで行う場合には、メモリーまたはレジスターの指し示す先がIOPL=3の値であることを確認しなければならない。VMがこのシーケンスを実行するとき、IOPLに3を設定するリング0の命令は#GPを引き起こしてVMExitのトリガーとなる。VMMが“間違った”IOPLとともにVMを再開するなら、例えば、IOPL==0でリング3のPUSHFまたはSYSCALLがメモリーあるいはレジスターを経由して、この不正確なIOPLを漏洩させることになるだろう。また、リング3のPOPFはIFを更新することはない。適切な枠組みは、IOPLが0に戻されるまでVMMがゲストをエミュレートすることだ。このようなケースは現代のソフトウェアでは想定されない。
      2. ゲストがリング0でPOPF命令を使用してIOPLをゼロ以上に設定することを試みると、これは警告なしで無視される。IOPLの値は更新されずに、そしてVMMは、これが起こったことを検出することはできない。後続の命令は、この値によって(例えば、CLI/STI/IN/OUT)における#GPの生成や、警告なしで異なる意味を持って実行される(例えば、POPFによるIFの更新、PUSHFによるメモリーへの書き込み、SYSCALLによるフラグのストアなど)。
    2. EFER.SCEがクリアされている時に、SYSCALL/SYSEXITを実行したときの振る舞いを#UDとする。

3.20.5 Intel 64への移行

もし、ゲストがX86SからIntel 64へ移行するとき、X86Sによって削除されたVMCSフィールドのセグメンテーションを(特定の値で)満たしたセグメンテーション状態の許容が必要です:

  • Limit: 削除されたフィールドを無制限へと満たす。
  • Base: 削除されたbaseを0へと満たす。
  • CS: もし、セレクターがゼロであればUnusable=1とし、そうでなければ S=1, Type=11, L=VMCSからの値, CPL=VMCSからの値, D=!L, G=1, P=1とする。
  • SS: もし、セレクターがゼロであればUnusable=1とし、そうでなければ S=1, Type=3, B=VMCSからの値, CPL=VMCSからの値, P=1, G=1とする。
  • DS/ES/FS/GS: もし、セレクターがゼロであればUnusable=1とし、そうでなければ S=1, Type=3, G=1, P=1とする。
  • LDT(R)/GDT(R)/TR: S=0およびそれぞれのタイプとし、Gビットに基づくlimit値を設定する。

以上で言及しなかったフィールドは0とします。

4 参考情報

この参考情報は限定されたセグメンテーションと例外の互換性に関する詳細に言及するものです。

4.1 セグメンテーション命令の振る舞い

説明文は命令の新しい振る舞いについて説明する目的のみであることに注意してください。これまでの振る舞いについてはSDM※15を参照してください。疑似コードには、最終的なフォルトの発生またはエラー・コードについて説明が存在していない部分があります。何かの変更がベースラインから適用されていない場合には、それには言及しません。

Check_selector(selector):
  IF CS AND selector is NULL THEN
    #GP(0);
  FI
  IF (selector.TI == 0 AND selectorはGDT limitを超えている) OR
   (selector.TI == 1 AND selectorはLDT limitを超えている) OR
   テーブルの中のディスクリプター・アドレスがキャノニカルではない THEN
    #GP(selector); // OR ZF := 0
  FI
END

Check_CS_desc(selector, Descriptor, newCPL):
  IF Descriptorがコード・セグメントではない
   OR (Descriptor.L xor Descriptor.D == 0) // 16ビットのサイズを防ぐ。無効なサイズ
   OR Descriptor.DPL == 1 // ゲートのためにのみ必要とする
   OR Descriptor.DPL == 2 // ゲートのためにのみ必要とする
   OR selector.RPL != Descriptor.DPL
   OR (Descriptor.DPL != newCPL and not (トラップまたは割り込みゲート))
   OR (Descriptor.DPL > newCPL and (トラップまたは割り込みゲート)) // ゲートは外に行くことはできない
   OR (Descriptor.L == 0 AND Descriptor.DPL == 0) // 32ビット・リング0を防ぐ
   OR (descriptor.P == 0 ) THEN
    #GP(selector);
FI
END

Check_CS_desc_for_IRET(selector, Descriptor, newCPL):
  IF Descriptorがコード・セグメントではない
   OR (Descriptor.L xor Descriptor.D == 0) // 16ビットのサイズを防ぐ。無効なサイズ
   OR Descriptor.DPL == 1
   OR Descriptor.DPL == 2
   OR selector.RPL != Descriptor.RPL
   OR Descriptor.DPL != newCPL // IRETは内側に行くことはできない
   OR (Descriptor.L == 0 AND Descriptor.DPL == 0) // 32ビット・リング0を防ぐ
   OR (descriptor.P == 0 ) THEN
    #GP(selector);
  FI
END

Check_Data_desc(selector, Descriptor):
  IF selector is not NULL THEN
    IF selectorがGDT/LDT limitを超えている // VMEntry/RSMに適用できない
     OR selector.RPL < CPL
     OR Descriptorはシステム・タイプ
     OR (descriptor.P == 0 ) THEN
      #GP(selector); // OR ZF := 0
    FI
  FI
END

// MOV SS、POP SS、LSSでこれを使用する
Check_SS_desc(selector, Descriptor):
  IF selectorがGDT/LDT limitを超えている
   OR (selector is non NULL AND selector.RPL != DPL)
   OR selector is NULL
   OR Descriptorがシステム・タイプ
   OR Descriptor.DPL != CPL
   OR Descriptor.P == 0 THEN)
    #GP(selector); // OR ZF := 0
  FI
  // SS.B / Selector / DPLをVMXのために保存する
END

// IRETのためにのみこれを使用する
Check_SS_desc_for_iret(selector, Descriptor, newCPL):
  IF selector is not NULL THEN
    IF selectorがGDT/LDT limitを超えている
     OR selector.RPL != Descriptor.DPL
     OR Descriptorがシステム・タイプ
     OR Descriptor.DPL != newCPL
     OR descriptor.P == 0 THEN
      #GP(selector); // OR ZF := 0
    FI
  ELSIF (newCPL == 3 OR 64ビット・モードではない) THEN // NULL
    #GP(selector)
  FI
  // SS.B / Selector / DPLをVMXのために保存する
END

Load_descriptor_from_GDT_LDT(selector):
  IF (selector & 0xFFF8) != 0x0 THEN
    IF selector.TI == 1 THEN BASE := LDT Base;
    ELSE BASE := GDT Base; FI;
    Desc := load_physical_sup(BASE + (selector & 0xFFF8));
    ディスクリプター・コピーのアクセス・ビットをセットするが、メモリー内はセットしない
    Return Desc;
  ELSE
    Return 0;
  FI
END

Load_descriptor_from_IDT(vector):
  Desc := load physical_sup(IDT base + vector << 4);
  Return Desc;
END

4.2 セグメンテーション命令の疑似コード

4.2.1 CALL Far

FAR CALLはイントラレベル※16専用です。モード制限が強制されます。セレクターはGDT/LDT内のコンフォーミング・コード・セグメントではないディスクリプターを指し示さなければなりません。CS.accessedビットはセットしません。新しいディスクリプターはVMXで使用するために保存します。16ビットのオペランド・サイズが伴う場合には命令は#UD例外を投げます。0x67プリフィクスで間接かつ32ビット・モードの命令は#GP(0)となります。#NPと#SSは#GPに置き換えられます。

IF 16ビットのオペランド・サイズ THEN #UD ; FI

IF 0x67 プリフィクス AND 間接 AND 32ビット・モード THEN #GP(0); FI

Check_selector(newCS);
newCSdesc := Load_descriptor_from_GDT_LDT(tempCS);
Check_CS_desc(tempCS, newCSdesc, CPL);
IF newRIPはキャノニカルではない THEN
  #GP(0)
FI
Push CS;
Push RIP;
CS := newCS;
RIP := newRIP;
Save newCSdesc;
有効にされているならシャドウ・スタックにPUSHする
有効にされているなら分岐終了状態に遷移する

4.2.2 ERETU

RFLAGSの制限が強制されます。モードの制限はコード・セレクター・タイプの制限と同様に強制されます。ディスクリプターのアクセス・ビットをセットすることはありません。#NPと#SSは#GPに置き換えられます。

Intel64と同じフローで開始する。
// Intel 64 FREDはIA32_STARと互換性のあるCS/SSであるかを確認する
いくつかのFREDコード
ELSE IF newCS OR newSS がIA32_STARと互換性がない THEN
  #GP(0);
FI
残りの流れはIntel 64と同じ

4.2.3 ERETS

RFLAGSの制限が強制されます。

4.2.4 FRED Entryの流れ

RFLAGSの制限が強制されます。

4.2.5 CR4.FRED ==0におけるINT n、INT3、INTO、外部割込、例外

モードの制限とディスクリプター・タイプの制限が強制されます。ディスクリプターのアクセス・ビットはセットしません。#NPは#GPに置き換えられます。

※訳注:次の疑似コードの冒頭部分には何か処理名(と場合によっては+α)が記述されていたか、冒頭処理の最後のEND;が表記上不要なものであるかのいずれかの可能性があります。

  IF INTO and CS.L = 1 THEN
    #UD;
  FI;
  IF ((vector_number « 4) + 15)がIDT.limit内でなければ THEN
    #GP(error_code(vector_number,1,EXT));
  FI;
  gate := Read_descriptor_from_IDT(vector_number);
  IF gate.type not in {64ビット割り込みゲート, 64ビット・トラップ・ゲート} THEN
    #GP(error_code(vector_number,1,EXT));
  FI;
  IF ソフトウェア割り込み (* INT1へは受け入れられない *) THEN
    IF gate.DPL < CPL THEN
      #GP(error_code(vector_number,1,0));
    FI;
  FI;
  IF gate.P == 0 THEN
    #GP(error_code(vector_number,1,EXT));
  FI
  newCS := gate.selector;
  IF newCS is NULL THEN
    #GP(EXT); (* エラー・コードにはNULLセレクターを含む *)
  FI;
  Check_selector(newCS);
  newCSdesc := Load_descriptor_from_GDT_LDT(newCS);
  Check_CS_desc(newCS, newCSdesc, 0);
  IF newCSdesc.DPL < CPL THEN
    GOTO INTER-PRIVILEGE-LEVEL-INTERRUPT;
  ELSIF newCSdesc.DPL = CPL THEN
    GOTO INTRA-PRIVILEGE-LEVEL-INTERRUPT;
  ELSE
    #GP(error_code(新しいコードセグメント・セレクター,0,EXT));
  FI
END;

// 訳注:特権レベルをまたぐ割り込みの疑似コード
INTER-PRIVILEGE-LEVEL-INTERRUPT:
  IF gate.IST == 0 THEN
    TSSstackAddress := (newCSdesc.DPL « 3) + 4;
  ELSE
    TSSstackAddress := (gate.IST « 3) + 28;
  FI;
  IF (TSSstackAddress + 7) > TSS.limit THEN
    #TS(error_code(TSS.selector,0,EXT);
  FI;
  NewRSP := 8 bytes loaded from (TSS.base + TSSstackAddress);
  NewSS := newCSdesc.DPL; (* RPL = new CPLを伴うNULLセレクター *)
  IF gate.IST = 0 THEN
    NewSSP := IA32_PLi_SSP; (* where i = newCSdesc.DPL *)
  ELSE
    NewSSPAddress := IA32_INTERRUPT_SSP_TABLE_ADDR + (gate.IST « 3);
    IF ShadowStackEnabled(CPL0) THEN
      NewSSP := NewSSPAddressから8バイトをロード;
    FI;
  FI;
  IF NewRSPがキャノニカルではない THEN
    #GP(EXT); (* エラー・コードにはNULLセレクターを含む *)
  FI;
  IF gate.IPがキャノニカルではない THEN
    #GP(EXT); (* エラー・コードにはNULLセレクターを含む *)
  FI;
  RSP := NewRSP & FFFFFFFFFFFFFFF0H;
  SS := NewSS;
  SSdesc := const;
  Push(SS);
  Push(RSP);
  Push(RFLAGS); (* 8バイトのPUSH *)
  Push(CS);
  PUSH(RIP);
  Push(ErrorCode); (* もし必要とされるなら8バイト *)
  RIP := gate.RIP;
  CS := newCS;
  IF ShadowStackEnabled(CPL) AND CPL == 3 THEN
    IA32_PL3_SSP := LA_adjust(SSP);
  FI;
  CPL := newCSdesc.DPL;
  CS.RPL := CPL;
  IF ShadowStackEnabled(CPL) THEN
    oldSSP := SSP
    SSP := NewSSP
    IF (SSP & 0x07 != 0) THEN
      #GP(0);
    FI
    IF (CS.L = 0 AND SSP[63:32] != 0) THEN
      #GP(0);
    FI
  FI;
  expected_token_value := SSP; (* Bustビットはクリアでなければならない *)
  new_token_value := SSP | BUSY_BIT; (* Bustビットをセットする *)
  IF (shadow_stack_lock_cmpxchg8b(SSP, new_token_value,
   expected_token_value) !=
   expected_token_value) THEN
    #GP(0);
  FI;
  IF oldSS.DPL != 3
    ShadowStackPush8B(oldCS);
    ShadowStackPush8B(oldRIP);
    ShadowStackPush8B(oldSSP);
  FI;
  IF EndbranchEnabled (CPL)
    IA32_S_CET.TRACKER = WAIT_FOR_ENDBRANCH;
    IA32_S_CET.SUPPRESS = 0
  FI;
  IF gate.typeが64ビット割り込みゲート THEN
    RFLAGS.IF := 0 (* 割り込みフラグに0をセットし、割り込みを禁止する *);
  FI;
  RFLAGS.TF := 0;
  RFLAGS.RF := 0;
  RFLAGS.NT := 0;
END;

// 訳注:特権レベルをまたがない割り込み
INTRA-PRIVILEGE-LEVEL-INTERRUPT:
  NewSSP := SSP;
  CHECK_SS_TOKEN := 0;
  IF gate.IST != 0 THEN
    TSSstackAddress := (IDT-descriptor IST « 3) + 28;
    IF (TSSstackAddress + 7) > TSS.limit THEN
      #TS(error_code(current TSS selector,0,EXT));
    FI;
    NewRSP := 8 bytes loaded from (current TSS base +
    TSSstackAddress);
  ELSE
    NewRSP := RSP;
  FI;
  IF ShadowStackEnabled(CPL) THEN
    NewSSPAddress := IA32_INTERRUPT_SSP_TABLE_ADDR + (IDT gate IST « 3)
    NewSSP := NewSSPAddressから8バイトをロード
    CHECK_SS_TOKEN := 1
  FI;
  IF NewRSPがキャノニカルではない THEN
    #GP(EXT); (* エラー・コードにはNULLセレクターを含む *)
  FI;
  IF gate.RIPがキャノニカルではない THEN
    #GP(EXT); (* エラー・コードにはNULLセレクターを含む *)
  FI;
  RSP := NewRSP & FFFFFFFFFFFFFFF0H;
  Push(SS);
  Push(RSP);
  Push(RFLAGS); // 8バイトのPUSH – .IFを含むがIOPL、CPLの影響は受けない
  Push(CS);
  PUSH(RIP);
  Push(ErrorCode); (* もし必要とされるなら8バイト *)
  oldCS := CS;
  oldRIP := RIP;
  RIP := gate.RIP;
  CS := newCS;
  CS.RPL := CPL;
  IF ShadowStackEnabled(CPL) AND CHECK_SS_TOKEN == 1 THEN
    IF NewSSP & 0x07 != 0 THEN
      #GP(0);
    FI;
    IF (CS.L = 0 AND NewSSP[63:32] != 0) THEN
      #GP(0);
    FI;
    expected_token_value := NewSSP (* Bustビットはクリアでなければならない *)
    new_token_value := NewSSP | BUSY_BIT (* Bustビットをセットする *)
    IF shadow_stack_lock_cmpxchg8b(NewSSP, new_token_value,
     expected_token_value) !=
     expected_token_value THEN
      #GP(0);
    FI;
  FI;
  IF ShadowStackEnabled(CPL) THEN
    (* 次の8ビット境界へと位置を合わせる *)
    tempSSP = SSP;
    Shadow_stack_store 0から(NewSSP − 4)の4バイト
    SSP := newSSP & 0xFFFFFFFFFFFFFFF8H;
    ShadowStackPush8B(oldCS);
    ShadowStackPush8B(oldRIP);
    ShadowStackPush8B(tempSSP);
  FI;
  IF EndbranchEnabled (CPL)
    IF CPL == 3 THEN
      IA32_U_CET.TRACKER = WAIT_FOR_ENDBRANCH;
      IA32_U_CET.SUPPRESS = 0;
    ELSE
      IA32_S_CET.TRACKER = WAIT_FOR_ENDBRANCH;
      IA32_S_CET.SUPPRESS = 0;
    FI;
  FI;
  IF IDT gateが割り込みゲート THEN
    RFLAGS.IF := 0; (* 割り込みフラグに0をセットし、割り込みを禁止する *)
  FI;
  RFLAGS.TF := 0;
  RFLAGS.NT := 0;
  RFLAGS.RF := 0;
END;

4.2.6 IRET

IRETは16ビット・モードあるいはVM86モードに入ることはできません。タスク・ディスクリプターのアクセス・ビットはセットしません。モードの制限が強制されます。#NPと#SSは#GPに置き換えられます。

IF FGLAGS.NT == 1 THEN
  #GP(0);
FI
tempRIP := POP(); // オペランド・サイズに従う
tempCS := POP(); // オペランド・サイズに従う
newCPL := tempCS.RPL
tempFlags := POP();// オペランド・サイズに従う
IF CPL == 3 THEN
  tempFlags(VIP, VIF, IOPL) := (0, 0, 0);
ELSIF tempFlags(VIF, VIP, IOPL) != (0,0,0) THEN
  #GP(0);
FI
Check_selector(tempCS);
Descriptor := Load_descriptor_from_GDT_LDT(tempCS);
Check_CS_desc_for_IRET(tempCS, Descriptor, newCPL);
IF newCPL > CPL THEN
  IF CR4.FRED THEN
    #GP(tempCS);
  ELSE
    GOTO RETURN_TO_OUTER_PRIVLEDGE_LEVEL; // レベル3でなければならない
  FI
ELSIF 64ビット・モードを開始済み THEN
  GOTO RETURN_FROM_IA32e;
ELSE
  GOTO RETURN_FROM_SAME_PRIVLEDGE_LEVEL;
FI

RETURN_FROM_SAME_PRIVLEDGE_LEVEL:
  IF tempRIPがキャノニカルではない THEN
    #GP(0); // RSPを元に戻す
  FI
  IF ShadowStackEnabled(CPL) THEN
    SDMで説明されているように、通常のシャドウ・スタック操作を実行する;
  FI
  CS := tempCS;
  RIP := tempRIP;
  RFLAGS(CF, PF, AF, ZF, SF, TF, DF, OF, NT, RF, AC, IC) := tempFlags;
  IF CPL == 0 THEN FGLAGS(IF) := tempFlags; FI;
    NMIのマスクを解除する;
  END;

RETURN_FROM_IA32e:
  tempRSP := POP();
  tempSS := POP();
  Check_sel(tempSS);
  tempSSdesc := Load_descriptor_from_GDT_LDT(tempSS);
  check_SS_desc(tempSS, tempSSdesc, newCPL); // IA-32eがリング3であるためNULLの取り扱いは必要とされない
  SS := tempSS;
  RSP := tempRSP;
  GOTO RETURN_FROM_SAME_PRIVLEDGE_LEVEL;

RETURN_TO_OUTER_PRIVLEDGE_LEVEL:
  IF newCPL != 3 THEN
    #GP(tempCS);
  FI
  tempRSP := POP();
  tempSS := POP();
  IF tempRIPがキャノニカルではない THEN
    #GP(0); // RSPを元に戻す
  FI
  CPL := newCPL;
  IF ShadowStackEnabled() THEN
    SDMで説明されているように、通常のシャドウ・スタック操作を実行する;
  FI
  Check_selector(tempSS);
  tempSSdesc := Load_descriptor_from_GDT_LDT(tempSS);
  check_SS_desc_for_IRET(tempSS, tempSSdesc, newCPL);
  CS := tempCS;
  RIP := tempRIP;
  SS := tempSS;
  RSP := tempRSP;
  Save CS.ARbyte
  RFLAGS(CF, PF, AF, ZF, SF, TF, DF, OF, NT, RF, AC, IC) := tempFlags;
  IF CPL == 0 THEN FGLAGS(IF) := tempFlags; FI;
  NMIのマスクを解除する;
END;

4.2.7 JMP Far

FAR JMPはイントラレベル専用です。モードの制限が強制されます。セレクターはGDT/LDT内のコンフォーミング・コードではないディスクリプターを示さなければなりません。CS.accessedビットへのセットは行いません。16ビットのオペランド・サイズを伴う命令は#UD例外となります。32ビット・モードの命令において0x67プリフィクスを伴う場合には#GP(0)となります。

疑似コード:

IF オペランド・サイズは16ビット THEN #UD ; FI

IF 0x67プリフィクスがある AND 32ビット・モード THEN #GP(0); FI
Check_selector(newCS);
newCSdesc := Load_descriptor_from_GDT_LDT(tempCS);
Check_CS_desc(tempCS, newCSdesc, CPL);
IF newRIPはキャノニカルではない THEN
  #GP(0);
FI
CS := newCS;
RIP := newRIP;
Save newCSdesc;
有効にされているならシャドウ・スタックにPUSHする;
有効にされているなら分岐終了状態に遷移する;

4.2.8 LSL、LAR、VERW、VERR

簡素化されたチェックを使用します。LARはアクセス・ビットを常に1とします。

Check_Selector(selector);
// 失敗するのであればZF := 0で返す
Desc := Load_descriptor_from_GDT_LDT(selector);
// 失敗するのであればZF := 0で返す
Check_Data_Desc(selector, Desc, CPL);
// 失敗するのであればZF := 0で返す
// LARは常にAccess = 1で返す
// LSL/LAR/VERW/VERRのフローではディスクリプターからの情報を返す

4.2.9 LDS、LES、LFS、LGS、LSS

Desc.accessedビットは設定しません。簡素化されたチェックを使用します。

疑似コード:

If newSel is NULL AND LSS AND NOT (CPL0 AND CS.L) THEN
  #GP(0);
FI
Check_selector(newSel);
newDesc := Load_descriptor_from_GDT_LDT(newSel);
IF LSS THEN
  Check_SS_desc(newSEL, newDesc);
ELSE
  Check_Data_desc(newSel, newDesc);
FI
Dest(sel) := newSel;
Dest(offset) := offest;
newDescの保存;

4.2.10 LGDT

振る舞いはSDMで説明されているとおりです。

4.2.11 LLDT

ロードするセレクターのビット[2:15]に0がセットされていればLDTのbaseとlimitはクリアとなります。

4.2.12 LIDT

セレクターがNULLの場合にUnusableビットがARバイトに設定されていないことを除いて、SDMで説明されているように振る舞います。代わりにlimitはゼロとなります。それは、NULLのLDTへアクセスするときに、#GPを引き起こすという効果を持っています。

4.2.13 LKGS

後述するセグメント・レジスターへのMOVと同じように、変更されたセレクターのロードをチェックします。

4.2.14 LTR

BUSYビットはチェックされず、メモリーにも設定されていないことを除いて、振る舞いはSDMで説明されているとおりです。

4.2.15 セグメント・レジスターからのMOV

振る舞いはSDMで説明されているとおりです。

4.2.16 セグメント・レジスターへのMOV

簡素化されたチェックを使用します。

If newSel is NULL AND MOV SS AND NOT (CPL0 AND CS.L) THEN
  #GP(0);
FI
Check_selector(newSel);
newDesc := Load_descriptor_from_GDT_LDT(newSel);
IF MOV SS THEN
  Check_SS_desc(newSEL, newDesc);
ELSE
  Check_Data_desc(newSel, newDesc);
Dest(sel) := newSel;
IF SS THEN
  MOV SS命令によるブロック※17;
  ARバイトの保存
FI;

4.2.17 セグメント・レジスターのPOP

簡素化されたチェックを使用します。

IF 64ビット・モードでのPOP DS、POP ES、POP SS THEN
  #UD;
FI
newSel := POP
Check_selector(newSel);
newDesc := Load_descriptor_from_GDT_LDT(newSel);
IF POP SS THEN
  Check_SS_desc(newSEL, newDesc);
ELSE
  Check_Data_desc(newSel, newDesc);
Dest := newSel;
IF SS THEN
  POP SSをしたことによるブロック;
  ARバイトの保存;
FI

4.2.18 POPF

IOPL、VM、VIP、およびVIFフラグは、常にゼロであり、POPFで無視されます。

4.2.19 PUSHセグメント・セレクター

振る舞いはSDMで説明されているとおりです。

4.2.20 PUSHF

振る舞いはSDMで説明されているとおりです。

4.2.21 RDFSBASE、RDGSBASE

振る舞いはSDMで説明されているとおりです。

4.2.22 RET far

Far RETはイントラレベル専用です。セレクターはGDT/LDT内のディスクリプターを指し示さなければなりません。CS.accssedビットはセットしません。16ビット・オペランド・サイズを示す命令は#UD例外を引き起こします。

IF 16ビット・オペランド・サイズである THEN #UD ; FI
newRIP := POP;
newCS := POP;
If newCS is NULL THEN
  #GP(0)
FI
Check_selector(newCS);
newCSdesc := Load_descriptor_from_GDT_LDT(tempCS);
Check_CS_desc(tempCS, newCSdesc, CPL);
IF newRIPはキャノニカルではない THEN
  #GP(0)
FI
CS := newCS;
RIP := newRIP;
newCSdesc.ARbyteを保存する;
有効にされているならシャドウ・スタックを使用する
有効にされているなら分岐終了状態に遷移する

4.2.23 SGDT

振る舞いはSDMで説明されているとおりです。

4.2.24 SLDT

振る舞いはSDMで説明されているとおりです。

4.2.25 SIDT

振る舞いはSDMで説明されているとおりです。

4.2.26 STR

振る舞いはSDMで説明されているとおりです。

4.2.27 SWAPGS

振る舞いはSDMで説明されているとおりです。

4.2.28 SYSCALL

FLAGSの制限を強制する部分を除き、振る舞いはSDMとFRED EAS※18で説明されているとおりです。

4.2.29 SYSENTER

振る舞いはSDMで説明されているとおりです。

4.2.30 SYSEXIT

振る舞いはSDMで説明されているとおりです。

4.2.30 SYSEXIT

振る舞いはSDMで説明されているとおりです。

4.2.31 SYSRET

RFLAGS(R11)のVIF、VIP、またはIOPLが0ではなくフォルトする場合を除き、振る舞いはSDMとFRED EASで説明されているとおりです。

4.2.32 WRFSBASE, WRGSBASE

振る舞いはSDMで説明されているとおりです。

4.2.33 VMEntry

それぞれのCS、SS、DS、ES、FS、GS、TR、およびLDTRフィールドはVMCSゲスト状態からロードされます:

  • TRとLDTR:セレクターにより、baseおよびlimitフィールドをロードします。Gビットは使用しない。limitは常に32ビットとしてロードする。
  • CS: セレクターのフィールドは、アクセス権フィールドのLビットおよびDビットからと同様にロードを行う。DPLはチェックの対象となるが、ロードされない。Dビットは常にNOT Lとなる。それ以外のビットについてはUnusable(使用不可能)を含むARバイトにおける他のビットを無視する。
  • SS, DS, ES, FS, GS: セレクターのフィールドをロードする。SS DPLとBをロードする。FS/GSに関してはbaseをロードする。ARバイトに含まれるDS、ES、FS、GSに対するUnusable(使用不可能)は無視する。

VMEntryはVMCSの以下の条件において不正なゲスト状態を示すアボートのトリガーとなります:

  • CS.L == 0 and CS.D == 0 (16-bit)。
  • CS.L == 1 and CS.D == 1 (不正)。
  • CS.L == 0 and SS.DPL == 0 (32ビットのリング0)。
  • SS.DPL is 1 or 2。
  • SS.RPL != SS.DPL。
  • CS.RPL != SS.DPL。
  • TR.sel.TI != 0 (LDT内にTRがない)。
  • LDTR.sel.TI != 0。
  • LDTRのbaseがキャノニカルではない。
  • SS以外のデータ・セグメントのチェックを行わない。

4.2.34 VMExit

CS、SS、DS、ES、FS、GS、LDTR、GDTR、TRのそれぞれについて:

  • FS/GS/TR/LDTR/IDTR/GDTRのbaseフィールドは保持される。
  • TR/LDTR/IDTR/GDTRのlimitフィールドは保持される。limitは常にGビットが設定されていない状態で常に保持される。
  • CSに関して: Lビットは保存され、DビットにはLビットの反転したものがセットされる。SS.DPLの値がCS.DPLに設定される。フィールドの他のビットは未定義となる。
  • SSに関して: DPLとBビットは保存される。同じフィールドと他のビットについては未定義である。

CS、SS、DS、ES、FS、GS、TR、GDTRについて:

  • ホスト・セレクター・フィールドがロードされる。CS/TRにおいてNULLセレクターをロードする際に検出される失敗を除いて0セレクターによる使用不可能なセレクターの概念は存在しない。
  • FS/GS/TRは、Intel 64のルールに則り、ホストのbaseからロードする。他のbaseは無視する。
  • TRのlimitは0x67に設定する。
  • SS.DPLにはゼロをセットし、SB.Bにもゼロをセットする。

LDTRに対してbaseとlimitはゼロを設定します。GDTRとIDTRに対するbaseへのロード時には、limitへ0xfffffをセットします。

4.2.35 デュアル・モニター・アクティベーションのためのSTMホスト・ステートのロード

CS、SS、DS、ES、FS、GSに対するロードは以下のように行われます:

  • CSセレクターに8を設定する。
  • SS/DS/ES/FS/GSセレクターに16を設定する。
  • FS/GSのbaseアドレスに0を設定する。
  • CS.Lビットを1に設定する。
  • CR4.FREDをクリアする。

4.3 セグメンテーション命令と関連する振る舞いのリスト

表19にセグメンテーション命令と関連する振る舞いのリストを示します。

表19. セグメンテーション命令のリストと関連する振る舞い

命令 振る舞い
SGDT Intel64の振る舞いからの変更はない。
SIDT Intel64の振る舞いからの変更はない。
SLDT Intel64の振る舞いからの変更はない。
STR Intel64の振る舞いからの変更はない。
LGDT Intel64の振る舞いからの変更はない。
LIDT Intel64の振る舞いからの変更はない。
LLDT ディスクリプター0をロードするとbase/limitはクリアされる。
LTR TSS.bustビットをチェックすることはない。
VERR セクション5.1において説明するセグメンテーション設計に従うための変更を行った。
VERW セクション5.1において説明するセグメンテーション設計に従うための変更を行った。
ARPL Intel64の振る舞いからの変更はない。
FAR CALL セクション5.2において説明するセグメンテーション設計に従うための変更を行った。16ビット・オペランドは#UD。32ビット・モードにおける間接を伴う0x67プリフィクスによる#GP。リングを変更することはできない。モード制限を強制する。
FAR JMP セクション5.2において説明するセグメンテーション設計に従うための変更を行った。16ビット・オペランドは#UD。32ビット・モードにおける0x67プリフィクスによる#GP。リングを変更することはできない。
FAR RET セクション5.2において説明するセグメンテーション設計に従うための変更を行った。16ビット・オペランドは#UD。リングを変更することはできない。モード制限を強制する。
IRET イントラリングおよびリング0からリング3への移行のみをサポートする。RFLAGSレジスターに対する制約が強制される。簡易化されたチェックを適用する。
LDS DSにおけるFARポインターのロードは簡易化されたチェックを適用する。
LES ESにおけるFARポインターのロードは簡易化されたチェックを適用する。
LFS FSにおけるFARポインターのロードは簡易化されたチェックを適用する。
LGS GSにおけるFARポインターのロードは簡易化されたチェックを適用する。
LSS SSにおけるFARポインターのロードは簡易化されたチェックを適用する。
LKGS カーネルGS.baseへの代入はセクション5.1で説明したセグメント・チェック規則が適用される。
DSへMOV DSへのロードは簡易化されたチェックを適用する。
ESへMOV ESへのロードは簡易化されたチェックを適用する。
SSへMOV SSへのロードは簡易化されたチェックを適用する。
FSへMOV FSへのロードは簡易化されたチェックを適用する。
GSへMOV GSへのロードは簡易化されたチェックを適用する。
DSからMOV Intel64の振る舞いからの変更はない。
ESからMOV Intel64の振る舞いからの変更はない。
SSからMOV Intel64の振る舞いからの変更はない。
FSからMOV Intel64の振る舞いからの変更はない。
GSからMOV Intel64の振る舞いからの変更はない。
POP DS スタックの先頭からPopしてDSへのロードは簡易化されたチェックを適用する。
POP ES スタックの先頭からPopしてESへのロードは簡易化されたチェックを適用する。
POP SS スタックの先頭からPopしてSSへのロードは簡易化されたチェックを適用する。
POP FS スタックの先頭からPopしてFSへのロードは簡易化されたチェックを適用する。
POP GS スタックの先頭からPopしてGSへのロードは簡易化されたチェックを適用する。
PUSH CS Intel64の振る舞いからの変更はない。
PUSH DS Intel64の振る舞いからの変更はない。
PUSH ES Intel64の振る舞いからの変更はない。
PUSH SS Intel64の振る舞いからの変更はない。
PUSH FS Intel64の振る舞いからの変更はない。
PUSH GS Intel64の振る舞いからの変更はない。
SWAPGS Intel64の振る舞いからの変更はない。
RSM セグメンテーションに対する変更はないが、他のモードとRFLAGSの制限は強制される。
WRFSBASE Intel64の振る舞いからの変更はない。
WRGSBASE Intel64の振る舞いからの変更はない。
RDFSBASE Intel64の振る舞いからの変更はない。
RDGSBASE Intel64の振る舞いからの変更はない。
SYSENTER 16ビット・モードと仮想86モードに入ることはできない。
SYSEXIT 16ビット・モードと仮想86モードに入ることはできない。
SYSCALL RFLAGSに対する制限を強制する。
SYSRET RFLAGSに対する制限を強制する。
ERETU セグメント・チェックのルールが変更される。RFLAGSの制限が強制される。
FRED entry Intel64の振る舞いからの変更はない。
IDT entry セグメント・チェックのルールの変更とFREDによる制限が適用される。

4.4 LEGACY_REDUCED_OS_ISAを伴わない64ビットSIPI

LEGACY_REDUCED_OS_ISAビットによるX86Sシステムに対する互換性を持つように設定しないシステムにおいても、64ビットSIPIを実装することができます。このような場合、IA32_SIPI_ENTRY_STRUCT_PTRまたはSIPI_ENTRY_STRUCT FEATURESビットが有効化されていないのであれば、64ビットSIPIはレガシーINIT/SIPIへと戻る(フォールバックする)ことができます。


まとめ

最初に印刷して読んでみた時よりも、実際に日本語訳を作り始めた時点において、思ったよりも多くの「小さな」変更点があることに気づきました。プロセッサーの設計に関する部分ですから、これらの細かな変化は大変に重要です。いったんは日本語訳を作り終えてから、見逃しがないかの確認を進める工程にだいぶ時間を取られました。それでも文章量が多いので見逃しがあるかもしれません。その場合はお知らせいただければと思います。

今回はRevision 1.1の印刷物「だけ」にペンで書き込みをすることで、Revision 1.0との混同を最低限にする工夫をしました。改変元(Revision 1.0)と改変先(Revision 1.1)の両方の印刷物に書き込みをしてしまうと、それぞれの内容を取り違えたり見逃したりしてしまう可能性がでてきます。ですので「絶対」に改変先の印刷物に対してのみ差分書き込みを徹底することにしました。それでもPDFを画面上で2つ見比べるとなかなか厳しいこともありました。実際に取り違えて手戻りすることもありました。これについては最終的に「原書については印刷したもの以外は見ない」という対応をしました。それくらい細かい変更がいろいろとありました。

これらの変更や、全体を読んでみてどのように「さかきけい」が感じたのかは「分析編」で書いてみたいと思います。それほど長く間をあけずに書くとは思いますが、前回は期日を設定して痛い目を見たので今回は設定しないで置こうと思います。

変更履歴

2024年01月02日

  • 初版

2024年01月04日

  • 第2版
    • 各種誤記の修正を行いました。

  • 有効にしたい場合は原書をご確認ください。
  • インテル株式会社による表現がそうなっているので、それに合わせています。
  • インテル株式会社による表現がそうなっているので、それに合わせています。
  • 質問者の技術レベルに応じて必要な回答を用意するのは、非常に高いスキルと多くの時間を必要とするものです。私はこれらのサービスが可能な状態にはありません。
  • 訳注:翻訳元のホワイト・ペーパーが英語なのでフィードバックも英語であるべきであろうと私は考えますが、もしかすると日本語で送ったとしてもAI技術の専門家でもあり、日本法人もあるIntel Corporationであれば、読まれる可能性もゼロではないかもしれません。
  • 訳注:80386において、80287互換=0、あるいはそれ以降=1であるかを示すビットで、それ以降はFPUがある限り常に1となります。
  • 訳注:原文通りにしていますが、正しくは0x0000280Cです。
  • 訳注:原文通りにしていますが、正しくは0x0000280Eです。
  • 訳注:原文通りにしていますが、正しくは0x00002810です。
  • 訳注:原文通りに記載をしましたが、「1に固定。」が正しいのではないかと思われます。
  • 訳注:A20Mについては現状で廃止されているはずなのにもかかわらず考慮されているようです。
  • 訳注:「N.E.」を「実行不可」と訳しています。
  • 訳注:POPF
  • 訳注:原文通りとしていますが、コンフォーミング・コード・セグメントがサポートされないというのがX86Sの特徴ですから、「非」のつかない「コンフォーミング・コード・セグメント」が正しいです。
  • 訳注:イントラレベルとは特権レベルの変更がないことを意味します。対義語はインターレベルです。
  • 訳注:SS更新後の次の命令の実行後まで割り込みは自動的にブロックされます。これは次の命令でRSP/ESP/SPレジスターが更新されることを前提に、新しいスタック・ポインターが確定するまで割り込みが起こらないようにするための8086からの機能です。
  • 訳注:「Flexible Return and Event Delivery (FRED) Specification」のことを示しているものと思われます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です