GDT設定
GDT(Global Descriptor Table)の設定はarch/i386/kernel/head.Sで行われている(v2.6.11)。
ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x0000000000000000 /* 0x0b reserved */ <略> .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */ .quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */ .quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */ <略>
v2.6.30だとarch/x86/kernel/cpu/common.cでテーブルを作成している。作成したテーブルの読み込みはswitch_to_new_gdt()で行われる。
DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #ifdef CONFIG_X86_64 /* * We need valid kernel segments for data and code in long mode too * IRET will check the segment types kkeil 2000/10/28 * Also sysret mandates a special GDT layout * * TLS descriptors are currently at a different place compared to i386. * Hopefully nobody expects them at a fixed place (Wine?) */ [GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } }, [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } }, [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } }, [GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } }, [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, #else [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } },
32bit環境ではCS(Code Segment)、DS(Data Segment)ともベースアドレスを0、リミットを上限いっぱいに設定することで、4GBのフラットなリニアアドレス空間を共有している。
64bit環境の場合は32bitプロセスも動作させるために、CS(Code Segment)は64bitと32bitの両方が存在する。64bitと32bitのセグメントディスクリプタの違いはL bitが立っているか否かになる。
64bitモードではセグメンテーション(limitチェック等)は行われないため、Segment Limitフィールドは意味がないが、32bit用のディスクリプタと同じようにAll 0xfが設定されている。