InterruptDescriptorTable
IDT(Interrupt Descriptor Table:割り込み記述子表)
IDTとは、割り込みと割り込みハンドラ(割り込みに対応する処理)を結びつけるテーブルです。
割り込み(キーボード押下やマウス操作など)が発生した場合に、どのような処理を実行するのかという情報を管理します。
プロテクトモードの場合、ゲート・ディスクリプタと呼ばれるデータ構造体を介してハンドラの処理に移行します。
(リアルモードの場合、割り込みベクターに記述された割り込みハンドラのアドレスを介して、ハンドラの処理を行います。)
IDTのゲート・ディスクリプタとは
ゲート・ディスクリプタとは、割り込みハンドラ関連情報を管理するデータ構造体です。
IDTは、ゲートディスクリプタの配列であり、最大256エントリを設定出来ます。
IDTには、3種類のゲート・ディスクリプタのいずれかがエントリされます。
- タスク・ゲート・ディスクリプタ
- 割り込みゲート・ディスクリプタ
- トラップ・ゲート・ディスクリプタ
割り込みゲート・ディスクリプタ
割り込みゲートディスクリプタは、以下のような構造体で表すことができます。
struct gate_descriptor{
unsigned short base_low; /* 割り込み時の実行関数アドレス下位16bit */
unsigned short selector; /* セグメントセレクタ */
unsigned char reserved; /* Intel予約領域 */
unsigned char flags; /* 割り込み種類識別用 */
unsigned short base_high; /* 割り込み時の実行関数アドレス上位16bit */
} __attribute__ ((packed));
typedef struct gate_descriptor gate_descriptor_t;
- reserved
- 予約領域は使用できないので、通常「0」を設定します。
flagsは以下の構造になります。
struct gatedesc_flags{
unsigned type:4; /* type */
unsigned s:1; /* descriptor type (0 for system segment) */
unsigned dpl:2; /* descriptor privilege level */
unsigned p:1; /* present bit */
};
- Pフラグ
- セグメントがメモリ内に存在しているか(P Flag=1)、または存在していないか(P Flag=0)を示します。
- DPL フラグ
- セグメントの特権レベル(アクセスの制御)を指定する。
- 特権レベルは0-3の範囲で指定でき、0が最高の特権レベルである。
- D フラグ
- ゲートのサイズ。(1=32bit,0=16bit)
IDTR (Interrupt Descriptor Tbale Register)
IDTRとは、IDTの先頭アドレスとサイズ(リミット)を記録するレジスタです。
CPUは割り込み処理を行う際、IDTRを参照して、IDTディスクリプタ・テーブルにアクセスして、割り込みハンドラのアドレスを取得します。
struct idtr{
unsigned short size; /* IDTのサイズ */
unsigned int base; /* IDTのアドレス */
} __attribute__ ((packed));
typedef struct idtr idtr_t;
LIDT命令
LIDT命令を使ってIDTRにIDTのサイズとアドレスを格納します。
static inline void
load_idtr(void)
{
__asm__ __volatile__("lidt %0" :: "m"(idtr));
}
割り込み処理の流れ
割り込みハンドラの呼び出しは以下の流れになります。
- 割り込み発生。
- IDTRを参照する。
- IDTを参照する。
- 割り込みハンドラを実行する。
- 割り込み発生前の状態に戻る。