Pentium F00F バグ
From Wikipedia, the free encyclopedia
問題を起こす機械語コード(f0 0f c7 c8)に対応するアセンブリ言語表現は以下のようになる。本来はメモリオペランドを指定して使用する前提の命令であり[2]、下記のコードは実際のアセンブラで処理できないかもしれない。
lock cmpxchg8b eax
不具合を引き起こすにはオペランドはレジスタである必要がある[1][2]。ここでは例示としてeaxをオペランドにしているが、その他のレジスタでもよい。
cmpxchg8b命令は、オペランドとして指定されたアドレスのメモリ上の8byteの領域を取る。この命令を実行すると、edx:eaxの値とメモリ上の8byte値を比較し[2]、一致したらZフラグをセットするとともにecx:ebxの値をこの8byte領域にストアし、一致しなければZフラグをクリアするとともに8byteのデータをedx:eaxにロードする(コンペア・アンド・スワップ、詳細はリファレンスマニュアル等を参照)。ただし、この命令の機械語では、命令フォーマット上はオペランドにレジスタも指定することが許容される。そして、レジスタオペランドを指定したcmpxchg8b命令を、lockプレフィクス付で実行すると、この不具合が引き起こされる[1][2]。
lockプレフィックス[注釈 2]なしでは、この命令は不正命令例外を引き起こすだけである[1][2]。即ち、レジスタペアedx:eaxに格納された8byte=64bitのデータと、指定されたレジスタ、上記の例ではeaxに格納された4byte=32bitのデータの比較は妥当ではないからである。
しかし、lockプリフィックスを付けた場合、以後のメモリアクセスが抑制されるために、プロセッサは不正命令例外ハンドラに移行することができず[1]、この段階でハングアップし以後は一切の命令を実行せず、割り込みも受け付けなくなってしまう。復旧するにはシステムを再起動しなければならない[1]。
対策
この命令は特別な権限を要求せず、特に、発見時点ではユーザープロセスの実行中にOSが全く関与できずに発生すると思われたため、当初は重大な問題と考えられた[3]。以後、OSでの対策が行われるとともに、プロセッサ側でも対策が行われた。
オペレーティングシステムでの対応
広く普及していたプロセッサにエラッタが発見されたことから、オペレーティングシステムベンダは発生条件を検知してクラッシュを防ぐ対策を実装する作業に追われた[4][5]。
発見時点では不可能にも思われたが、オペレーティングシステムでの対策で回避は可能であった。具体的には、例外発生時に、例外ハンドラへのアクセスが、まずページフォールトを発生するようにして、不具合を回避する[1][2]。
プロセッサのバグフィクス
Pentium Pro以降のIntelプロセッサにはこのバグの影響はない[1]。また、最新のIntel Pentium Processor Specificationもアップデートされ、B2ステッピングではこの問題は修正されている。
影響
f00f命令を問題のあるシステム上で実行しても、ハードウェア的なダメージを起こさない[1]。もちろんファイルシステムやオペレーティングシステム、その他の状況にもよるが、ディスクバッファがフラッシュされていなかったり書込み操作中にドライブに割り込まれたり、とあるアトミックでない操作中に割り込まれたりした状態でこのコードを踏み、フリーズしたならば、データを失うことはあり得る。
f00fバグは一般的に知られたので、この言葉は時々よく似たハードウェア設計ミス、例えばCyrix coma バグのようなものを指すのにも使われる。