diff --git a/study/kernel/03-vmarea/00-code/02-gdt_table/get_gdt_table.c b/study/kernel/03-vmarea/00-code/02-gdt_table/get_gdt_table.c index 7de0d0e..04be244 100644 --- a/study/kernel/03-vmarea/00-code/02-gdt_table/get_gdt_table.c +++ b/study/kernel/03-vmarea/00-code/02-gdt_table/get_gdt_table.c @@ -22,14 +22,167 @@ MODULE_LICENSE("Dual BSD/GPL"); #define bit_clr(number, pos) ((number) &= ~(1 << (pos))) /// 把某位清0 #define bit_cpl(number, pos) ((number) ^= 1 << (pos)) /// 把number的POS位取反 + + +/* + * 打印段描述符的数据 + * desc 指向GDT的指针 + */ +static void print_desc_struct(struct desc_struct *desc) +{ +#if 0 + printk("limit0 = %0x, ", desc->limit0); + printk("base0 = %0x, ", desc->base0); + + printk("base1 = %0x, ", desc->base1); + printk("type = %0x, ", desc->type); + printk("s = %0x, ", desc->s); + printk("dpl = %0x, ", desc->dpl); + printk("p = %0x, ", desc->p); + + printk("limit = %0x, ", desc->limit); + printk("avl = %0x, ", desc->avl); + printk("l = %0x, ", desc->l); + printk("d = %0x, ", desc->d); + printk("g = %0x, ", desc->g); + + printk("base2 = %0x\n", desc->base2); +#endif +/* +段描述符 +---------------------------------------------------------------------------------------- +63 56/55 52/51 48/47 40/39 32/31 16/15 0 +---------------------------------------------------------------------------------------- +| B31-B24 | G D/B O AV | L19-L16 | P DPL S E ED/C R/W A | B23-B16 | B15-B0 | L15-L0 | +---------------------------------------------------------------------------------------- + | | | | | | | | | | | + | | | | | | | --------- | + | | | | | | | | | + | | | | | | | | ------------ = 1, 已被访问过 + | | | | | | | | + | | | | | | | | |-- E = 0, 数据段 + | | | | | | | | ------|-- ED = 0, 向上延伸(数据段); ED = 1, 向下延伸(堆栈段) + | | | | | | | | | |-- W = 0, 不可写入; W = 1, 可写入 + | | | | | | | ----------| + | | | | | | | | |-- E = 1, 代码段 + | | | | | | | ------|-- C = 0, 忽视特权级别; C = 1, 依照特权级别 + | | | | | | | |-- R = 0, 不能读; R = 1, 可读 + | | | | | | | + | | | | | | | |-- = 0, 表示专用于系统管理的系统段, 如各类描述表 + | | | | | | |---------------------| + | | | | | | |-- = 1, 表示用于一般的代码段或者数据段 + | | | | | | + | | | | | ---------------------------- 特权级别 + | | | | ------------------------------- = 1, 表示该段在内存中 + | | | | + | | | | + | | | -------- 可由软件使用, CPU忽略该位 + | | ----------- 永远为0 + | -------------- = 1, 表示对该段的访问为32位指令; = 0, 为16位指令 + ----------------- = 1, 段长以4K字节为单位; = 0, 以字节为单位 + +*/ + +#define get_desc_struct_BASE0(gdt) (((gdt) >> 16) & 0xffff) +#define get_desc_struct_BASE1(gdt) (((gdt) >> 32) & 0xff) +#define get_desc_struct_BASE2(gdt) (((gdt) >> 56) & 0xff) +#define get_desc_struct_BASE(gdt) \ + ((get_desc_struct_BASE0(gdt) << 16) \ + | (get_desc_struct_BASE1(gdt) << 8) \ + | (get_desc_struct_BASE2(gdt))) + + +#define get_desc_struct_LIMIT0(gdt) ((gdt) & 0xffff) +#define get_desc_struct_LIMIT1(gdt) (((gdt) >> 48) & 0x0f) +#define get_desc_struct_LIMIT(gdt) \ + ((get_desc_struct_LIMIT0(gdt) << 4) \ + | (get_desc_struct_LIMIT1(gdt))) + +#define get_desc_struct_G(gdt) (((gdt) >> 55) & 0x01) /* 55 */ +#define get_desc_struct_D_or_B(gdt) (((gdt) >> 54) & 0x01) /* 54 */ +#define get_desc_struct_O(gdt) (((gdt) >> 53) & 0x01) /* 53 */ +#define get_desc_struct_AV(gdt) (((gdt) >> 52) & 0x01) /* 52 */ +#define get_desc_struct_P(gdt) (((gdt) >> 47) & 0x01) /* 47 */ +#define get_desc_struct_DPL(gdt) (((gdt) >> 45) & 0x03) /* 46-45 */ +#define get_desc_struct_S(gdt) (((gdt) >> 44) & 0x01) /* 44 */ +#define get_desc_struct_E(gdt) (((gdt) >> 43) & 0x01) /* 43 */ +#define get_desc_struct_ED_or_C(gdt) (((gdt) >> 42) & 0x01) /* 42 */ +#define get_desc_struct_R_or_W(gdt) (((gdt) >> 41) & 0x01) /* 41 */ +#define get_desc_struct_A(gdt) (((gdt) >> 40) & 0x01) /* 40 */ + + + printk("0x%08x, 0x%08x | 0x%x | %d | %d |\n", + desc->b, desc->a, desc->type, desc->dpl, desc->s); + unsigned long data = *((unsigned long *)desc); + printk("base = 0x%0x, limit = 0x%0x, P = %d, DPL = %d, type = %d%d%d%d\n", + get_desc_struct_BASE(data), get_desc_struct_LIMIT(data), + get_desc_struct_P(data), get_desc_struct_DPL(data), + get_desc_struct_S(data), get_desc_struct_ED_or_C(data), + get_desc_struct_R_or_W(data), get_desc_struct_A(data)); +} + + +/* + * 打印 CPU 的 GDT 的数据 + * 参数 + * cpu : CPU 的编号 + */ +static void print_cpu_gdt_table(unsigned int cpu) +{ + int i = 0; + struct desc_struct *gdt_table = get_cpu_gdt_table(cpu); + + + printk("GDT_ENTRIES = %d\n", GDT_ENTRIES); + printk("-----------------------------------\n"); + printk("|\t\t\t\t| type | dpl | s |\n"); + for(i = 0; i < GDT_ENTRIES; i++) + { + printk("| [%0x] = ", i); + print_desc_struct(gdt_table + i); + } + printk("-----------------------------------\n"); + +} + +/* + * 打印段选择符和段描述符号的信息 + * + * 段标识符(段选择符)(存放在段寄存器中)字段如下 : + * index 用来得到段描述符在GDT或LDT中的偏移(位置) + * TI 指明段描述符是在GDT中(TI=0)或在LDT中(TI=1) + * RPL 请求特权级, + * + * 由于一个段描述符是8字节, + * 因此它的地址=GDT或LDT内的首地址+(index*8). + * 能够保存在GDT中的段描述符的最大数目是8191(213-1),其中13是index的位数. + * 不同段的段描述符构成段描述符表, + * 段描述符(8字节)存放在全局描述符表(GDT)或局部描述符表(LDT)中 + * GDT在主存中的地址和大小存放在gdtr控制寄存器中, + * 当前正被使用的LDT地址和大小存放在ldtr控制寄存器中。 + */ +static void print_segment_desc(unsigned long seg) +{ #define get_segment_INDEX(n) ((n) >> 3) #define get_segment_TI(n) (((n) >> 2) & 0x01) #define get_segment_RPL(n) ((n) & 0x03) + printk("0x%0x, index = %d, TI = %d, RPL = %d\n", seg, + get_segment_INDEX(seg), + get_segment_TI(seg), + get_segment_RPL(seg)); +} + // http://lxr.free-electrons.com/source/arch/x86/include/asm/segment.h#L123 +/* + * 打印 Linux 内核中分段信息, + * 打印段描述 + */ static void print_segment(void) { - long data = 0; + long data = 0; + struct desc_struct *gdt_table = get_cpu_gdt_table(1); + /* --------------------------------------------------------------------------------------------- @@ -51,79 +204,55 @@ static void print_segment(void) __USER_DS = 0x0033 = | 00110011 00000000 | __USER_DS = 0x002B = | 00101011 00000000 | */ - data = __KERNEL_CS; - printk("__KERNEL_CS = %0x, index = %d, TI = %d, RPL = %d\n", data, - get_segment_INDEX(data), - get_segment_TI(data), - get_segment_RPL(data)); + printk("=====================\n"); + // 打印__KERNEL_CS的段描述符 + printk("__KERNEL_CS = "); + print_segment_desc(__KERNEL_CS); + // 打印__KERNEL_CS在gdt_table中的具体值 + printk("__KERNEL_CS @ index(%d) in cpu_gdt_table\n", get_segment_INDEX(__KERNEL_CS)); + printk("GDT[%d] = ", get_segment_INDEX(__KERNEL_CS)); + print_desc_struct(gdt_table + get_segment_INDEX(__KERNEL_CS)); + printk("=====================\n\n"); - data = __KERNEL_DS; - printk("__KERNEL_DS = %0x, index = %d, TI = %d, RPL = %d\n", data, - get_segment_INDEX(data), - get_segment_TI(data), - get_segment_RPL(data)); + printk("=====================\n"); + // 打印__KERNEL_DS的段描述符 + printk("__KERNEL_DS = "); + print_segment_desc(__KERNEL_DS); + // 打印__KERNEL_DS在gdt_table中的具体值 + printk("__KERNEL_DS @ index(%d) in cpu_gdt_table\n", get_segment_INDEX(__KERNEL_DS)); + printk("GDT[%d] = ", get_segment_INDEX(__KERNEL_DS)); + print_desc_struct(gdt_table + get_segment_INDEX(__KERNEL_DS)); + printk("=====================\n\n"); - data = __USER_CS; - printk("__USER_CS = %0x, index = %d, TI = %d, RPL = %d\n", data, - get_segment_INDEX(data), - get_segment_TI(data), - get_segment_RPL(data)); - - data = __USER_DS; - printk("__USER_DS = %0x, index = %d, TI = %d, RPL = %d\n", data, - get_segment_INDEX(data), - get_segment_TI(data), - get_segment_RPL(data)); -} - - -static void print_desc_struct(struct desc_struct *desc) -{ -#if 0 - printk("limit0 = %0x, ", desc->limit0); - printk("base0 = %0x, ", desc->base0); - - printk("base1 = %0x, ", desc->base1); - printk("type = %0x, ", desc->type); - printk("s = %0x, ", desc->s); - printk("dpl = %0x, ", desc->dpl); - printk("p = %0x, ", desc->p); - - printk("limit = %0x, ", desc->limit); - printk("avl = %0x, ", desc->avl); - printk("l = %0x, ", desc->l); - printk("d = %0x, ", desc->d); - printk("g = %0x, ", desc->g); - - printk("base2 = %0x\n", desc->base2); -#endif - printk("0x%08x, 0x%08x | 0x%x | %d | %d |\n", - desc->b, desc->a, desc->type, desc->dpl, desc->s); -} - - -static void print_cpu_gdt_table(struct desc_struct *desc, int size) -{ - int i = 0; - printk("-----------------------------------\n"); - printk("|\t\t\t\t| type | dpl | s |\n"); - for(i = 0; i < size; i++) - { - printk("| [%0x] = ", i); - print_desc_struct(desc + i); - } - printk("-----------------------------------\n"); + printk("=====================\n"); + // 打印__USER_CS的段描述符 + printk("__USER_CS = "); + print_segment_desc(__USER_CS); + // 打印__USER_CS在gdt_table中的具体值 + printk("__USER_CS @ index(%d) in cpu_gdt_table\n", get_segment_INDEX(__USER_CS)); + printk("GDT[%d] = ", get_segment_INDEX(__USER_CS)); + print_desc_struct(gdt_table + get_segment_INDEX(__USER_CS)); + printk("=====================\n\n"); + printk("=====================\n"); + // 打印__USER_DS的段描述符 + printk("__USER_DS = "); + print_segment_desc(__USER_DS); + // 打印__USER_DS在gdt_table中的具体值 + printk("__USER_DS @ index(%d) in cpu_gdt_table\n", get_segment_INDEX(__USER_DS)); + printk("GDT[%d] = ", get_segment_INDEX(__USER_DS)); + print_desc_struct(gdt_table + get_segment_INDEX(__USER_DS)); + printk("=====================\n\n"); } static int hello_init(void) { - printk("GDT_ENTRIES = %d\n", GDT_ENTRIES); - struct desc_struct *gdt_table = get_cpu_gdt_table(1); - print_cpu_gdt_table(gdt_table, GDT_ENTRIES); + print_cpu_gdt_table(0); print_segment(); + + return 0; }