11

次のコードで興味深い状況が発生しました。

    static void DivideByZero() {
      // volatile to prevent compiler optimizations.
      volatile float zero = 0.0f;
      volatile float result __attribute__((unused)) = 123.0f / zero;
    }
  DivideByZero();
  int raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW);
  ASSERT_TRUE((raised & FE_DIVBYZERO) != 0);

サポート付きで qemu デバイスを実行するとKVM、次の結果が得 られました。

 FE_DIVBYZERO !=0; //and it's ok

しかし、KVMサポートなしで同じソースを実行すると:

 FE_DIVBYZERO ==0; //and it's not ok

私がこの状況を理解しているようにmxcsr、レジスタビット (div by zero) が設定されていないために発生します。しかし、このビットが設定されていない理由がわかりません。何か案は?

更新 : qemu ベース
のエミュレーターでも同じ状況が発生しました。android

emulator -avd test -qemu  

リターン: FE_DIVBYZERO !=0;

emulator -avd test -qemu -disable-kvm

リターン: FE_DIVBYZERO ==0;

4

3 に答える 3

3

MXCSRレジスターについては、 Intel® 64 and IA-32 Architectures Software Developer's Manualで説明されています。

scalar最近の x86 プロセッサでは、コンパイラは、命令が使用するのと同じリソースを使用して、浮動小数点演算を SIMD としてマップしvector (SSE)ます。

レジスタは、浮動小数点命令と浮動小数点命令の両方のMXCSR操作を制御します。MXCSR を説明する関連セクションを以下に含めました。 ゼロ除算マスクです。クリア (0) すると、CPU はゼロ除算が検出されたときに例外を発生させます。仮想マシンで実行している場合、例外は「仮想化」され、「ハイパーバイザー」、場合によってはKVMによって処理されます。次に、ハイパーバイザーは、例外をゲスト仮想マシンに反映するかどうかを決定します。私の理論では、ゼロ除算マスクがクリアされ、例外が発生し、KVM および/または QEMU が、ゼロ除算例外が発生したことを示すフラグをクリアして、仮想マシンを再開するというものです。したがって、これはおそらく KVM/QEMU のバグです。scalarvector (SSE)MXCSR[9]MXCSR[2]

の前にfegetexcept()を発行DivideByZero()して、ゼロによる除算の例外がマスクされているか (1)、マスクされていないか (0) を調べることができます。マスクされていない場合は、fedisableexcept()を使用してマスクできます。

MXCSR コントロール/ステータス レジスタ

于 2013-03-18T07:13:21.730 に答える
1

QEMU がソフトウェア エミュレーションとして機能する場合。

http://qemu.weilnetz.de/qemu-tech.html#intro_005fx86_005femulationから。

2.8 例外のサポート

longjmp() は、ゼロ除算などの例外が発生したときに使用されます。

ホストの SIGSEGV および SIGBUS シグナル ハンドラは、無効なメモリ アクセスを取得するために使用されます。シミュレートされたプログラム カウンターは、対応する基本ブロックを再変換し、ホスト プログラム カウンターが例外ポイントにあった場所を調べることによって検出されます。

仮想 CPU は、条件コードの最適化のために計算されない場合があるため、正確な EFLAGS レジスタを取得できません。エミュレートされたコードはどのような場合でも再起動できるため、大きな問題ではありません。

FPUの状態も失われているように見え、FPUの例外が何であるかを示すビットが失われます-あなたのケースではゼロ/無効な引数による除算が失われます。また、QEMU は fetestexcept を適切にエミュレートできませんでした。したがって、結果。

QEMU がハードウェア仮想化 (KVM) を使用して動作する場合、浮動小数点例外は適切に処理されるため、テストは正しくなります。

-- 編集: その他の可能性として、例外モードの初期化が異なる可能性があります。それを追加して、ゼロ例外による div を有効にすることができます。fenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);

于 2013-03-21T16:44:34.683 に答える
0

ロジックについてはよくわかりませんが、QEMU はソフトウェア実装で、KVM はハードウェア サポートです。そのため、ソフトウェアの実装では、浮動小数点の計算ミスまたは浮動小数点値の格納のためにビットが設定されていない可能性があります..

于 2013-03-18T03:53:10.543 に答える