Linux Kernel(2.6)の実装に関するメモ書き

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が設定されている。





最終更新 2010/11/17 00:44:37 - kztomita
(2010/11/17 00:44:37 作成)


リンク
最近更新したページ
検索