カーネル読書会 第0x40回
↓ これに行ってきた。
http://mkosaki.blog46.fc2.com/blog-entry-166.html
http://d.hatena.ne.jp/hyoshiok/20060609#p1
CPUIDの結果から、より適切なコードバイトが使えるCPUなら、起動時にコードを書き換える仕組み。
Pentium4 対応カーネルってどうなってんのかな、と思っていたのだけど、こういう仕組みなら、古いマシンで立ち上げても動くのかな。
kosakiさんのサンプルコードにて。
誰か: この57ってなんですか? kosaki: (マジックナンバーとして)素数を使うと、(自分で埋め込んだという印になるから)探しやすいです。 私: 3で割れますが…。
思わずツッコミを入れてしまいました。
皆さん、低レベルな話が大好きですね。10時過ぎまでというのは、かなり盛り上がったほうだと思います。kosakiさんありがとうございました。
よしおかさんの『「薄い話」とわざわざ言う奴ほど濃い話をするという法則』は見事的中。
次回はldsoとちらっとおっしゃっていましたので期待しています。
ちなみにapply_alternatives()で使用する7バイトのNOPは、
#define GENERIC_NOP7 ".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n"
となっている。Intel風に書くと
lea esi, [esi + 0]
つまり mov esi, esi なのでNOPということのようだ。(参照)
prefixをつけるのかと思っていたら、そうではなく。たぶんprefixは特別な作用(で遅くなる可能性)があるので避けているのかなと。
思ったのは、add [esp + 0], 0 みたいに、メモリの読み出しを発生させる(かもしれない)NOPと、本当に何もしないNOPがあるなと。
(その辺が実際はどうなのかは、実装者にしかわからないというのが、よしおかさんの話にもあった)
lea esi, [esi + 0]も、mov esi, esiに変換されて、さらに何もしないNOPになるかもしれないし、esi + 0をALUに計算させるかもしれない。
add [eax + ebx + 0], 0みたいな方が長いんだけど、採用されていないのはその辺の理由なのだろう。
あと、AMDサポートを入れたときには8バイトNOPがサポートされるというのを聞いて、それだとIntel CPUで動かなくなるんじゃないのかと思ったんだけど、そこは微妙。
#define K8_NOP4 ".byte 0x66,0x66,0x66,0x90\n" #define K8_NOP8 K8_NOP4 K8_NOP4
とかになってる。なんじゃこりゃ。
0x66は32bit prefixで、0x90はNOP。たぶんAMD系は同じprefixを繰り返してもオッケーで、ペナルティが無視できるくらい小さいのだろう。
そういえばx86は、命令長が1バイトから?バイトくらいまである超変態命令セット。そんな「異端児」が何年も改良され続けているのがすごい。
で、最大何バイトだっけか、と思ったら、よくわからない。
1〜15バイト説
http://www.atmarkit.co.jp/fpc/rensai/zunouhoudan001/pentium3vsathlon.html
100バイト以上説
http://www2.nsknet.or.jp/~azuma/nu/nu0025.htm
15バイトに、prefixをいくらでもつけられるから、100バイトを超える、という理解でいいのかな。