Intel64 and IA-32 Architectures Software Developer's Manuals 改訂

8月31日に Intel64 and IA-32 Architectures Software Developer's Manuals が version 044 に改訂された。

主な変更の箇所は

  • APIC Virtualization
  • 2.2.1 に Extended Feature Enable Register(IA32_EFER MSR) の説明が追加。
  • 17.13.3 に Time-Stamp Counter Adjustment が追加。
  • SYSCALL と SYSENTER の説明が詳しくなった。
  • 17.8 に Last Branch, Call Stack, Interrupt, and Exception Recording for Processors based on Intel Microarchitecture code name Haswellが追加。
  • 18.9 3rd Generation Intel Core Processor Performance Monitoring Facility が追加。Haswell 向け。
  • 19.2 Perforamcne Monitoring Events For Next Generation Intel Core Processors が追加。Haswell 向け。

一番大きな変更は APIC Virtualization だが、それより Time-Stamp Counter Adjustment と Call Stack Profiling に心引かれる。

Time-Stamp Counter Adjustment

論理 CPU 毎に 64 ビットの IA32_TSC_ADJUST MSR が新設された。
IA32_TSC_ADJUST MSR は初期値は 0 だが、WRMSR でここに値を書き込むと、以降 RDTSC 命令で読める TSC の値が (補正前の TSC + IA32_TSC_ADJUST) になる。つまり TSC の値に ±の補正をかけることができるようになった。
補正前の TSC 自体を変更するには、これまで通り IA32_TIME_STAMP_COUNTER MSR を使える。

これは以下のような目的で役に立つ。

SMP 向け OS では各論理 CPU の TSC をできるだけ合致させたい。プロセスが論理 CPU 間をマイグレーションした時に TSC のずれが見えるのを防ぎたいとか、TSC を時刻基準として使っているためである。

しかし TSC は論理 CPU をスタートした時点からカウントアップを始めるので、そのままだとシステム内の CPU の TSC はバラバラになる。そこで 2 つ目以降の論理 CPU のブートアップ処理の中でマスター(論理) CPU の TSC に自分の TSC を同期させる処理が入っている。

この処理はプロセス間割り込み(IPI)などを使って、(1) CPU A が RDTSC してメモリに記録 → (2) CPU A から CPU B に IPI → (3) CPU B が RDTSC してメモリに記録 → (4) CPU B から CPU A に IPI → もう一度 (5) CPU A が RDTSC してメモリに記録→ ? CPU A から CPU B に IPI、を繰り返し続ける。

IPI の処理が CPU A → CPU B でも CPU B → CPU A でも同じ時間かかるので、本来 CPU B の TSC\frac{(1) + (5)}{2} であるべき。そのため CPU B は \frac{(1) + (5)}{2} - (3) だけずれていることになる。そのため CPU B を CPU A に合わせるなら、あらため CPU B の RDTSC を読んでそれに \frac{(1) + (5)}{2} - (3) を足した値を間髪をいれずに IA32_TIME_STAMP_COUNTER MSR で書き込む必要がある。

このような調整の後でズレを再確認すると、やっぱりまだズレている。さらにここで「100サイクル遅れている」と分かり、もう一度ズレを計算して CPU B の IA32_TIME_STAMP_COUNTER MSR を設定すると今度は「100サイクル進んでいる」というようにズレる。同期処理のプロセス自体が誤差を生む原因になっているからだ。

このズレは TSC 自体を絶対値として設定する IA32_TIME_STAMP_COUNTER MSR ではなく、差分として設定できる IA32_TSC_ADJUST MSR があればより正確に時刻合わせができる。「100 サイクル遅れている」と分かれば、IA32_TSC_ADJUST MSR を素直に +100 して再設定できるから。

Call Stack Profiling

Branch Trace Store (BTS) はブランチ命令が実行された時にその分岐先をメモリ中に記録してゆくデバッグ機構だが、Haswell には call stack profie. 機構が導入された。

ブランチ記録はプログラム動作の概要を知るために行っているが、全ての分岐命令を記録するとすぐにバッファが溢れてしまう。Pascal/C 言語のような構造化プログラムでは関数が多段に呼ばれていて、呼び出しの深い関数は末端に近く、浅い箇所は根幹に近い。特にそれ以上別の関数を呼び出さない関数は末端(leaf)である。

Call stack profile は、ブランチ記録をとりながら、別途 CALL のスタック(LIFO) を作ってゆく。RETURN 命令が実行された場合、この LIFO を巻き戻すと同時に前回の CALL 以降のブランチ記録をフラッシュしてしまう。これで細部のブランチ記録を捨てて重要部分の記録を多く残すことができる。