Linux Kernel (v 0.11)源代码解读-head.s

Study Linux Kernel Notes(v 0.11)                        Shawn.Xie
                                                                                 Shawshie@msn.com


                                                       
3.  Head.s

 3.1  Procedure OverView

   (1) 初始化ds, es, fs, gs选择子,均指向在setup.s中建立起的数据段描述符。

   -----------------------------------------------------------------------------
    386全局描述符详解

      63          56 55 54 53 52 51   48 47 46 45 44 43 41 40 39             16 15               0
      +-------------+--+--+-----+-------+--+-----+--+----+--+------------------+-----------------+
      |Seg Base Addr|G |D | 0 0 |Seg Len|P | DPL |S |TYPE| A| Seg Base Addr    |  Segment Length |
      +-------------+--+--+-----+-------+--+-----+--+----+--+------------------+-----------------+

      属性字节中各字段的含义如下:
      286/386共有部分:
      P ------ 该字节最高位(D7),占一位。用以确定此段是否存在于物理存储器中。P=1,表示在物理存储器中;P=0,在虚拟内存
      DPL ---- 该字节D6, D5位,占两位。描述符所定义的段的特权级,其值为0 --- 3
      S ------ 该字节D4位,占一位。当S=1时,定义的段为代码段或数据段;S=0时,表示该描述符为系统控制描述符。
      TYPE---- 该字节D3,D2 ,D1位,占三位。用于规定该段的的类型:是代码段还是数据段,及相应属性。
                   当D3=1时,为代码段;D3=0时,为数据段。
                   当D3=1时,表示该段为代码段,这时
                       D2=0,当CPL>=DPL时,代码段只能执行
                       D1=0,代码段不能读;D1=1,代码段可读
      A ------- 用于判断该段是否被访问过。当A=0时,未被访问过;否则A=1。该标志用于虚拟存储操作系统中,虚拟内存的交换。该位由操行系统进行修改。

      386新增部分:
      51-48 -- 新增的4位段长                                                                  
      53-52 -- 为与将来的处理器兼容必须设置=0                                                 
      D ------ D位,缺省操作数的大小(仅在代码段描述符中识别)。D=1表示32位段   ; D=0表示16位段
      G ------ G位,表示粒度:G=1表示段长度为页粒度、G=0表示段长度为字节粒度                   

     In setup.s, such as the following:
      Text Segment:
        .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
        .word   0x0000          ! base address=0
        .word   0x9A00          ! code read/exec
        .word   0x00C0          ! granularity=4096, 386
     
        G=1          : 表示段长度为页粒度
        D=1          : 表示32位段
        P=1          : 表示在物理存储器中
        DPL=0        : 段的特权级 0
        S=1          : 定义的段为代码段或数据段 
        TYPE=101b    : D3=1时,为代码段;
                       D2=0,当CPL>=DPL时,代码段只能执行
                       D1=1,代码段可读
        A=0          : 用于虚拟存储操作系统中,虚拟内存的交换,该位由操行系统进行修改
        Seg Base Addr: base address=0
        Segment Len  : 0x7ff    

      Data Segment: (2048*4096=8Mb)
        .word 0x07FF         ! 8Mb - limit=2047 (2048*4096=8Mb)
        .word 0x0000         ! base address=0                 
        .word 0x9200         ! data read/write                
        .word 0x00C0         ! granularity=4096, 386          
   -----------------------------------------------------------------------------

   -----------------------------------------------------------------------------
    386选择子详解
   
      15                3  2 1 0
      +------------------+--+---+
      |       Index      |TI|RPL|
      +------------------+--+---+
 
      其中:                                                                                                                             
      RPL --------- 构成选择子特权(数0---3),表示所请求的物权层RPL。                                                                   
      TI  --------- 表指示器,表示选择子选择的是全局描述符表或是局部描述符表。TI=0,表示选择的是全局描述符表;TI=1,表示选择局部描述符表。
      索引--------- 形成描述符表的入口索引,可寻址8K个描述符。(2^13 = 8K)                                                                
   
    _pg_dir:              
    startup_32:           
     movl $0x10,%eax
     mov %ax,%ds   
     mov %ax,%es   
     mov %ax,%fs   
     mov %ax,%gs
    
    Index = 2       对应于数据段描述符
    TI    = 0            表示选择的是全局描述符表
    RPL   = 0       表示所请求的物权层RPL 0
   -----------------------------------------------------------------------------
  
   (2) 初始化堆栈指针, 指向全局数组变量  long user_stack [ PAGE_SIZE>>2 ],大小为4K
 
   (3) 建立IDT
       -------------------------------------------------------------------------
        中断门详解:
        63             48 47 46 45 44 4341 40 39 32  31         16 15               0
        +----------------+--+-----+--+----+--+------+-------------+-----------------+
        |   Invalid      |P | DPL |S |TYPE| A|      | Selector    |  Shift          |
        +----------------+--+-----+--+----+--+------+-------------+-----------------+
       
        字节0 ------ 字节1        偏移量                             
        字节2 ------ 字节3        2个字节共16位,目标选择子          
        字节4 ------              此字段无效,可为任意值             
        字节5 ------              段的属性,包含P、DPL、S、TYPE等字段
        字节6 ------ 字节7        286未用,保留给386使用             
      
       IDT0~255:  0x0000 8E00 0008 &ignore_int

        P=1:  表示在物理存储器中
        DPL=0:描述符所定义的段的特权级 0
        S=0       表示该描述符为系统控制描述符。
        TYPE=111b D3=1,为代码段
                  D2=1,D2=0,当CPL>=DPL时,代码段只能执行。D2=1则不受限制
                  D1=1,代码段可读
        A 用于判断该段是否被访问过
        Selector 0x0008 
            Index = 1       对应于代码段描述符             
            TI    = 0            表示选择的是全局描述符表
            RPL   = 0       表示所请求的物权层RPL 0
        Shift = &ignore_int 表示跳到ignore_int执行   
       -------------------------------------------------------------------------
        
   (4) 重新建立GDT,数据段和代码段扩大到16Mb     
      
       _gdt:
        .quad 0x0000000000000000 /* NULL descriptor */       
        .quad 0x00c09a0000000fff /* 16Mb */                
        .quad 0x00c0920000000fff /* 16Mb */                
        .quad 0x0000000000000000 /* TEMPORARY - don't use */
       
   (5) GDT重新建立之后,重新初始化各个段选择子,以及堆栈段。
  
   (6) 验证A20是否使能,否则进入死循环。
       (6.1) 验证值=0
       (6.2) 验证值+1,往 0x0地址写验证值,再读出0x100000的值,看看是否等于验证值,如果不是,跳出;否则,继续。

   (7) 判断协处理器是否存在,不存在的话,模拟协处理器,执行协处理器的指令。存在话直接执行
       287的协处理器码0xDBE4。
  
       -------------------------------------------------------------------------
        80386中有3个32位的控制寄存器CR0、CR2、CR3,以保存全局性(不是特定的个别任务)
        的机器状态(CR1 保留)。
       
        CR0.MP ------ 监控协处理器,第1位。MP位和TS位一起使用以确定在TS=1时,WAIT操作
        码是否产生协处理器无效陷阱(异常7)。即当MP=1且TS=1时,WAIT操作码产生陷阱;否则,
        WAIT操作码不产生陷阱。
       -------------------------------------------------------------------------
      
       协处理器不知道怎么下发指令,先不管它了。
      
   (8) 将0L,0L,0L,&L6,&main压栈
  
   (9) 初始化页表机制
  
       (9.1) 将0x0000 - 0x5000的空间清零。
       (9.2) 初始化页目录表
                页表目录项 * 4
                页表项     * 1024
             将16M的内存空间分成 4K 页
            
       (9.3) CR3 = 0    第一个页目录
             CR1.PG = 1 使能页表机制
            
   (10) 函数返回,堆栈弹出main,执行main。
                     
               ~ ~ ~ ~ ~ ~ ~ ~ ~
              |                  |
        ----- +------------------+ 0x5000 _tmp_floppy_area
          |   | 0xfff007         |
        Page  | 0xffe007         |
        Table | ...              |
          |   | 0xf00007         | <----- Page Table Entry * 1024
        ----- +------------------+ 0x4000 pg3 <-----+
              |                  |                  |
              +------------------+ 0x3000 pg2       |
              |                  |            ...   |
              +------------------+ 0x2000 pg1       |
              |                  |                  |
        ----- +------------------+ 0x1000 pg0 <--+  |
          |   |                  |               |  |
        Page  | pg3+7            | --------------|--+
        Dir   | pg2+7            | <----- Page Directory Entry
          |   | pg1+7            | ...           |
          |   | pg0+7            | --------------+
        ----- +------------------+ _pg_dir 


 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值