http://pdos.csail.mit.edu/6.828/2014/xv6/book-rev8.pdf
トラップを処理するのも大変だなー。
xv6ではperlを使って、ベクタテーブルを作っているみたいだ。まあそこは問題じゃなくて、trapが発生すると、それを処理するためにまずalltrapsというルーチンに飛ぶ。 このルーチンでは、ユーザプロセスのレジスタのありとあらゆる情報を保存してスタックに書き込んでいる。alltrapsはカーネルモードで実行されるのかな? これにより、カーネルスタック上に次々とレジスタ値が保存されていく。こんな感じらしい。
この図のことを、トラップフレームと読んでいる。さらに、trapというCで記述されている関数に飛ぶ。これには引数を設定する必要があるのだが、これもスタック上に積み上げている。
3270 # Call trap(tf), where tf=%esp 3271 pushl %esp 3272 call trap 3273 addl $4, %esp
trap(tf)内では、割り込みの種類に応じて処理を切り替える。
- システムコールの場合: T_SYSCALLを設定してsyscallを呼び出す。
- ハードウェアの割り込みの場合: それに応じた処理
- それ以外: 異常なトラップと判断してユーザプロセスをクリーンアップ
- カーネルがtrapを発生させ、どのトラップなのか分からない: OSの異常として強制終了
以下が、ベクタテーブルの生成perlスクリプトになっている。
3200 #!/usr/bin/perl −w 3201 3202 # Generate vectors.S, the trap/interrupt entry points. 3203 # There has to be one entry point per interrupt number 3204 # since otherwise there’s no way for trap() to discover 3205 # the interrupt number. 3206 3207 print "# generated by vectors.pl − do not edit\n"; 3208 print "# handlers\n"; 3209 print ".globl alltraps\n"; 3210 for(my $i = 0; $i < 256; $i++){ 3211 print ".globl vector$i\n"; 3212 print "vector$i:\n"; 3213 if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 3214 print " pushl \$0\n"; 3215 } 3216 print " pushl \$$i\n"; 3217 print " jmp alltraps\n"; 3218 } 3219 3220 print "\n# vector table\n"; 3221 print ".data\n"; 3222 print ".globl vectors\n"; 3223 print "vectors:\n"; 3224 for(my $i = 0; $i < 256; $i++){ 3225 print " .long vector$i\n"; 3226 } 3227 3228 # sample output: 3229 # # handlers 3230 # .globl alltraps 3231 # .globl vector0 3232 # vector0: 3233 # pushl $0 3234 # pushl $0 3235 # jmp alltraps 3236 # ... 3237 # 3238 # # vector table 3239 # .data 3240 # .globl vectors 3241 # vectors: 3242 # .long vector0 3243 # .long vector1 3244 # .long vector2 ````