🔲

ARM Cortex-R52の仮想化関連について調べる

2024/06/02に公開

はじめに

仮想化技術といえば以前はPCや大きめのサーバで主に使われてましたが、最近は組み込みシステムでもARMのCortex-R52系統やルネサスのマイコンの仮想化支援機構を利用して使われ始めています。低レイヤが好きな自分としてはどこかで勉強したいなと思いながらもちょうどいい題材が見つかりませんでしたがたまたまARMのCortex-R52に関するちょうどいい資料(参考資料)を見つけました。なので訳しながらまとめた結果をここに展開します。

参考資料

全体の流れ

Cortex-R52の仮想化支援機構について

ここではCortex-R52が仮想化を実現するための機構(仮想化支援機構)について解説したいと思います。

Exception Level 2

  • EL0(user、アプリが動作するレベル)やEL1(supervisor、OSが動作するレベル)よりも高い特権
    この特権があることによりハイパーバイザーが成立します。
  • Cortex-R52はこのレベルで起動します。
    • ハイパーバイザーを積まない場合はすぐにEL1に落とします。
    • ハイパーバイザーを積んでいる場合はシステムレジスタの設定等を行った後にEL1に落とします。
  • Armv8-R virtualizationによればハイパーバイザーを積まない場合、その特権を生かして以下のようなことをやらせている場合もあるようです。
    • オンラインおよびオフラインのBuilt-In-Self-Test(BIST)ソフトウェアの実行
    • RAMスクラビングの実行
    • 安全イベントの処理
    • 必要に応じたRTOSのリブート
    • ファームウェアアップデートの処理
    • ハードウェア・セキュリティ・モジュール(HSM)による認証

Hypervisor Call(HVC)

  • EL1時にこの命令を呼ぶことでEL2に遷移し、Hyp-mode entry exceptionが生成します。
    • ハイパーバイザーがこの例外を処理した後は元通りGuest OSのEL1に遷移します。
  • 準仮想化を実現する上でキーとなる命令です。また、Exception Level 2(EL2)に記載の通り、ハイパーバイザーを積まずなおかつEL2を利用する方式でも上位のVMに提供するAPIでこの命令を呼び出すことでEL2に遷移させることができます。

Two Levels of MPU

  • Cortex-AのMMUと同様に2段階のMPUが存在します。
  • EL1-controlled-MPU
    • EL1またはEL2が設定可能なMPUです。
    • これを使うことでOSとアプリケーションタスク/ISR間、またはアプリケーションタスク/ISR-アプリケーションタスク/ISR間を分離することが可能です。
    • 参考資料
  • EL2-controlled-MPU
    • EL2のみが設定可能なMPUです。
    • これによりハイパーバイザー-それ以外(Guest OS、アプリケーションタスク/ISR)間を分離することが可能です。
    • 参考資料
  • アプリケーションタスクがあるメモリにアクセスする際はまずEL1-controlled-MPUにおける設定を参照しそこでアクセス可能であればEL2-controlled-MPUで同様の操作を行います。ある領域のアクセス権限はEL1-controlled-MPUとEL2-controlled-MPUの内の厳しい方に従います。
  • EL1またはEl0で実行中のGuestソフトウェアがEL2-controlled-MPUで禁止されている領域にメモリアクセスを行うとCortex-R52プロセッサはEL2に切り替え、Hyp-mode entry exceptionを生成します。

Peripheral Protection mechanisms & System Memory Protection Unit(SMPU)

Peripheral Protection mechanisms

  • Best Practices for Armv8-R Cortex-R52+ Software ConsolidationではperipheralをバスマネージャーまたはVMに割り当て、ほかのバスマネージャーまたはVMがあるperipheralのレジスタにアクセスすることを禁止するものと説明しています。
  • おそらく各SoCごとに存在するペリフェラルガード的な機構と思われます。

System Memory Protection Unit(SMPU)

  • どのバスマネージャーがどのメモリアドレスにアクセスできるかを制御するものを示します。
    • Cortex-R/Mコアや一部ペリフェラルもバスマネージャーになることが可能です。
    • Cortex-AでいうところのSMMUに相当するものと思われます。
  • 各領域について
    • 設定可能の開始アドレスとサイズを持ち、1つまたは複数のバスマネージャーが割り当てられます。
    • 高度な設計をしている場合、Cortex-R52のVSCTLR.VMIDレジスタに格納されたVM識別子を使用して1つまたは複数のVMに割り当てられます。
  • バスマネージャー(またはVM)はそのバスマネージャーに割り当てられた領域内のメモリのみアクセス可能です。

Virtual Machine ID(VMID)

  • ハイパーバイザーが割り当てるGuest OSを識別するためのものです。
  • IDがバスにエクスポートされると、周辺機器へのアクセスをフィルタリングするために使用可能です。
    • この保護はデバイス単位またはレジスタ単位で外部のSMPUで実現します。
    • SMPUはVMIDに基づいてアクセスをフィルタリングします。
  • 値自体はVSCTRL内に格納します。
  • ARM提供のハイパーバイザーのサンプルソースの 「Guest OS switcher with virtual interrupts example」ではハイパーバイザーのResetハンドラー内のinit_guest_osという関数の中でGuest OSごとにVMIDを書き込んでいます。
hyp_start.s
initializeGuestOSsAndStartTimers:

    // ** Initialize the guest OSs

    // Initialize guest OS 2 
    LDR      r0, =GUEST_OS2_EL1_Vectors  // Guest OS 2 code starting point.
    LDR      r1, =guest_os2              // Data structure to back up registers in.
    LDR      r2, =GUEST_OS2_ID
    BL       init_guest_os
    DSB
    ISB

    // Initialize guest OS 1
    LDR      r0, =GUEST_OS1_EL1_Vectors  // Guest OS 1 code starting point
    LDR      r1, =guest_os1              // Data structure to back up registers in.
    LDR      r2, =GUEST_OS1_ID
    BL       init_guest_os
    DSB
    ISB
hyp_start.s

// This function expects r0, r1 and r2 to be set as follows:
// r0: The point the code should start from when the guest OS first runs.
// r1: The address of the data structure to back the registers up in.
// r2: The ID of the virtual machine running the guest OS.
.global init_guest_os
.type init_guest_os, "function"
init_guest_os:

    // ELR_HYP
    STR      r0, [r1, #140]
    MSR      ELR_HYP, r0

    // SPSR_HYP
    MRS     r5, cpsr
    MOV     r6, #Mode_SVC
    BFI     r5, r6, #0, #5
    STR     r5, [r1, #144]
    MSR     SPSR_HYP, r5

    // VSCTLR - Virtual Machine ID
    MRC p15, 4, r5, c2, c0, 0
    MOV r6, r2, LSL #16         // Move ID into bits 16-23.
    AND r5, r5, #0xFF00FFFF
    ORR r5, r5, r6
    MCR p15, 4, r5, c2, c0, 0   // Write back to VSCTLR.
    STR     r5, [r1, #196]

Hyp Configuration Register(HCR)

  • 様々な命令がEL2でトラップされているかどうかが定義されていることを含む仮想化関連の設定を行うためのレジスタです。
    • FMO/IMOを1にセットすることでEL1/EL0のFIQ/IRQをEL2でトラップできるようになる。
    • HCDを1にセットすることでHVCを無効化することができる。

Hypervisor Control System Registers

Interrupt Controller Hyp Control Register

  • このレジスタを用いることでGuest OSの実行環境を設定することができます。

Cortex-R52での仮想化を構成する要素技術の実現方式

Trap-and-emulate

  • Two-Levels-of-MPUを利用して実現します。
  • Two-Levels-of-MPUの項でも説明した通り、EL1またはEl0で実行中のGuestソフトウェアがEL2-controlled-MPUで禁止されている領域にメモリアクセスを行うとCortex-R52プロセッサはEL2に切り替え、Hyp-mode entry exceptionを生成します。Guestソフトウェアがレジスタを処理していた場合も例外発生後にハイパーバイザーがHyp Syndrome Registerで例外が発生した原因を突き止めHyp Data Fault Address Registerで例外が発生した際にアクセスされたメモリアクセスを調べGuestソフトウェアが度のレジスタ読み書きしていたか把握しそのレジスタへのアクセスを自らエミュレートするかまたはEL2デバイスドライバに委任するという一連の動作ができます。

Interrupt Virtualization

  • Hyp Configuration Register(HCR)Hypervisor Control System Registersを用いることで実現できます。
  • Hyp Configuration Register(HCR)のIMOとHypervisor Control System Registersの中のICH_HCRのENを設定することで、FIQまたはIRQが発生すると常にEL2に切り替わりEL2ベクターテーブルを使用してFIQまたはIRQ割り込みを取ることができます。ハイパーバイザは割り込みを処理するか、割り込みを仮想化し、ゲストソフトウェアがEL1/EL0で実行されるときにEL1ベクタテーブルを使用してEL1で仮想割り込みを処理します。
  • Guestソフトウェアにとって、仮想割り込みは実際の割り込みと区別がつきません。Guestソフトウェア割り込みを無効にしたり、プライオリティ・マスク・レジスタの値を変更したりすると、ゲストのVMにルーティングされた仮想割り込みだけが影響を受け、EL2で取り込まれる実割り込みは影響を受けません。そのため、ゲストソフトウェアはハイパーバイザーによって実行される割り込みを止めることはできません。

  • すべての割り込みは最初にハイパーバイザーによって処理されるため、ハイパーバイザーは割り込みをハイパーバイザー自体で処理するか、EL2デバイスドライバで処理するか、仮想化してVMに注入するかを決定できます。これにより、割り込み駆動の共有/仮想ペリフェラルを処理することができます。EL2デバイスドライバは、必要に応じて仮想割り込みをVMに注入することもできます。

Virtual Processor Cores

  • 割り込みの仮想化を利用して、仮想プロセッサ・コアをサポートすることもできる。
    • 例えば、タイマー割り込みをハイパーバイザーで処理し、仮想コア間のコンテキスト切り替えタイミングを決定する仮想コアスケジューラを駆動するために使用することができます。GuestソフトウェアはEL2での割り込みをブロックできないため、壊れたり悪意のあるGuestソフトウェアが他のGuestソフトウェアのプロセッサ時間を拒否することはできません。現在実行されていない仮想コアに到着した割り込みは仮想化され、ソフトウェアでキューに入れられ、次に実行されるときに仮想コアに注入されます。
  • 仮想コアの切り替えには、EL2 MPUの再プログラミングが必要になることが多い。また、コプロセッサ14および15のコンフィギュレーション・レジスタ(これらのレジスタは、エンディアンの有無、キャッシュの有効/無効、EL1 MPUの有効/無効など、プロセッサのさまざまな側面を設定するために使用されます)にも注意が必要です。これらのレジスタの中には、物理コア上のすべての仮想コアやハイパーバイザーに影響を与える可能性がある形で物理コアに影響を与えるものがあります。その他のレジスタは、EL1 MPU リージョン・レジスタのように、仮想コアに固有の影響を及ぼす可能性があります。後者のカテゴリのレジスタは、仮想コアのコンテキストの一部である必要があります。前者のカテゴリのレジスタについては、アクセス時にEL2でHyp-mode Entry例外を生成するようにCortex-R52を構成できます。ハイパーバイザーは、何らかの方法でこれらのレジスタへのアクセスをエミュレートできます。

  • 複数の仮想コアを1つの物理コアでホストする場合、仮想コアのスケジューリング方法を考慮する必要があります。

Discussion