2011-09-16 24 views
1

背景(私の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.私はこれに恩恵を始めましたが、答えはまだありません...

答えて

0

"VBoxInternal/TM/TSCTiedToExecution"を無効にしてテストプログラムを再度実行してみてください。次のコード

"VBoxInternal/TM/TSCTiedToExecution" 無効ディスプレイでのVirtualBox上で実行されている
ULONGLONG x1 = Cpu::Rdtsc(); 
ULONGLONG x2 = Cpu::Rdtsc(); 

DbgPrintUlong('D', x2 - x1, 30, 23); 

x2のこと - x1が約200 000サイクルを取りました。対照的に、 "VBoxInternal/TM/TSCTiedToExecution"が有効になっているマシンでは、3 000サイクルしかかかりませんでした。私は、この減少は、VirtualBoxのマニュアルからの次回の通過を意味します。「特別な状況では、ゲストのTSC(タイムスタンプカウンター)を実際にゲストを実行するのに費やした時間を反映させることが有用かもしれません。

私は、長い間、VirtualBoxでTSCエミュレーションが改善されないと考えています。

私がアドバイスできるのは、VmWare Workstationに移行することだけです。 TSCのエミュレーションがはるかに優れています。

関連する問題