Timekeeping in VMware Virtual Machines を読み解く (3)

以前の記事:

だいぶ間が開いてしまいましたが,今回は原典の pp.6-9 を読み解きます。

Host OS, Guest OS ともに Linux の場合についてのみ述べます。

  • 「時刻」のソース
  • 「時間」のソース
    • RTC Counters / Alarm
    • PIT (Programmable Interval Timer)
    • Local APIC (Advanced Programmable Interrupt Controller) (a.k.a. lapic)
    • ACPI Timer
    • TSC (Time Stamp Counter)
    • HPET (High Precision Event Timer)
Timekeeping in VMware Virtual Machines を読み解く (1) - daily dayflower

RTC TOD については重要なので後述します。

RTC Counters / Alarm

RTC Counters については完全にエミューレートします。

RTC Alarm については少なくとも ESX Server 2.x の時点ではサポートしていません。Server 1.x, 2.x 等についてどのようになっているのかはわかりません。

PIT (Programmable Interval Timer)

Linux の「システム時刻」を刻む上で最重要な PIT です。内包する3つのタイマーについて完全にエミュレートします。

Local APIC (Advanced Programmable Interrupt Controller; lapic)

完全にエミュレートします。

ACPI Timer

完全にエミュレートします。

TSC (Time Stamp Counter)

一応のエミュレートは行いますが,おそらく他のタイマデバイスとの整合性をとっている(逆算している)だけだと思います。

VMware guest で TSC に基づいた時刻補正はしないほうが吉なので詳しくは触れません。

HPET (High Precision Event Timer)

一切対応していません。

RTC TOD

擬似的なエミュレーションをおこないます。guest OS が「ハードウェア時刻」の取得を行う際,host OS の「時刻」*2に,ある種の「差分」を加減したものを返します。

このある種の「差分」は,通常状態であれば,VMware guest の nvram に保存されています。

たとえば,現在 nvram に「差分」が +3min として保存されているとします。

  1. 現在の host OS の「時刻」が 09:00:00 とする
  2. guest OS で「ハードウェア時刻」を取得すると,09:03:00 が返る

のようになります。

また,たとえば

  1. 現在の host OS の「時刻」が 12:00:00 とする
  2. guest OS で「ハードウェア時刻」を 15:15:00 を設定する
  3. guest OS の nvram の「差分」に +195min が設定される

のようになります。

guest OS のシャットダウン時には「システム時刻」から「ハードウェア時刻」への書き戻しが発生しますが,このときにも nvram への「差分」の書き込みが発生します。このように host との「差分」で管理を行っているので,guest OS のサスペンド・レジューム・シャットダウン・ブート時にも,一種の整合性が保たれるわけです。

上記の例では「差分」はあくまで host との絶対的な差分で表記しましたが,実際には host の UTC 時刻との差分です。


なお,この「差分」は,*.vmx 設定ファイルで static に与えることができます。それが rtc.diffFromUTC というパラメータです。

ということは。guest Linux OS のセットアップ時に時刻を UTC として設定した場合,rtc.diffFromUTC を 0 に設定すると,host OS の時刻が狂わない限り,guest OS の「ハードウェア時刻」が狂うことはありません。

時刻を Local time (JST) でセットアップした場合は,32400 を設定すれば OK です。


また rtc.startTime というパラメータを利用することで,guest が立ち上がる度に static な絶対的時刻を設定することができます。たとえば guest を電源 ON にする度に 2000/01/01 00:00:00 にハードウェア時刻を設定する,とか*3


上記で「完全にエミュレートします」と書いているデバイスが多いですが,それぞれ独立してエミュレートしているわけではなく,各デバイスの整合性をとった値を返しているのだと思います。

The timer runs in apparent time, matching the other timer devices.

って書いてあるデバイスも多いので。

*1:Time Of Day

*2:これはおそらく host OS の「ハードウェア時刻(RTC TOD)」ではなく「システム時刻」であると思われます。根拠のないまったくの予測です

*3:でもこんな機能,シェアウェアの期限切れ回避くらいにしか使えないような(笑)……って冗談ですよ,冗談。しかも,だとしても,かなり不便な気がする