IDTUtil.cpp IDT Interrupt Descriptor Table IDTUtil::setup() 割り込みデスクリプタテーブルを設定する。g_idtは割り込みデスクリプタテーブルの 起点を表す。割り込みデスクリプタテーブルは64Bitsあって次のような様式になっている。 0..15:割り込みプロシージャのオフセットの下位16ビット 16..31:割り込みプロシージャがあるセグメントを指すセレクタ 32..36:予約     | 37..39:0にしておく |unused 40..44:タイプ    | 45..46:DPL      | 47..47:存在フラグ  |type 48..63:割り込みプロシージャのオフセットの上位16ビット 割り込みデスクリプタテーブルにはタスクゲート、割り込みゲート、 トラップゲートの3種類のゲートデスクリプタを格納できる。これらのゲートの違いは タイプフィールドの値で決める。 タスクゲート :00101b 割り込みゲート:0D110b トラップゲート:0D111b ここで、Dはゲートサイズを表し、D=1なら32ビットになりD=0であれば16ビットになる。 これらの値はsetGateDesc関数で設定される。割り込みプロシージャのセグメントとオフセットは パラメータで指定されるが、タイプはこの関数の中で自動的に決定される。 割り込みベクタ番号が0x80の場合は0xEE、つまり、11101110bになる。 これはデスクリプタが存在して、デスクリプタ特権レベルが3(一番低い)になっていて、 ゲートが32ビットの割り込みゲートであることを意味する。デスクリプタ特権レベルが 3ということはユーザープロセスから使用できるということである。 この割り込みはシステムコールとして利用される。 一方その他の割り込みはタイプが0x8E、つまり、10001110bになる。意味するところは デスクリプタ特権レベルが0(一番高い)になっていることを除けば0x80の 割り込みデスクリプタと同様である。 割り込みプロシージャの開始アドレスはhandlersに収められている。これはihandlers.cppで 定義されて、ihandlers.asmとともに適切な割り込みを定義している。 void IDTUtil::setup() { g_idt = (GateDesc*)malloc(sizeof(GateDesc) * IHANDLER_NUM); extern InterruptHandlers handlers[IHANDLER_NUM]; for (int i = 0; i < IHANDLER_NUM; i++) { setGateDesc(g_idt, KERNEL_CS, &handlers[i]); } /* lidt */ IDTR idtr; idtr.base = (dword)g_idt; idtr.limit = sizeof(GateDesc) * IHANDLER_NUM - 1; lidt(&idtr); return; } void IDTUtil::setGateDesc(GateDesc* descZero, word selector, InterruptHandlers* handler) { GateDesc* desc = descZero + handler->number; desc->offsetL = (dword)(handler->handler) & 0x0000FFFF; desc->offsetH = ((dword)(handler->handler) & 0xFFFF0000) >> 16; desc->selector = selector; desc->type = handler->number == 0x80 ? 0xEE : 0x8E; /* System call use 0x80 */ desc->unused = 0x00; return; }