カーネルと 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)を破壊してよい。したがって、 ハイパーコールには関数呼び出しを使うことを推奨する。