2009年7月19日日曜日

setup_idt/setup_gdt

go_to_protected_mode関数のつづきを見ていきましょう。
まずは割り込みハンドラを登録するためのInterrupt Description Tableをセットするsetup_idtです。

arch/x86/boot/pm.c
=====

static void setup_idt(void)
{
static const struct gdt_ptr null_idt = {0, 0};
asm volatile("lidtl %0" : : "m" (null_idt));
}

=====
ここでは何も定義していないダミーのIDTを用意して、lidtl命令でロードしています。
ちゃんとしたものを後で登録するのだと思います。
次はセグメントを登録するためのGlobal Description Tableをセットするsetup_gdtです。

=====

static void setup_gdt(void)
{
static const u64 boot_gdt[] __attribute__((aligned(16))) = {
/* CS: code, read/execute, 4 GB, base 0 */
[GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
/* DS: data, read/write, 4 GB, base 0 */
[GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
/* TSS: 32-bit tss, 104 bytes, base 4096 */
/* We only have a TSS here to keep Intel VT happy;
we don't actually use it for anything. */
[GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
};
/* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead
of the gdt_ptr contents. Thus, make it static so it will
stay in memory, at least long enough that we switch to the
proper kernel GDT. */
static struct gdt_ptr gdt;

gdt.len = sizeof(boot_gdt)-1;
gdt.ptr = (u32)&boot_gdt + (ds() << 4);

asm volatile("lgdtl %0" : : "m" (gdt));
}

=====
最初にGDTを定義して最後にlgdtl命令でGDTをロードしています。
ここで設定しているGDTは以下のような設定になっています。

CS:コードセグメント、読み込み/実行用、0開始で4GB
DS:データセグメント、読み込み/書き込み、0開始で4GB
TSS:4096開始で104バイト。

TSSはタスクスイッチの際に実行中のタスク情報を退避させておく領域です。
ここで設定しているGDTもおそらくIDTと同じように暫定的な設定だと思います。

0 件のコメント:

コメントを投稿