ウォンツテック

そでやまのーと

OS作成

kernelでprocess1()関数を呼び出して無限ループさせておいてからPICの割り込みによってタスクスイッチをさせる時、process2→process3→process1の移行の部分がhangする問題でTSSの中身を見てみた。
おそらく正しい値が入っているんだけど、実際に2回目のprocess1になる部分(hangする部分)でregisterの値を見てみるとespだけがおかしい気がする。
具体的にはTSS内部では0x9C000付近(GDTで設定したstack segmentの最大値)で2回目のprocess1でのespが0x94000付近。これが原因でおかしくなってるのかな?

調査

「はじめて読む486」によると最初のTRを設定した時、TSSはビジーTSSに変更される(typeが0x89から0x8Bになる)と書いてあるけど、実際にTSSディスクリプタの中身を見てみると0x89のままで変わらず。これはqemuだからだろうか?一応手動で0x8Bを設定してprocess1に戻してみるとちゃんとGPE faultは発生していた。

続・調査

最初にTRした直後にTSSディスクリプタを見てみたらきっちり0x8Bになっていた。ただしその後にprocess2にタスクスイッチすると何故か0x89になったけどこれは仕様かな?
Intelマニュアルによるとbusyフラグ自体は自分自身にタスクスイッチをするのを避ける(自分自身にjmpしようとするとGPEFaultが発生する)ために立ててるので他のタスクにスイッチした時には元のタスクのbusyフラグはclearしておくとある。

なんとなく

わかった。process3からprocess1(kernel)に移行する時どこに戻ってるかを見てみたらprocjmpのljmp命令の後だった。kernelはprocess1処理の後に割り込み処理をさせてるのでそこがSIPの値になってしまってprocess1の無限ループに戻れなかった。ってことはkernel用のprocessを作成して以後のkernelの処理はそのprocessに書いてあげればうまくいきそうな気がする。