Core2 Quad で VMware Server の時刻が進む件は解決した
VMware Server 1.0.4 on Core2Quad で guest の時刻が進みまくり - daily dayflowerという現象があったのですが,なんとか解決にこぎつけることができました。
原因
- NEC Express 5800 / 110Gd の BIOS が(EIST をきちんとサポートしていないためか)おかしな CPU frequency を返す
- EIST 無効時は Core2 Quad Q6600 は 2.4GHz で動いている
- ホスト側は(自力でキャリブレーションしているのか)2.4GHz であると認識している(∴ホストの時刻は狂わない)
- VMware Server は ACPI 経由で CPU frequency を取得している
- 先に上げたように ACPI 経由の CPU frequency 取得がおかしいので(フルパワー時)900MHz であると認識される
- VMware Server は guest も host も 900MHz で動いているとみなす
- 実際には 2.4GHz をベースとして割り込みが発生しているので 2.4GHz / 900MHz(≒2.67倍)の割り込みが guest に伝達する
- このため clocksource を何にしたところで,最悪 2.67 倍のスピードで時刻が進んでいく(実際には割り込みのとりこぼし lost ticks が発生するのでそこまで早くはならない)
対策
- host のクロック変動を避けるため host の cpuspeed サービスを停止しておく
- Host Power Management Causes Problems with Guest Timekeeping on Linux Hosts に従って
/etc/vmware/config
に正しい host CPU frequency を設定しておく - guest のカーネルパラメータに
notsc clocksource=pit
を追加し,guest の kernel サイドのアグレッシブな時刻補正を無効にしておく((お好みでnosmp noapic nolapic
等を追加することで,割り込みハードウェアを IO-APIC ではなく XT-PIC にして割り込み負荷を軽減させることもできます)) - guest に VMware Tools をインストールして
syncTime
を有効にする
以下調査経過が長々と続きます。
調査結果
まずは /proc/cpuinfo
を見てみます。
CPU が EIST をサポートしていること,また現在のクロックが 600MHz である(と認識されている)ことがわかります。
# cat /proc/cpuinfoprocessor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 15
model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
stepping : 11
cpu MHz : 600.000
cache size : 4096 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 4
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov
pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx lm constant_tsc
pni monitor ds_cpl vmx est tm2 cx16 xtpr lahf_lm
bogomips : 4803.45
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
ひょっとすると cpuspeed
サービスが自動的にクロックを落としているのでしょうか。
# service cpuspeed status Frequency scaling enabled using ondemand governor
ondemand
という governor によってクロック周波数が決まっていることがわかります。どのような governor があり,どのような意味をもつかについては cpufreq-selectorのメモ (blog@browncat.org)が詳しいです。
さて,この環境ではどのような周波数レンジがサポートされているのでしょうか。/sys/devices/system/cpu/cpu0/cpufreq
を覗くといろいろわかります。
# cd /sys/devices/system/cpu/cpu0/cpufreq # ls -F affected_cpus ondemand/ scaling_driver cpuinfo_cur_freq scaling_available_frequencies scaling_governor cpuinfo_max_freq scaling_available_governors scaling_max_freq cpuinfo_min_freq scaling_cur_freq scaling_min_freq # for f (*); [ -f $f ] && ( echo -n "$f: "; cat $f ) affected_cpus: 0 1 2 3 cpuinfo_cur_freq: 600000 cpuinfo_max_freq: 900000 cpuinfo_min_freq: 600000 scaling_available_frequencies: 900000 600000 scaling_available_governors: ondemand userspace performance scaling_cur_freq: 600000 scaling_driver: centrino scaling_governor: ondemand scaling_max_freq: 900000 scaling_min_freq: 600000
これだけでもある程度の情報はわかりますが,これらの情報を見やすく整形してくれるのが cpufreq-info
というコマンドです(標準ではインストールされていません)。
# yum install cpufreq-utils # cpufreq-info cpufrequtils 002: cpufreq-info (C) Dominik Brodowski 2004-2006 Report errors and bugs to linux@brodo.de, please. analyzing CPU 0: driver: centrino CPUs which need to switch frequency at the same time: 0 1 2 3 hardware limits: 600 MHz - 900 MHz available frequency steps: 900 MHz, 600 MHz available cpufreq governors: ondemand, userspace, performance current policy: frequency should be within 600 MHz and 900 MHz. The governor "ondemand" may decide which speed to use within this range. current CPU frequency is 600 MHz (asserted by call to hardware). ...... snip ......
現状で ondemand
, userspace
, performance
の3種類の governor があり,CPU clock は 600MHz と 9000MHz の2種類が設定されうる,ということがわかります。
えっ?最高で 900MHz なの?
念のために dmesg で確認してみると……
# dmesg ...... snip ...... time.c: Using 14.318180 MHz WALL HPET GTOD HPET timer. time.c: Detected 2400.089 MHz processor. ...... snip ......
一応 2.4GHz のプロセッサであることが認識されています。これで host の時刻が狂うことはないはずです。
ですがなぜ 600MHz, 900MHz なのでしょう。実力をフルに発揮できていないのでしょうか。
と思って調べたところ,まったく同じような現象に遭遇している例を発見しました。
なぜ表示されるクロックが900MHz、600MHzという奇妙な値なのか、ということに関して、Intel社に在籍しているacpi-cpufreqの開発者の方にメールで質問を送ってみたところ、BIOSがエクスポートしている値がおかしいのではないか、との回答を得ました。
このマザーボードで使用しているBIOSではEISTで指定可能な周波数の値を設定することは出来ないことと、周波数とベンチマークの比率に整合性がとれているということを考えると、BIOSに問題があると推測されます。現時点ではそれ以上のことは分かっていません。
http://www.clustcom.com/content/view/88/32/
うーむ BIOS が怪しいのですか。たしかに Q6600 は 110Gd で正式にサポートされている CPU ではありませんし,EIST の項目もないので怪しい。ただ引用元の情報を見ていただければわかると思いますが,表示上おかしいだけで,実際には 900MHz のときに 2.4GHz で動いているようです。
引用元によると acpi-cpufreq を disable すると OK になるそうですが,手元の環境で cpuspeed を disable してリブートをかけてみても,900MHz にはなるものの 2.4GHz にはなりませんでした。
この誤認識がどのような弊害をもたらしているかですが。
VMware Server の vmware.log から抜粋します。
Dec 06 18:04:09: vmx| KHZEstimate 900000 Dec 06 18:04:09: vmx| MHZEstimate 900
このように 900MHz だと推定されています。それで guest の dmesg の結果ですが,
time.c: Using 3.579545 MHz WALL PM GTOD PM timer. time.c: Detected 899.923 MHz processor.
やはり,guest も 900MHz のクロックで動作しているとみなされているようです。このせいで時刻がどんどん先にすすんでいるようです。
では,対策は,というと VMware の Knowledge Base にありました。
To prevent guest clocks from running too quickly, specify the correct maximum host CPU speed in your global configuration file,
/etc/vmware/config
. If this file exists, edit it with a text editor, adding the lines described below. The file may not exist. If it does not exist, create it as a plain text file.The example presented here assumes that the host computer has a maximum speed of 1700MHz. The first line is the most important one. It should be your host computer's maximum speed in kHz -- that is, its speed in MHz times 1000, or its speed in GHz times 1000000. Add the following lines to your global configuration file:
host.cpukHz = 1700000 host.noTSC = TRUE ptsc.noTSC = TRUEHost Power Management Causes Problems with Guest Timekeeping on Linux Hosts
本来は SpeedStep(や EIST や PowerNow や Cool'n'Quiet)で host CPU のクロックが変動する際に用いるものですが,今回のように誤認識されている場合にもこのクロック数強制設定が使えそうです。
そこで上記設定を /etc/vmware/config
に書き足し,念のために guest の kernel options で notsc
と clocksource=pit
を追加,そして VMware Tools の時刻同期機能を使ってみました。
その結果。
まず vmware.log ですが,
...... snip ...... Dec 07 10:23:19: vmx| DICT --- CONFIGURATION ...... snip ...... Dec 07 10:23:19: vmx| DICT --- USER PREFERENCES Dec 07 10:23:19: vmx| DICT --- USER DEFAULTS Dec 07 10:23:19: vmx| DICT --- HOST DEFAULTS ...... snip ...... Dec 07 10:23:19: vmx| DICT host.cpukHz = 2400000 Dec 07 10:23:19: vmx| DICT host.noTSC = TRUE Dec 07 10:23:19: vmx| DICT ptsc.noTSC = TRUE Dec 07 10:23:19: vmx| DICT --- SITE DEFAULTS ...... snip ...... Dec 07 10:23:19: vmx| KHZEstimate 2400000 Dec 07 10:23:19: vmx| MHZEstimate 2400 ...... snip ...... Dec 07 10:23:19: vmx| TimeTracker host to guest rate conversion 3949280226459 @ 2400000000Hz -> 3949280226459 @ 2400000000Hz ...... snip ......
見事に 2.4GHz と認識されています。
さて,guest の dmesg です。
time.c: Using 3.579545 MHz WALL PM GTOD PM timer. time.c: Detected 2399.846 MHz processor.
おお,こちらでも無事 2.4GHz として認識されたことがわかります。
念のために guest で一度 ntpdate
しておいて,しばらくしてから時刻を調べてみます。
% /sbin/hwclock && date 2007年12月07日 10時38分44秒 -0.981510 秒 2007年 12月 7日 金曜日 10:38:44 JST
hwclock
というのは RTC の時刻を調べるもので実質 host 側の時刻を調べるものだと思って下さい*1。後者の date
については文字通り local time source の時刻を調べるものです。
結果をみると,ほぼ同じ時刻を刻んでいることがわかります。無事きちんと時刻を同期させることができるようになりました。
*1:厳密にいうと異なります。このへんはいつか続きを書きます