說明:此博文是Kernel有關GDT,LDT以及LDT的相關源碼剖析,而對有關GDT,LDT以及IDT的詳細說明以及原理講解都可以在Intel IA-32架構手冊中查到。這裡不再贅述,(手冊地址) 1、描述符(64bits)分類
2、三者的關係
a、GDT,IDT都是全域的。LDT是局部的(在GDT中有它的描述符)
b、GDT用來儲存描述符(門或非門);系統中幾個CPU,就有幾個GDT
struct gdt_page { struct desc_struct gdt[GDT_ENTRIES];} __attribute__((aligned(PAGE_SIZE)));DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
c、IDT整個系統只有一個
d、系統啟動時候需要初始化GDT和IDT。LDT和進程相關,並不一定必有
3、IA-32各種描述符的結構
4、描述符結構定義
<arch/x86/include/asm/desc_defs.h>
struct desc_struct { union { struct { unsigned int a; unsigned int b; }; struct { u16 limit0; u16 base0; unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1; unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8; }; }; } __attribute__((packed));
聯合體——對成員域訪問和設定成為一種很優美的方法。上面第一個匿名結構體用來作為成員訪問取值的出口,下面第二個結構體對真實的成員設定值的入口。
欄位(結合上面的圖示):
limit:段長度
base:段的首位元組的線性地址,有base0,base1,base2三部分構成
type:段的類型和存取許可權
s:系統標誌。1-系統段;0-普通段
dpl:描述符特權級
p:segment-Present。linux下總是1
avl:linux不用
d:區分程式碼片段還是資料區段
g:段大小粒度。以4K倍數計算
在32位機器上,這就是所有描述符的資料結構嘍,沒有細分門和非門。
typedef struct desc_struct gate_desc;typedef struct desc_struct ldt_desc;typedef struct desc_struct tss_desc;
由於三類描述符都是一個結構類型,從而一律使用下面宏初始化在GDT中表項
#define GDT_ENTRY_INIT(flags, base, limit) { { { \ .a = ((limit) & 0xffff) | (((base) & 0xffff) << 16), \ .b = (((base) & 0xff0000) >> 16) | (((flags) & 0xf0ff) << 8) | \ ((limit) & 0xf0000) | ((base) & 0xff000000), \ } } }
但是在64位機器上,Linux則進行了細緻劃分:
16位元組門描述符結構
/* 16byte gate */struct gate_struct64 { u16 offset_low; u16 segment; unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1; u16 offset_middle; u32 offset_high; u32 zero1;} __attribute__((packed));
16位元組LDT或TSS描述符結構
/* LDT or TSS descriptor in the GDT. 16 bytes. */struct ldttss_desc64 { u16 limit0; u16 base0; unsigned base1 : 8, type : 5, dpl : 2, p : 1; unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8; u32 base3; u32 zero1;} __attribute__((packed));
typedef struct gate_struct64 gate_desc;typedef struct ldttss_desc64 ldt_desc;typedef struct ldttss_desc64 tss_desc;
從上面代碼看出無論是32位還是64位機器上,都使用typedef重新定義,以提供給系統其他使用此描述符的部分一致的類型名
區分描述符的枚舉量
enum { GATE_INTERRUPT = 0xE, GATE_TRAP = 0xF, GATE_CALL = 0xC, GATE_TASK = 0x5,};
enum { DESC_TSS = 0x9, DESC_LDT = 0x2, DESCTYPE_S = 0x10, /* !system */};
系統GDT,IDT指標描述結構
struct desc_ptr { unsigned short size; unsigned long address;} __attribute__((packed)) ;這個結構記錄了系統的GDT或者IDT的大小以及在系統中的線性基地
Reference:
<arch/x86/include/asm/desc_defs.h>
http://www.osdever.net/tutorials/pdf/descriptors.pdf。