SSEがどう設定、使用されているのかを確認する。flagをOFFにして)、これらの命令を使えるようにしている。kernel_fpu_endにてフラグの切り替えをおこなっている1ため、この限りでない。)プログラミング言語の例外処理はパフォーマンスを落とすものとして一般に嫌われているが、ハードウェア(この場合x86)のレイヤでは、例外をあえて意図的に出すことでパフォーマンス向上を狙っている点で、面白いなと思った2ので、少し詳細に調べて見ようと思った。modeに移行した直後の処理をみていく。retここでは、まず、cr0のフラグについてとcheck_x87の動作について説明する。MPは常にこの値で、TSが特定のタイミングで切り替わる。flagについて、役割の概要を述べる。ch.2.5によれば、以下のような仕様である。check_fpuにて、ハードウェアがサポートされている限りONになる。SSEの命令時にException(#NM)を送出するとなる。math_state_restore)内にてTS=0として、2回目以降はこれらの命令を使えるようにしている。storeするのはパフォーマンスが良くない。storeするような方式7をとっている。handlerというわけだ。$1,X86_HARD_MATHとして、終了する。結果的にはIRQ13はdisableのままである。FPU以前のlegacyな計算機の外部deviceとして備え付けられていたものらしい9。その設定については、細かい(&かなりややこしい)ので補足に回す。cpu_inithead.Sではcr0.TSを0にしていなかったので、どこかで1にしているはずだ。flagをOFFにする狙いがある。2番目の行は、PF_USED_MATHをOFFにしている。flagをONにしている。task_struct)に結びついている。ModeにてFPUを使用する際に、(process単位でなく)thread単位でcr0.TSの管理をしたいという動機でTS_USEDFPUが使用される。switchの部分をみてみる。kernel_threadのコアの部分の関数である。~TS_USEDFPU;}TS_USEDFPUはFPU命令がすでに使用されていることを表すフラグ。使用されていれば、__save_init_fpuを実行する。boot_cpu_has(X86_FEATURE_FXSR)で真なので、fxsave命令が実行され、FPUやSSE関連のregisterが全てtsk->thread.i387.fxsaveに保存される。SSE命令をサポートしているか否かの違い10。(16)));となっている。unlazy_fpuはfork元の(親となる)processに対して実行しているが、dup_task_structではtask_structの内容をcopyするため、子のprocessに対しても同様にTS_USEDFPUが0となっている。skip__unlazy_fpuについては、do_forkの章でやったとおりなので、省略する。__unlazy_fpu(P_B)と実行されているので、TS_USEDFPUが0となっていることが保証される。exceptionのhandlerが発生し、cr0.TS=0となり、以降、exceptionが発生せずにFPU関連の命令が使用できる部分のコードをみていきたい。SSEの命令時にException(#NM)を送出するということを念頭に置く。set_trap_gate(7,&device_not_available);とhandlerが登録される。gateなので、device_not_available開始時にはeflags.IFが自動的に0にならない。今回は、device_not_availableに限った話をする。SSEの命令時にExceptionを送出せずに実行したいので、cr0.TSをoffにする。PF_USED_MATHがOFFなら、init_fpuでcurrent->thread.i387.fxsaveが初期化され12、PF_USED_MATHがONになる。restore命令)その後、TS_USEDFPUもONする。いうことで、cr0.TSをoffにしていることが確認できた。switchされるまではFPU関連の命令を使ってもdevice_not_availableで補足されない。MMX命令を使うようにする。landでは上のようなことができないからである。pageの中身を0埋めしている。*)get_zeroed_page(GFP_KERNEL);という形で使われている。0(free)のbitで表現するための構造体であり、pidmap_array->pageは、pidの最大値32768bit=4KBの大きさのbitmapである。processともいう)を除いて13すべて使用可能なので、0である必要がある。いうことで、0埋めするというモチベーションが起こる。fast_clear_page(page);という感じでようやく所要の関数にたどり着く。kernel_fpu_end();}という感じになっており、kernel_fpu_beginでcr0.TS=0が保証され、kernel_fpu_endでcr0.TS=1となる。両者の内部では、(cr0.TS=0なので)mmx命令がexceptionを送出せず使える。coprocessor)の設定のときに用いられているようだ。結果的にdisableになっている。FPU_IRQ=13にてIRQ13がsetupされるかどうか決まる。$1,X86_HARD_MATHの影響で、1になる。sizeof(new_cpu_data));でboot_cpu_dataに値がコピーされる。boot_cpu_data.hard_math=1で良さそう。cpu_has_fpuについても1になる。%edx,X86_CAPABILITYと関係がある。new_cpu_data+CPUINFO_x86_capabilityと合わせてみると、cpuidの結果FPUはサポートされているので、1が入るはずで、boot_cpu_has(X86_FEATURE_FPU)は1となり、cpu_has_fpu=1となるということで、IRQ13は使用されない14。clearしたり、pageのcopyをする際にmmx命令を使っている。HWのexceptionの機構とsoftwareの分野のそれとは、異なるものであるが、少なくとも言葉としては同じ"exception"なので。registerの方)を見れば良いとおもう。Processorsにも合致しているので、大丈夫そう。registerとある。そこでMXCSRがどう設定されてるのかを確認する。Power-upのときに、MXCSRが0x1F80にリセットされる。Exceptionは発生しないと思われる。必要であれば、TS=1と初期化されているようだ。OSが特別にこの性質を利用しているというわけではなく、x86側の機能としてそもそも搭載されているものだ。above).でそう書いてある。Word(regiterの中身)の初期値は0x0000である。