しばらく、特殊なスレッド並列プログラムで(のみ)、プログラムが途中でSIGILLで死んでしまうという現象に悩まされていたのだが、

よくよく調べた結果、Linuxカーネルのキャッシュ管理がバグっているという結論に。
オレ様GJ!


と書くと分けわからんので、以下詳細。

まず、Linuxのキャッシュ管理においてIA64アーキは特別な扱いを受けている。

普通のCPU:
flush_icache_page(): i-cache をパージ
lazy_mmu_prot_update(): NOP

IA64:
flush_icache_page(): NOP
lazy_mmu_prot_update(): i-cache をパージ

となっているので、lazy_mmu_prot_update()の呼び方を間違えると見事IA64でしか再現しないバグの出来上がりである。

で、カーネルいじってる連中でも忘れがちであるが、IA64のようなキャッシュが物理メモリアドレスで管理されているCPUアーキはプロセスの消滅と同時にキャッシュがなくなったりはしないので(なくなるようにも出来るけどそれをする性能デメリットが大きすぎる)、ファイルをreadしているだけでもi-cacheパージを意識しなければいけない。

ファイルをreadしようが、writeしようがmemoryにとってはwriteであり、メモリを「前の状態」から書き換えるときはキャッシュコヒーレンシは常に維持しないといけないから。

逆に仮想アドレスによるキャッシュだとプロセス切り替わった時に、すでに前のプロセスのキャッシュはパージされているので、readしかしない(=1回しかmemory writeがない)状態だとキャッシュの事はあまり考えなくてもすんえ楽である。

で、ここまで書いたらお分かりな用にカーネルの do_no_page()のキャッシュパージ処理が間違っていたんだな。
南無。

以下のURLにも説明ある

http://www.gelato.unsw.edu.au/archives/linux-ia64/0704/20323.html

Linux IA64 MLに始めた話題があがったのが2007/04/04だから、Monteciteの発表以降半年以上誰も気づかなかった事になるな。

あ、Madison以前はL2がI-D 兼用cacheだからソフトが明示的にi-cacheパージしなくてもよいCPUだったってことね。

いじょ


PS
余談だけど、このlazy_mmu_prot_update()であるが、実はすでに設計思想が崩壊していて。。。
あー、まあこの話はいいや。