前の記事でxv6ではどうなのかを述べた。$0x80の挙動についてまとめる。APICがからんだinterruptは後回しにしたい。referenceは前の記事を参考にしてね。modeのentrypointになっており、registerの設定をいろいろした後に、start_kernelに飛ぶ。この関数は、init/main.cにある。最初にarch/i386/kernel/head.SでIDTを初期化して、とりあえずロードまで済ませている。trap_initのset_**_gateでIDTのentryを設定する。gateに初期化する。syscall(0x80)の部分はtrap_initで設定されているのでskipしていることに注意。skipここで、interruptはarch/i386/kernel/entry.Sで定義されているcallbackを要素に持つ配列。次回以降で詳しくみていく。exception(#0)を例に取る。landから呼ばれるので%csのRPL(CPL)は3である。set_trap_gate(0,&divide_error);と設定した1。書いたが、ここでは、TSSの設定だけ見る。(GDT_ENTRY_TSS*8))なので、TSSにloadされるesp0はprocのstack(thread_info)内にあることがわかる。例外が発生した場合、権限周りは大丈夫として、スタックにレジスタが積まれる。pt_regsが形成されていく。segment)の方向から構築されていく。ESやORIG_EAXはconstantとして指定されているが、すぐ下のコードに出てくる。ret_from_exceptionと処理が走る。registerの設定だ。*%ediでdo_divide_errorが動く。これが終わったら、ret_from_exceptionに移動する。trapframeに対応していることが見て取れる。&info);}雰囲気的には、do_trap関数を呼ぶようだ。これは、関数の引数とregisterを直接対応させることができる。https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.htmlとある。error_code)に対応する。stack取り出さないで、registerを直接使うという点でfastcallなんだろう。notify_dieはkprobe_exceptions_notifyがcallbackとして呼ばれ、notify_dieの第一引数で戻り値が決定するようだ。今回はDIE_TRAPで、NOTIFY_DONEとなるので、条件分岐はfalseとなる。したがって、どのみちdo_trapが呼ばれる。FPE_INTDIVとなる。send_signalと続くようだ。processにSIGFPEを投げるのが仕事っぽい。siginfoで受け取れるようにできる。Interfaceのch21.4あたりで詳しく解説されている。do_trapが終わったので、ret_from_exceptionを見る。Kernelのch4.6が圧倒的に詳しいので、2つだけこの記事で触れる。1つ目が一番最初のところ。gateが入口になる事があるため、eflags.IF=ONのママの場合がある。このため、exceptionの部分だけ、cli命令が付加されている。disableの状態が続く。2つ目がexceptionの一番最後のところ。最後で触れているが、hardware側で%eipやら%espやら%ssやらを復元していく。pointerだったから、exceptionの処理終了後はここに飛んで作業を再開する。.fixupはよくわかんないので、TODOに回す。同様にiret命令があることがポイント。interruptが発生した場合どうなっているのかをみていく。trap_initで設定されていることに注意する。interruptが発生した時、hardware側で権限周りを確認後、registerをstackにpushする。その後、arch/i386/kernel/entry.S内のENTRY(system_call)からソフトウェア的な処理がスタートする。*sys_call_table(,%eax,4)が呼ばれ、所要の関数に飛ぶ。spaceに引き戻される。processに飛んだままになるかもしれない(処理が帰ってこない)ので、違う記事にて処理を追いたい。kernelのch10にあるみたいだが、まだ読んでないので読んだらまとめたい。exception中のinterruptの挙動exception中にinterruptが生じるか否かは実はexceptionの種類によって異なる。gateの場合はeflags.IFがOFFになるので、手動でONにしない限り、interruptは発生しない。gateの場合はeflags.IFフラグはexceptionの前後でそのまま3。Gateであるという部分だけである。0b1111とセットされてる)なので、IFはクリアされない。set_system_gateもtypeが0x1111なのでIFはクリアされない。$0x80が発生中にinterruptが生じる場合ことももちろんある。syscallの終了]とか。timerが0になるprocessは別プロセスであってもよく、その場合は、interruptを開始するprocessはexceptionが起こったprocessと別になる。みたいなことが起こりうる。exception中のschedulingについてこちらも起こりうる。pointだから、現在exceptionの処理中にもかかわらず、別のprocessに移動することが有りうる。_TIF_NEED_RESCHEDがいつ付加されるかは、自分がまだ把握しきっていないので、別の機会に。Modeにいるときに別のprocessに移動できる状態のことをpreemptというみたい。pointerに切り替えて作業する。(#DF)に分類され、abortとなる。(同じexceptionが重なることはないというところがポイント)interruptの最中にexceptionは起こるか?こちらも起こりうるが、これはinterruptについて解説するときにまとめるのが良いだろう。selector);となっている。厳密に言えば、call命令で呼び出される関数内でeflags.IFがONになることはあるがassembly内では終了処理中はdisableのまま。Kernels"の4つの箇条書されたやつがそう。callの内部実装の違い(xv6を例に)月別アーカイブはてなブログをはじめよう!knknkn11626さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。