加载全局/中断描述符表

来源:互联网 发布:python ssh执行.sh 编辑:程序博客网 时间:2024/05/01 06:04

4.2 start_kernel进发

分段、分页单元完成以后,我们的0号进程的运行环境就初步搭建起来了,那么就要“走向现代”,去调用start_kernel了,调用它之前还有几个重要的步骤要走。

 

4.2.1 加载全局/中断描述符表

很多人就有疑问, 刚才我们设置好了中断描述符表,那内核怎么用它呢?不好意思,刚才在略过了的checkCPUtype过程中有一步非常重要的步骤,现在把它补上:

418 is386:      movl $2,%ecx        # set MP

419 2:     movl %cr0,%eax

420        andl $0x80000011,%eax       # Save PG,PE,ET

421        orl %ecx,%eax

422        movl %eax,%cr0

423

424        call check_x87

425        lgdt early_gdt_descr

426        lidt idt_descr

427        ljmp $(__KERNEL_CS),$1f

428 1:     movl $(__KERNEL_DS),%eax    # reload all the segment registers

429        movl %eax,%ss                    # after changing gdt.

430

431        movl $(__USER_DS),%eax         # DS/ES contains default USER segment

432        movl %eax,%ds

433        movl %eax,%es

434

435        movl $(__KERNEL_PERCPU), %eax

436        movl %eax,%fs                    # set this cpu's percpu

 

425行重新加载一个全局描述符表early_gdt_descr

707 ENTRY(early_gdt_descr)

708        .word GDT_ENTRIES*8-1

709        .long gdt_page                     /* Overwritten for secondary CPUs */

 

同样也是包含段限和全局描述符表地址,gdt_pagearch/x86/include/asm/desc.h定义:

 

  35

  36struct gdt_page {

  37        struct desc_struct gdt[GDT_ENTRIES];

  38} __attribute__((aligned(PAGE_SIZE)));

 

为什么需要重新加载一个全局描述符表很简单因为现在起到分页了所以要重新定位全局描述符表的位置而由于aligned(PAGE_SIZE)所以gdt_page正好是一个页面的开始位置。GDT_ENTRIES的值是32,定义在arch/x86/include/asm/segment.h

110#define GDT_ENTRIES 32

 

所以全局描述符表式每个表项为desc_struct结构的,32个表项的数组,它的每个表项是:

  22struct desc_struct {

  23        union {

  24                struct {

  25                        unsigned int a;

  26                        unsigned int b;

  27                };

  28                struct {

  29                        u16 limit0;

  30                        u16 base0;

  31                        unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;

  32                        unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;

  33                };

  34        };

  35} __attribute__((packed));

 

正好看到第二个联合体,熟悉吧,描述符结构。哦,你不熟悉,那就看看博客“Intel 80286工作模式” http://blog.csdn.net/yunsongice/archive/2010/10/04/5920447.aspx8个字节,所以gdt表共占8*32=256个字节,相对于一个页面的4096字节,仅仅占了一个页面前1/16的空间。

 

回到426行,把我们刚才设置好的中断门描述符表idt_descr通过lidt加载上,然后427~436行分别将段选择子__KERNEL_CS__KERNEL_DS__USER_DS__KERNEL_PERCPU加载到寄存器csssds/esfs。注意这里一个细节,加载cs寄存器重来都不使用mov指令,而是通过ljmp $(__KERNEL_CS),$1f来设置。还有,这时候,gdt是早已初始化了的。

 

原创粉丝点击