🐡

ARM64 ハイパーバイザー: Arm Generic Timer の仮想化

2022/10/21に公開

1. はじめに

CPUコアに内蔵されている(SoCのペリフェラルではない)Arm Generic Timer の仮想化についてまとめています。なお、本記事は aarch64 (ARM64) に限定した内容になっています。

2. タイマーの種類

Arm Generic Timer には以下の7種類のタイマーが用意されています。物理的には1つのマスターとなるタイマーのみ存在しますが、そのタイマーに対してオフセット値を設定したり、タイマー割り込みをオーバラップすることにより仮想的なタイマーを下位のEL (Exception Level) に提供可能な仕組みになっています。

タイマー 用途 割り込みID(PPI) レジスタprefix
EL1 physical timer 通常はEL1で起動したOS(カーネル)が利用。EL0もアクセス可能 30 CNTP
EL1 virtual timer 通常はハイパーバイザー上で動作するゲストOSが利用。EL0もアクセス可能 27 CNTV
Non-secure EL2 physical timer 通常はEL2で起動したハイパーバイザーが利用 26 CNTHP
Non-secure EL2 virtual timer 通常は利用されないはず? 28 CNTHV
Secure EL2 physical timer 通常は利用されないはず 20 CNTHPS
Secure EL2 virtual timer 通常は利用されないはず 19 CNTHVS
EL3 physical timer 通常はEL2で起動したセキュアモニターが利用 29 CNTPS

3. タイマーの仕様

タイマー自体はごく普通のシンプルな仕様ですが、仮想化の対応が入っている分だけ少し複雑になります。以下に全体の概要ブロック図を示します。

タイマー制御レジスタ

各タイマーは主に以下の3種類のレジスタから構成(制御)されます。タイマーを制御する<timer>_CTL_EL<x>レジスタ、タイマー割り込み発生用の比較値<timer>_CVAL_EL<x>レジスタ、そしてタイマーの現在の値を示す<timer>_TVAL_EL<x>レジスタです。このタイマーの制御自体はごく一般的にあるタイマーの仕様とほとんど同じだと思います。

レジスタ名 用途
{prefix}_CTL_ELx タイマー制御レジスタ
{prefix}_CVAL_ELx 比較用カウンタ値
{prefix}_TVAL_ELx タイマーのカウンタ値

タイマーの仮想化

マスター(リファレンス)となるタイマーのカウンタは一つで、そのカウンタ値及び周波数はCNTPCT_EL0及びCNTFRQ_EL0からリード可能です。これらは普通の物理タイマーです。一方で仮想化のタイマーとして、CNTVOFF_EL2レジスタの設定によりカウンタ値が減る方向の仮想タイマーCNTVCT_EL0が用意されています。CNTVOFF_EL2はEL2/EL3で設定可能す。

ではなぜ、仮想タイマー用にオフセットが必要かというと、EL2(ハイパーバイザー)が動作している間の時間経過分をEL1のゲストOSにコンテキストスイッチした時に相殺するためです(EL2が動いていた分の経過時間を設定すれば、EL1から見ると自分がずっと継続して動いているように見かけ上出来る)。

こんな感じでタイマーを仮想化しています。例えば、ハイパーバイザー上で動作するゲストOSの場合は(通常は仮想モードで動く)、EL1 virtual timer (CNTV)を利用します。

ハイパーバイザーでキーとなるCNTHCTL_EL2レジスタ

このレジスタは別途存在する重要なHCR_EL2レジスタのE2H及びTGEビットフィールドの設定に連動しています。TGE及びE2Hが両方1の場合、EL0がEL2の物理および仮想タイマーにもアクセス可能になります。用途はよくわかりません(KVM?)が、ホストOSをEL2レベルで動かす時の用途みたいです。

https://zenn.dev/hidenori3/articles/1c33e080cd643e

4. イベントストリーム機能

Arm Generic Timerはイベントストリームと呼ばれる機能も保有しています。WFE (Wait For Event)命令でコアが低消費電力モードに入った状態から復帰するためのイベントを、Generic Timerを利用して発生させることが出来ます。

直接はタイマーとは関係ないのですが、タイマーのカウンターの各ビットをイベントフラグ的に扱い、そこに1を立てたら(もしくは0クリアしたら)イベントを発行するという使い方が可能です。

この制御もCNTHCTL_EL2レジスタで設定可能です。

5. 参考文献

https://tc.gts3.org/cs3210/2020/spring/r/aarch64-generic-timer.pdf

Discussion