背景(私のrdtscの仮想化の理解):私はVirtualBoxのTSC値を試しています。 VirtualBoxがrdtsc
をエミュレートする方法についての私の現在の理解は、仮想モードでは、rdtscへの呼び出しは、別のレジスタに設定された値である所定の結果によってオフセットされることです。この値は、仮想マシンの起動時にホスト上でrdtsc
になります。「TiedToExecution」を有効にすると、VirtualBoxでTSCが大きくなるのはなぜですか?
この戦略の利点は、rdtsc
が壁時計の時間を予想どおりに進めることですが、プロセスではrdtsc
が予想よりも長くかかると感じることがあります。例えば、このような単純なコードで:ゲスト上で実行
x = rdtsc();
y = rdtsc();
z = y - x;
print z
、z
のためトラップRDTSCに関連付けられた壁クロック時間コストの予想よりも大きくてもよいです。ホストOSがこれらの2つの呼び出しの間にVirtualBoxプロセスをスワップすると、さらに悪化します。
VirtualBoxのマニュアル(TSCモードの変更)を読んだところ、TSCを直接シミュレートする代替仮想化技術があります。私が理解しているように、オフセット値は、ゲストOSが実際にCPUを使用する時間だけを考慮に入れます。利点は、使用可能なサイクルに関しては、TSCがまるでホストマシン上にあるかのように動作することです。欠点は、ゲストOSが認識していない「欠落したサイクル」があるため、TSCがウォールクロック時間から離れることです。
私の目標: 2番目のオプションを実行するようにVirtualBoxを設定しようとしています。 rdtscの短期的な動作をハードウェアで可能な限り正確に実行しているかのようにエミュレートしたいと思います。壁時計の時刻と一致しないかどうかは気にしません。私はこれがSMPで「信頼できる」ものではないことを完全に認識しています。それはエンタープライズソフトウェアを実験するためのものではありません。私が何をしたか
:は、最初に私が繰り返しrdtsc
を呼び出す簡単なテストプログラムを書いて、その結果を出力します。
__inline__ uint64_t rdtsc()
{
uint32_t lo, hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (uint64_t)hi << 32 | lo;
}
int main()
{
int i;
uint64_t val[8];
val[0] = rdtsc();
val[0] = rdtsc();
val[0] = rdtsc();
val[0] = rdtsc();
val[0] = rdtsc();
val[0] = rdtsc();
val[0] = rdtsc();
val[0] = rdtsc();
for (i = 0; i < 8; i++) {
printf("rdtsc (%2d): %llX", i, val[i]);
if (i > 0) {
printf("\t\t (+%llX)", (val[i] - val[i - 1]));
}
printf("\n");
}
return 0;
}
私は私のホストマシン上でこのプログラムを試してみました。その後、VirtualBoxマシンで実行しました。 rdtsc
の間のデルタは本質的に同一でした - 唯一の違いは私のホスト上の値そのものは約30T以上でした。出力例:次に
rdtsc (0): 334F2252A1824
rdtsc (1): 334F2252A1836 (+12)
rdtsc (2): 334F2252A1853 (+1D)
rdtsc (3): 334F2252A1865 (+12)
rdtsc (4): 334F2252A1877 (+12)
rdtsc (5): 334F2252A1889 (+12)
rdtsc (6): 334F2252A18A6 (+1D)
rdtsc (7): 334F2252A18B8 (+12)
は、私はより正確な仮想サイクル計数の有利な壁時計時間を無視するようになっていた考えのVirtualBoxにTSCTiedToExecution
フラグを変更しました。私は上記のマニュアルページからこれを得ました:
./VBoxManage setextradata "HelloWorld" "VBoxInternal/TM/TSCTiedToExecution" 1
しかしこれは私に予期しない結果をもたらしました。仮想プログラムは、現在返さ:
、RDTSCを実行するために約1100サイクルを取っているように見えるのTSCTiedToExecution
で
rdtsc (0): F2252A1824
rdtsc (1): F2252A1836 (+B12)
rdtsc (2): F2252A1853 (+B1D)
rdtsc (3): F2252A1865 (+AFF)
rdtsc (4): F2252A1877 (+B13)
rdtsc (5): F2252A1889 (+AF2)
rdtsc (6): F2252A18A6 (+B1D)
rdtsc (7): F2252A18B8 (+B0C)
....
質問:まず、私はこの振る舞いを取得しなかった理由私は疑問に思って?それは私が期待していたものとほぼ反対のようですが、これがどのように実装されているかについての私の理解とは必ずしも一致しません。
第2に、ハードウェア上にあるかのように、仮想サイクルごとにTSCを進めるという私の本来の目標をどうやって達成できますか?
マイセットアップ:私は8x Intel Xeon CPU X5550 @ 2.67GHzで動作しています。 VirtualBoxにはVMXとネストされたページングが有効になっています。私はソースからコンパイルしました、バージョン:4.1.2_OSE r38459。
ありがとうございます。
P.S.私はこれに恩恵を始めましたが、答えはまだありません...