以下の内容はhttps://msyksphinz.hatenablog.com/entry/2024/11/19/040000より取得しました。


RISC-V IOMMU の構成についてマニュアルを読んでまとめる (12. IOVA の変換プロセス)

前回:msyksphinz.hatenablog.com

github.com

RISC-V IOMMUの構成について、概略をざっくり理解するためのメモ。

何回か読もうとして挫折してきたので、もう一度ちゃんと読んでみようと思う。


デバイスコンテキストの場所を特定するプロセス

device_idを使ってトランザクションのDevice-contextを見つけるプロセスは以下の通りである:

  1. addtp.PPN x 212 とし、i = LEVELS - 1とする。ddtp.iommu_mode3LVL のとき、LEVELSは3である。ddtp.iommu_mode2LVL のとき、LEVELS は2である。ddtp.iommu_mode1LVL の場合、LEVELS は1である。
  2. もし i == 0 ならステップ8に進む。
  3. ddte をアドレス a + DDI[i] x 8 の8バイトの値とする。 ddteへのアクセスが PMA または PMP チェックに違反するならば、停止して "DDT entry load access fault" (cause = 257) を報告する。
  4. ddte アクセスがデータ破損(poison データ)を検出した場合、停止して"DDTデータ破損"(cause= 268)を報告する。
  5. ddte.V == 0 なら、停止して "DDT entry not valid" (cause = 258) と報告する。
  6. ddte 内に将来の標準使用のために予約されているビットやエンコーディングが設定されている場合、停止して"DDT entry misconfigured" (cause = 259) と報告する。
  7. i = i - 1 とし、a = ddte.PPN x 212 とする。 ステップ2に進む。
  8. DC をアドレス a + DDI[0] * DC_SIZEのDC_SIZE バイトの値とする。もし capabilities.MSI_FLAT が1ならば、 DC_SIZE は64バイトであり、そうでなければ32バイトである。 もしDC へのアクセスがPMAまたはPMPチェックに違反するならば、停止し、"DDT entry load access fault" (cause = 257)を報告する。もしDCのアクセスがデータ破損(毒データ)を検出したら、停止して"DDTデータ破損"(cause=268)を報告する。
  9. DC.tc.V == 0 の場合、停止し、"DDT entry not valid" (cause = 258)と報告する。
  10. DC が ???に概説された規則によって決定されるように誤って設定されている場合、停止して "DDT entry misconfigured" (cause = 259) と報告する。
  11. デバイスコンテキストの位置は正常に特定される。

プロセスコンテキストを見つけるプロセス

device-contextはPDTルートページPPN(pdtp.ppn)を提供する。 DC.iohgatp.modeBare でない場合、 pdtp.PPNpdte.PPN はゲスト物理アドレス(GPA)であり、 DC.iohgatp が指す第2ステージのページ・テーブルを使用して、スーパーバイザ物理アドレス(SPA)に変換されなければならない。 PDTへのメモリ・アクセスは、第2ステージによって暗黙の読み取りメモリ・アクセスとして扱われる。

process_id を使ってトランザクションのProcess-contextを見つける処理は以下の通りである:

  1. apdtp.PPN x 212 とし、i = LEVELS - 1 とする。 pdtp.MODEPD20 のとき、 LEVELS は3である。 pdtp.MODEPD17 のとき、 LEVELS は2つです。 pdtp.MODEPD8 の場合、 LEVELS は1である。
  2. DC.iohgatp.mode != Bare ならば、 a は GPA である。 aを暗黙のメモリアクセスとしてSPAに変換するプロセスを呼び出す。 もしa の第2段アドレス変換中にフォルトが発生したら、第2段アドレス変換プロセスによって検出されたフォルトを停止して報告する。変換された a は以降のステップで使用される。
  3. もし i == 0 ならステップ9に進む。
  4. pdte をアドレス a + PDI[i] x 8 の8バイトの値とする。 pdteへのアクセスが PMA または PMP チェックに違反するならば、停止して"PDT entry load access fault" (cause = 265) を報告する。
  5. もし pdte アクセスがデータ破損(poisonデータ)を検出したなら、停止して "PDTデータ破損"(cause=269)を報告する。
  6. pdte.V == 0 の場合、停止して "PDT entry not valid"(cause=266)と報告する。
  7. pdte 内に将来の標準使用のために予約されているビットやエンコーディングが設定されている場合、停止して"PDT entry misconfigured" (cause = 267) と報告する。
  8. i = i - 1 とし、 a = pdte.PPN x 212 とする。 ステップ2に進む。
  9. PC をアドレス a + PDI[0] x 16 の16バイトの値とする。 PC へのアクセスが PMA または PMP チェックに違反するならば、停止して"PDT entry load access fault" (cause = 265) を報告する。もしPCアクセスがデータ破損(poisonデータ)を検出するならば、停止して"PDTデータ破損"(cause=269)を報告する。
  10. PC.ta.V == 0 の場合、停止し、"PDT entry not valid" (cause = 266)と報告する。
  11. PC が誤って設定されている場合、停止して"PDT entry misconfigured"(cause=267)と報告する。
  12. プロセス・コンテキストの位置が正常に特定される。

MSI のアドレスを変換するプロセス

I/OデバイスがゲストOSによって直接設定される場合、デバイスからのMSIは、ゲストOSの仮想マシン内の仮想IMSICをターゲットとし、実マシンには不適切で安全でないゲスト物理アドレスを使用することが予想される。 IOMMUは、そのようなデバイスからの特定の着信書き込みをMSIとして認識し、実マシン用に必要に応じて変換しなければならない。

変換を必要とする1つのデバイスから発信されるMSIは、1つのRISC-V仮想マシン内で実行される1つのゲストOSによってデバイスに設定されていることが期待される。 VM自体がRISC-V Advanced Interrupt Architectureに準拠していると仮定すると、MSIは仮想IMSICの割り込みファイルのメモリ・マップされたレジスタに書き込むことで、VM内の仮想HARTに送信される。 これらの仮想割り込みファイルはそれぞれ、VMのゲスト物理アドレス空間内の個別の4KiBページを占有する。 このため、ゲスト物理アドレスへの書き込みが、VM内の仮想IMSICの割り込みファイルによって占有されているページへの書き込みであれば、仮想HARTへのMSIとして認識することができる。

MSI アドレス変換がサポートされている場合 (capabilities.MSI_FLAT, [CAP]) 、入力された IOVA を仮想割り込みファイルのアドレスとして識別し、MSI ページテーブルを使用してアドレスを変換するプロセスは次のようになる:

  1. AGPA とする。
  2. DC を Process to locate the Device-context に概説されているプロセスを使用してデバイスの device_idを使用して見つけられたデバイスコンテキストとする。
  3. アドレス AがMSIアドレスマスク(msi_addr_mask)とパターン(msi_addr_pattern)で指定された仮想割り込みファイルへのアクセスかどうかを判断する。
  4. もしアドレスが仮想割り込みファイルのものであると判断されなかった場合は、この処理を停止し、代わりにアドレス変換を行うために通常の変換データ構造を使用する。
  5. A から割り込みファイル番号 II = extract(A >> 12, DC.msi_addr_mask) として抽出する。ビット抽出関数 extract(x, y) は、マスク x の同じ位置にある一致するビットがゼロである y からのすべてのビットを破棄する、 そして、 x からの残りのビットを、x と同じビット順序を保ちながら、結果の最下位端で連続的にパックし、結果の最上位端にある他のビットをゼロで埋める。例えば、 xy のビットが次のような場合:
    1. x = a b c d e f g h
    2. y = 1 0 1 0 0 1 1 0
    3. とすると、 extract(x, y) の値はビット 0 0 0 a c f g を持つ。
  6. m(DC.msiptp.PPN x 2^12) とする。
  7. msipte をアドレス (m|(I×16)) の16バイトの値とする。` msipt`eへのアクセスが PMA または PMP チェックに違反する場合、停止して "MSI PTE load access fault" (cause = 261) を報告する。
  8. msipte アクセスがデータ破損 (毒データ) を検出した場合、停止して "MSI PT データ破損" (cause = 270) を報告する。
  9. msipte.V == 0 の場合、停止して "MSI PTE not valid"(cause = 262)と報告する。
  10. msipte.C == 1 の場合、PTEを解釈するためのさらなる処理は実装で定義されている。
  11. msipte.C == 0 の場合、処理は以降のステップで概説される。
  12. msipte.M == 0 またはmsipte.M == 2の場合、停止し、"MSI PTE misconfigured" (cause = 263)を報告する。
  13. msipte.M == 3 の場合、PTEは基本トランスレートモードであり、トランスレート処理は以下のようになる:
  14. msipte 内に将来の標準使用のために予約されているビットまたはエンコーディングが設定されている場合、停止し、"MSI PTE misconfigured" (cause = 263)と報告する。
  15. msipte.PPN << 12 | A[11:0] として変換されたアドレスを計算する。
  16. msipte.M == 1 の場合、PTEはMRIFモードであり、変換処理は以下のようになる:
    1. capabilities.MSI_MRIF == 0 の場合、停止し、"MSI PTE misconfigured" (cause = 263) と報告する。
    2. msipte 内に将来の標準使用のために予約されているビットまたはエンコーディングが設定されている場合、停止して "MSI PTE misconfigured" (cause = 263) を報告する。
    3. 宛先MRIFのアドレスは msipte.MRIF_Address[55:9] * 512 である。
    4. 通知MSIの宛先アドレスは msipte.NPPN << 12 である。
    5. NID(msipte.N10 << 10) | msipte.N[9:0] とする。 通知MSIのデータ値は11ビットの NID 値をゼロ拡張して32ビットにしたものです。
  17. このプロセスによって決定される変換に関連するアクセス許可は、R=W=U=1 および X=0 を持つ通常のRISC-VセカンドステージPTEと同等である。 セカンドステージPTEと同様に、U ビットをチェックするとき、トランザクションはスーパーバイザ特権を要求していないものとして扱われる。
  18. トランザクションが未変更または変更された実行読み出しの場合は、停止して「命令アクセス・フォールト」(cause = 1)を報告する。
  19. MSI アドレス変換処理は完了する。

MRIF モードでは、Advanced Interrupt Architecture Specification に、受信 MSI を宛先 MRIF に格納し、通知 MSI を生成する動作が定義されている。 これらの動作はIOMMU自身が実行してもよいし、IOMMUが変換要求に応答してデスティネーションMRIFアドレス、通知MSIアドレス、通知MSIデータ値をI/Oブリッジに提供し、I/Oブリッジがその動作を実行してもよい。




以上の内容はhttps://msyksphinz.hatenablog.com/entry/2024/11/19/040000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14