準仮想化クロックのしくみについて解説してるブログがありました。
まず、ゲストOSが読めるメモリーをMSRを使って登録しておきます。そこへKVMがホストの起動してからの時間とTSC(Time Stamp Counter)を書き込みます。ゲストOSは時間を知りたいときに、まず現在のTSCを読みます。そして、メモリー上の起動してからの時間とTSCの差分の値を使って現在時間を割り出します。
ホストの起動したときの時刻は別に保存してあるそうです。
メモリーを使って値のやり取りをしていることと、TSCを使っているのが特徴かなと思います。
メモリーの値がアップデートされるのはホストOSからゲストOSに制御が移るVM eventの前だそうです。
時計がどれだけ正確化は、ゲストOSがどういうタイミングで時計をチェックして更新するかによります。
Linuxのシステムクロックについては、こちらの解説がくわしいです。4回の連載になっていて、kvm-clockについてもpvclockとして解説があります。
kvm-clockはRTCのようにハードウェアクロックの1種とされているようですが。
ハードウェアの時計とシステムクロックの同期は、システムの起動時とサスペンド、レジューム時に行われるそうです。その他に、getnstimeofday()/ktime_get_real()はハードウェアの時計も参照するとなっています。、gettimeofday()はハードウェアの時計を参照するようです。
カーネルにおけるタイマー事情 ~第3回 IAマシンのもつ各種計時ハードウェア~
準仮想化クロックを使っているときは、ホストOSにNTPを動かしていることが大切ですね。ゲストOSで動かしたほうがいいかどうかはディストリビューションによって意見が分かれるようです。
KVMにおいて ホストとゲストの時間管理はNTPを用いるべきか?
ゲストOSでNTPを使わなかった場合、ハードウェアの時計であるkvm-clockをゲストOSのシステムクロックに反映させる必要があります。UbuntuやSUSEにそういう仕組みがありましたっけ。確認が必要です。
以上簡単ですが準仮想化クロックについて調べてみました。
追記
ハードウェアクロックというとRTC(Real Time Clock)のことを指すそうです。kvm-clockは、ハードウェアの時計と書き直しました。
追記(2015/08/09)
KVMがメモリに値を書き込む頻度についてLinuxのカーネルソースを調べたところ、そう頻繁には値が更新されていないことがわかりました。