日期:2014-05-16 浏览次数:20773 次
说明:此博文是Kernel有关GDT,LDT以及LDT的相关源码剖析,而对有关GDT,LDT以及IDT的详细说明以及原理讲解都可以在Intel IA-32架构手册中查到!这里不再赘述,(手册地址)
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和进程相关,并不一定必有
<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), \ } } }
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, };