無料Wikiサービス | デモページ
Linux Kernel(2.6)の実装に関するメモ書き
リンク
最近更新したページ
検索

例外処理


例外処理のメモ。対象CPUはi386。

例外処理

例外ベクタテーブル(IDT)

idt_table[256]にIDT(Interrupt Descriptor Table)が登録されている。IDTはtrap_init()で初期化する。IDTRレジスタはidt_tableを指すがこれは起動時にstartup_32_smpで初期化される(lidt idt_descr)。

Interrupt Descriptor Table
idt_table[256] <---- IDTR Register
+-------------+
| Descriptor |
+-------------+
| |
+-------------+
| |
:
+-------------+
| |
+-------------+

各Descriptorにはフォーマットによって以下の種類に分けられる。

表1 IDTに格納されるGateの種類
Descriptor種別
用途
Interrupt gateハンドラへのポインタを保持しており、当該ベクタの例外/割り込みが発生すると指定したハンドラへ飛ぶ。
Trap gate
ハンドラへのポインタを保持しており、当該ベクタの例外/割り込みが発生すると指定したハンドラへ飛ぶ。(*1)
Task gate
TSSセグメントセレクタでGDT内のTSSディスクリプタを選択し、該当TSSのタスクにタスクスイッチする。Task gateはタスクスイッチのために使われるが、IDTの中で使用して例外/割り込み処理にタスクスイッチすることもできる。(*2)
(*1) Interrupt gateとTrap gateは同じ様なものだが、Interrupt gate経由でハンドラに飛んだ場合は、EFLAGSレジスタのIFフラグをクリアして割り込みが抑止される点がことなる。

(*2) あえて複雑なTask gateを使うメリットとしては、TSSが切り替わるため割り込みハンドラ用に新しいスタックを使用できてシステムの安全性を高めることができることなどがある。ただし、Interrupt gateやTrap gateの方が軽いので通常はそちらを使う。Linuxではダブルフォルト例外の時にしか使っていない。


各ディスクリプタを設定するルーチンには以下のものがある。
set_intr_gate()
set_system_intr_gate()
set_trap_gate()
set_system_gate()
set_task_gate()


表2 trap_init()のidt_table設定内容(一部)
ベクタ番号種類
Descr.形式
エントリルーチン
0
0除算Trap
divide_error
8
ダブルフォルト
Task
doublefault_fn (*1)
14
ページフォルトInterrupt
page_fault
80h
システムコール(int80h)
Trap
system_call

(*1) このエントリはTask Gateなのでハンドラには直接ジャンプしない。このTask GateにはTSSセグメントセレクタにGDT_ENTRY_DOUBLEFAULT_TSS(31)が設定されており、GDT_ENTRY_DOUBLEFAULT_TSSで定義されるTSSに飛ぶ。GDT_ENTRY_DOUBLEFAULT_TSSのTSS実体はdoublefault_tssで.eipにdoublefault_fnが設定されているため、最終的に本ハンドラに飛ぶ。


最終更新 2006/06/24 19:04:34 - kztomita
(2006/03/27 12:49:42 作成)