カーネルと HYP の間の内部 ABI
このファイルは、Linux をハイパーバイザとして実行するとき(たとえば KVM)の、 Linux カーネルとハイパーバイザ層の間のやり取りを記述する。カーネルをゲスト として実行するとき(Xen、KVM などのハイパーバイザの下)のカーネルと ハイパーバイザのやり取りや、カーネルをホストとして使うときのハイパーバイザ 固有のやり取りは対象としない。
注: KVM/arm はカーネルから削除された。ただし、ここで説明する API は今も 有効である。HYP で起動したときにカーネルが kexec できるようにするためだ。 必要なら KVM 以外のハイパーバイザも使える。
arm と arm64(VHE なし)では、カーネルはハイパーバイザモードで動作しないが、 それでもハイパーバイザとやり取りする必要がある。組み込みのハイパーバイザを インストールしたり破棄したりできるようにするためである。
そのために、カーネルは HYP(arm)または EL2(arm64)で起動しなければならない。 そうすることで、SVC/EL1 へ落ちる前に一連のスタブをインストールできる。これらの スタブには 'hvc #0' 命令でアクセスでき、個々の CPU に対してのみ作用する。
別途指定がない限り、組み込みのハイパーバイザはこれらの関数を実装しなければ ならない(arch/arm{,64}/include/asm/virt.h を参照):
r0/x0 = HVC_SET_VECTORS r1/x1 = vectors
'vectors' を HVBAR/VBAR_EL2 に設定してハイパーバイザを有効にする。 'vectors' は物理アドレスでなければならず、アーキテクチャのアラインメント 要件を満たす必要がある。初期スタブだけが実装し、Linux ハイパーバイザは 実装しない。
r0/x0 = HVC_RESET_VECTORS
HYP/EL2 の MMU をオフにし、HVBAR/VBAR_EL2 を初期スタブの例外ベクタ値に 戻す。これで既存のハイパーバイザは事実上無効になる。
r0/x0 = HVC_SOFT_RESTART r1/x1 = restart address x2 = x0's value when entering the next payload (arm64) x3 = x1's value when entering the next payload (arm64) x4 = x2's value when entering the next payload (arm64)
すべての例外をマスクし、MMU を無効にし、I+D ビットをクリアし、引数を 所定の位置に移して(arm64 のみ)、HYP/EL2 のまま再起動アドレスへ ジャンプする。このハイパーコールは呼び出し元に戻ることは想定されていない。
x0 = HVC_FINALISE_EL2 (arm64 only)
コマンドラインオプションに応じて EL2 の設定を完了する。たとえば、VHE モードを有効にしてカーネルの例外レベルを EL1 から EL2 へ上げる試みも 含む。これは、CPU が VHE をサポートしていること、EL2 の MMU がオフで あること、VHE がほかの手段(たとえばコマンドラインオプション)で無効に されていないことを条件とする。
r0/x0 のその他の値はハイパーバイザ固有の扱いを引き起こす。ここでは説明しない。
スタブのハイパーコールの戻り値は r0/x0 に入り、成功時は 0、エラー時は HVC_STUB_ERR である。スタブのハイパーバイザは、呼び出し側が保存する レジスタ(arm64 では x0-x18、arm では r0-r3 と ip)を破壊してよい。したがって、 ハイパーコールには関数呼び出しを使うことを推奨する。