ARM 仮想汎用割り込みコントローラ v3 以降 (VGICv3)
- 対応するデバイスタイプ:
KVM_DEV_TYPE_ARM_VGIC_V3 ARM Generic Interrupt Controller v3.0
この API でインスタンス化できる VGIC は 1 つだけである。作成された VGIC は VM の割り込みコントローラとして動作する。したがって、エミュレートされた ユーザ空間のデバイスは、CPU に直接ではなく VGIC に割り込みを注入する必要がある。 同じ VM 上で GICv3 と GICv2 の両方を作成することはできない。
ゲストの GICv3 デバイスを作成するには、GICv3 のホスト、または FEAT_GCIE_LEGACY をサポートする GICv5 のホストが必要である。
- Groups:
- KVM_DEV_ARM_VGIC_GRP_ADDR
Attributes:
- KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
ゲスト物理アドレス空間における GICv3 ディストリビュータのレジスタ マッピングのベースアドレス。KVM_DEV_TYPE_ARM_VGIC_V3 でのみ有効である。 このアドレスは 64K に整列されている必要があり、領域は 64K バイトを占める。
- KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
ゲスト物理アドレス空間における GICv3 リディストリビュータのレジスタ マッピングのベースアドレス。vCPU ごとに 2 つの 64K ページがあり、 リディストリビュータのページはすべて連続している。 KVM_DEV_TYPE_ARM_VGIC_V3 でのみ有効である。 このアドレスは 64K に整列されている必要がある。
- KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION (rw, 64-bit)
kvm_device_attr.addr が指す属性データは __u64 の値である:
bits: | 63 .... 52 | 51 .... 16 | 15 - 12 |11 - 0 values: | count | base | flags | index
index はリディストリビュータ領域の一意なインデックスを表す
flags: 将来の使用のために予約済みで、現在は 0
base フィールドは、領域内の最初のリディストリビュータのゲスト物理 ベースアドレスのビット [51:16] を表す
count は領域内のリディストリビュータの数を表す。0 より大きい 必要がある
領域内の各リディストリビュータには 2 つの 64K ページがあり、 リディストリビュータは領域内で連続して配置される。領域はインデックスの 順にリディストリビュータで埋められる。すべての領域の count フィールドの 合計は、vCPU の数以上でなければならない。リディストリビュータ領域は インデックス 0 から始めて、昇順に登録しなければならない。
特定のリディストリビュータ領域の特性は、attr データの index フィールドを あらかじめ設定しておくことで読み出せる。 KVM_DEV_TYPE_ARM_VGIC_V3 でのみ有効である。
KVM_VGIC_V3_ADDR_TYPE_REDIST と KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION 属性の呼び出しを混在させるのは無効である。
再現性のある結果が得られるようにするには(保存・復元の操作をまたいで同じ vCPU が同じリディストリビュータに対応づけられるようにするには)、vCPU の 作成順、リディストリビュータ領域の作成順、および vCPU と領域の作成の 交互の順序を保たなければならない。どちらの順序を変えても vcpu_id と リディストリビュータの対応が変わりうる。その結果、復元時に VM の実行に 失敗する。
Errors:
-E2BIG
アドレスがアドレス指定可能な IPA の範囲外である
-EINVAL
アドレスの整列が不正、リディストリビュータ領域の count/index が 不正、リディストリビュータ領域の属性の使い方が混在している
-EEXIST
アドレスがすでに設定されている
-ENOENT
存在しないリディストリビュータ領域の特性を読み出そうとした
-ENXIO
このデバイスではグループまたは属性が不明かサポートされていない、 またはハードウェアのサポートがない
-EFAULT
attr->addr のユーザポインタが不正である
-EBUSY
初期化後に読み出し専用となるレジスタに書き込もうとした
- KVM_DEV_ARM_VGIC_GRP_DIST_REGS, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
Attributes:
kvm_device_attr の attr フィールドは 2 つの値をエンコードする:
bits: | 63 .... 32 | 31 .... 0 | values: | mpidr | offset |
ディストリビュータのレジスタはすべて (rw, 32-bit) であり、 kvm_device_attr.addr は __u32 の値を指す。64 ビットレジスタに アクセスするには、下位ワードと上位ワードに分けてアクセスしなければ ならない。
読み出し専用レジスタへの書き込みはカーネルによって無視される。
KVM_DEV_ARM_VGIC_GRP_DIST_REGS はメインのディストリビュータレジスタに アクセスする。KVM_DEV_ARM_VGIC_GRP_REDIST_REGS は mpidr で指定された CPU のリディストリビュータにアクセスする。
offset は GICv3/4 仕様で定義されている「[Re]Distributor ベース アドレス」からの相対値である。このようなレジスタの取得または設定は、 実ハードウェア上でそのレジスタを読み書きするのと同じ効果を持つ。 ただし、GICD_STATUSR、GICR_STATUSR、GICD_ISPENDR、GICR_ISPENDR0、 GICD_ICPENDR、GICR_ICPENDR0 は除く。これらのレジスタは、ソフトウェアが VGIC の内部状態を完全に把握できるようにするため、このインタフェース 経由でアクセスしたときはアーキテクチャで定義された動作とは異なる 振る舞いをする。
mpidr フィールドは、どのリディストリビュータにアクセスするかを指定する ために使う。ディストリビュータでは mpidr は無視される。
mpidr のエンコーディングは、アーキテクチャで定義された MPIDR の アフィニティ情報に基づいており、フィールドは次のように エンコードされる:
| 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 | | Aff3 | Aff2 | Aff1 | Aff0 |
ディストリビュータのフィールドはバンク化されておらず、レジスタへの アクセスに使った mpidr に関係なく同じ値を返す。
ユーザ空間は、VGIC を初期化する前に、次のレジスタフィールドに 書き込んでよい。
GICD_IIDR.Revision
GICD_TYPER2.nASSGIcap
GICD_IIDR.Revision は、ゲストまたはユーザ空間から直接観測できる形で KVM の実装が変更されたときに更新される。ユーザ空間は KVM から GICD_IIDR を読み出し、読み出した値を書き戻して、期待する動作が KVM の 実装と一致しているかを確認すべきである。期待どおりの動作を得るには、 ユーザ空間は他のどのレジスタを設定するよりも前に GICD_IIDR を 設定すべきである。
GICD_TYPER2.nASSGIcap を使うと、ユーザ空間はアクティブ状態を持たない SGI のサポートを制御できる。VGIC の作成時にこのフィールドはシステムの 最大ケイパビリティにリセットされる。ユーザ空間は、このフィールドに 書き込む前に、サポートされる値を調べるためにフィールドを読み出すことが 期待される。
GICD_STATUSR レジスタと GICR_STATUSR レジスタは、クリアされたビットへの 書き込みは効果がなく、セットされたビットへの書き込みはその値をクリアする、 とアーキテクチャで定義されている。ユーザ空間がこれら 2 つのレジスタの 値を自由に設定できるようにするため、これら 2 つのレジスタのオフセットで 属性を設定すると、予約済みでないビットが単に書き込んだ値に設定される。
GICD_ISPENDR レジスタ領域および GICR_ISPENDR0 レジスタへのアクセス (読み出しと書き込み)は、割り込みのラッチされたペンディング状態の値を 取得または設定する。
これは、エッジトリガ割り込みについてゲストが ISPENDR から読み出した値と 同じであるが、レベルトリガ割り込みでは異なることがある。エッジトリガ 割り込みでは、割り込みがペンディングになると(入力線でエッジが検出された ためでも、ゲストが ISPENDR に書き込んだためでも)、この状態は 「ラッチ」され、割り込みがアクティブ化されたとき、またはゲストが ICPENDR に書き込んだときにだけクリアされる。レベルトリガ割り込みは、 デバイスによってレベル入力がハイに保たれているため、またはゲストが ISPENDR レジスタに書き込んだためにペンディングになることがある。 ラッチされるのは ISPENDR への書き込みだけである。デバイスが線の レベルを下げると、ゲストが ISPENDR にも書き込んでいない限り、割り込みは ペンディングでなくなる。逆に、線のレベルがハイに保たれている間は、 ICPENDR への書き込みや割り込みのアクティブ化によってペンディング状態が クリアされることはない。(これらの規則は GICv3 仕様の ICPENDR レジスタと ISPENDR レジスタの説明に記載されている。)レベルトリガ 割り込みでは、ここでアクセスする値は ISPENDR でセットされ ICPENDR または割り込みのアクティブ化でクリアされるラッチの値であり、ゲストが ISPENDR から読み出した値はラッチの値と入力線のレベルの論理和である。
ラッチ状態への生のアクセスがユーザ空間に提供される。これは、GIC の 内部状態全体(現在の入力線のレベルとラッチ状態の組み合わせで定義され、 線のレベルと ISPENDR レジスタの値だけからは推測できない)を保存・復元 できるようにするためである。
GICD_ICPENDR レジスタ領域および GICR_ICPENDR0 レジスタへのアクセスは RAZ/WI セマンティクスを持ち、読み出しは常に 0 を返し、書き込みは常に 無視される。
Errors:
-ENXIO
このレジスタの取得または設定はまだサポートされていない
-EBUSY
1 つ以上の vCPU が実行中である
- KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS
Attributes:
kvm_device_attr の attr フィールドは 2 つの値をエンコードする:
bits: | 63 .... 32 | 31 .... 16 | 15 .... 0 | values: | mpidr | RES | instr |
mpidr フィールドは、アーキテクチャで定義された MPIDR のアフィニティ 情報に基づいて CPU ID をエンコードし、フィールドは次のように エンコードされる:
| 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 | | Aff3 | Aff2 | Aff1 | Aff0 |
instr フィールドは、システムレジスタアクセス用の A64 命令セット エンコーディングで定義されたフィールドに基づいて、アクセスする システムレジスタをエンコードする(RES は将来の使用のために予約済みの ビットで、0 であるべきである):
| 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 | | Op 0 | Op1 | CRn | CRm | Op2 |
この API を通じてアクセスするシステムレジスタはすべて (rw, 64-bit) であり、kvm_device_attr.addr は __u64 の値を指す。
KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS は、mpidr フィールドで指定された CPU の CPU インタフェースレジスタにアクセスする。
利用できるレジスタは次のとおりである:
ICC_PMR_EL1
ICC_BPR0_EL1
ICC_AP0R0_EL1
ICC_AP0R1_EL1
ホストが優先度を 6 ビット以上実装している場合
ICC_AP0R2_EL1
ホストが優先度を 7 ビット実装している場合
ICC_AP0R3_EL1
ホストが優先度を 7 ビット実装している場合
ICC_AP1R0_EL1
ICC_AP1R1_EL1
ホストが優先度を 6 ビット以上実装している場合
ICC_AP1R2_EL1
ホストが優先度を 7 ビット実装している場合
ICC_AP1R3_EL1
ホストが優先度を 7 ビット実装している場合
ICC_BPR1_EL1
ICC_CTLR_EL1
ICC_SRE_EL1
ICC_IGRPEN0_EL1
ICC_IGRPEN1_EL1
ゲストで EL2 が利用できる場合、次のレジスタも利用できる:
ICH_AP0R0_EL2
ICH_AP0R1_EL2
ホストが優先度を 6 ビット以上実装している場合
ICH_AP0R2_EL2
ホストが優先度を 7 ビット実装している場合
ICH_AP0R3_EL2
ホストが優先度を 7 ビット実装している場合
ICH_AP1R0_EL2
ICH_AP1R1_EL2
ホストが優先度を 6 ビット以上実装している場合
ICH_AP1R2_EL2
ホストが優先度を 7 ビット実装している場合
ICH_AP1R3_EL2
ホストが優先度を 7 ビット実装している場合
ICH_HCR_EL2
ICC_SRE_EL2
ICH_VTR_EL2
ICH_VMCR_EL2
ICH_LR0_EL2
ICH_LR1_EL2
ICH_LR2_EL2
ICH_LR3_EL2
ICH_LR4_EL2
ICH_LR5_EL2
ICH_LR6_EL2
ICH_LR7_EL2
ICH_LR8_EL2
ICH_LR9_EL2
ICH_LR10_EL2
ICH_LR11_EL2
ICH_LR12_EL2
ICH_LR13_EL2
ICH_LR14_EL2
ICH_LR15_EL2
CPU インタフェースレジスタは AArch64 エンコーディングでのみ記述する。
Errors:
-ENXIO
このレジスタの取得または設定はサポートされていない
-EBUSY
vCPU が実行中である
-EINVAL
指定された mpidr またはレジスタ値が不正である
- KVM_DEV_ARM_VGIC_GRP_NR_IRQS
Attributes:
この GIC インスタンスの割り込み(SGI、PPI、SPI)の数を表す値で、64 から 1024 まで 32 刻みの範囲である。
kvm_device_attr.addr は __u32 の値を指す。
Errors:
-EINVAL
設定された値が想定範囲外である
-EBUSY
値はすでに設定されている。
- KVM_DEV_ARM_VGIC_GRP_CTRL
Attributes:
- KVM_DEV_ARM_VGIC_CTRL_INIT
VGIC の初期化を要求する。kvm_device_attr.addr に追加のパラメータはない。 すべての vCPU を作成した後に呼び出さなければならない。
- KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES
すべての LPI ペンディングビットをゲスト RAM のペンディングテーブルに 保存する。
ペンディングテーブルの先頭 1 kB は、この操作では変更されない。
Errors:
-ENXIO
この属性を呼び出す前に VGIC が必要に応じて正しく設定されていない
-ENODEV
オンラインの vCPU がない
-ENOMEM
vgic の内部データを割り当てるときにメモリが不足した
-EFAULT
ゲスト RAM へのアクセスが不正である
-EBUSY
1 つ以上の vCPU が実行中である
- KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
Attributes:
kvm_device_attr の attr フィールドは次の値をエンコードする:
bits: | 63 .... 32 | 31 .... 10 | 9 .... 0 | values: | mpidr | info | vINTID |
vINTID は、どの IRQ の集合について報告するかを指定する。
info フィールドは、ユーザ空間がこのインタフェースを使って取得または設定 したい情報を指定する。現在、次の info 値をサポートしている:
- VGIC_LEVEL_INFO_LINE_LEVEL:
連続する 32 個の番号の割り込みについて、IRQ 線の入力レベルを 取得または設定する。
vINTID は 32 の倍数でなければならない。
kvm_device_attr.addr は __u32 の値を指し、その値にはビットマップが 入る。セットされたビットは割り込みレベルがアサートされていることを 意味する。
Bit[n] は割り込み vINTID + n の状態を表す。
SGI と、サポートされる割り込み数を超える ID を持つ割り込みは RAZ/WI と なる。LPI は常にエッジトリガであり、したがってこのインタフェースでは サポートされない。
PPI は mpidr フィールドで指定された vCPU ごとに報告され、SPI は指定された mpidr に関係なく同じ値で報告される。
mpidr フィールドは、アーキテクチャで定義された MPIDR のアフィニティ 情報に基づいて CPU ID をエンコードし、フィールドは次のように エンコードされる:
| 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 | | Aff3 | Aff2 | Aff1 | Aff0 |
- Errors:
-EINVAL
vINTID が 32 の倍数でない、または info フィールドが VGIC_LEVEL_INFO_LINE_LEVEL でない
- KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ
Attributes:
kvm_device_attr の attr フィールドは次の値をエンコードする:
bits: | 31 .... 5 | 4 .... 0 | values: | RES0 | vINTID |
vINTID は、vGIC がメンテナンス割り込みを生成しなければならないときに 生成する割り込みを指定する。これは PPI でなければならない。