Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1241197
  • 博文数量: 122
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4004
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-20 08:27
文章分类
文章存档

2016年(1)

2015年(21)

2014年(100)

分类: LINUX

2014-02-20 15:48:49


=============================================================
 CPU相关概念
=============================================================

 

------------------------------------------------------------
2 IA32:把80386以后的处理器统称为IA32(32
Bit Intel Architecture)。
-------------------------------------------------------------


2.1 寄存器

2.1.1 8个通用寄存器32位

2.1.2 6个段寄存器:存放段选择符,而不是段基址

2.1.2.1 用于LDT中的索引?

2.1.3 状态和控制寄存器

2.1.3.1 标志寄存器EFLAGS

标志寄存器EFLAGS存放有关处理器的控制标志
在这些标志位中,我们只介绍在Linux内核代码中常用且重要的几个标志位:
第8位TF(Trap Flag)是自陷标志,当将其置1时则可以进行单步执行。当指令执
行完后,就可能产生异常1的自陷(参看第四章)。也就是说,在程序的执行过程中,每
执行完一条指令,都要由异常1处理程序 (在Linux内核中叫做debug())进行检验。当
将第8位清0后,且将断点地址装入调试寄存器DR0~DR3时,才会产生异常1的自陷。
第12、13位IOPL是输入输出特权级位,这是保护模式下要使用的两个标志位。由于输
入输出特权级标志共两位,它的取值范围只可能是0、1、2和3共4个值,恰好与输入输出
特权级0~3级相对应。但Linux内核只使用了两个级别,即0和3级,0表示内核级,3
表示用户级。在当前任务的特权级CPL(Current Privilege Level)高于或等于输入输出
特权级时,就可以执行像IN、OUT、INS、OUTS、STI、CLI和LOCK等指令而不会产生异常13
(即保护异常)。在当前任务特权级CPL为0时,POPF(从栈中弹出至标志位)指令和中
断返回指令IRET可以改变IOPL字段的值。
第9 位IF(Interrupt Flag)是中断标志位,是用来表示允许或者禁止外部中断
(参看第四章)。若第9位IF被置为1,则允许CPU接收外部中断请求信号;若将IF位清
0,则表示禁止外部中断。在保护模式下,只有当第12、13位指出当前CPL为最高特权级时,
才允许将新值置入标志寄存器EFLAGS以改变IF位的值。
第10位DF(Direction Flag)是定向标志。DF位规定了在执行串操作的过程中,对
源变址寄存器ESI或目标变址寄存器EDI是增值还是减值。如果DF为1,则寄存器减值;
若DF为0,则寄存器值增加。
第14位NT是嵌套任务标志位。在保护模式下常使用这个标志。当IA32在发生中断和
执行CALL指令时就有可能引起任务切换。若是由于中断或由于执行CALL指令而出现了任
务切换,则将NT置为1。若没有任务切换,则将NT位清0。
第17位VM (Virtual 8086 Mode Flag)是虚拟8086方式标志,是IA32新设置的一
个标志位。表示IA32CPU是在虚拟8086环境中运行。如果IA32CPU是在保护模式下运行,
而VM为又被置成1,这时IA32 就转换成虚拟8086 操作方式,使全部段操作就像是在
8086CPU上运行一样。VM位只能由两种方式中的一种方式给予设置,即或者是在保护模式
下,由最高特权级(0)级代码段的中断返回指令IRET设置,或者是由任务转换进行设
置。Linux内核实现了虚拟8086方式,但在本书中我们不准备对此进行详细讨论。
从上面的介绍可以看出,要正确理解标志寄存器EFLAGS的各个标志需要很多相关的
知识,有些内容在本章的后续部分还会涉及到。在后面的章节中,你会体会如何灵活应用
这些标志。
 


2.1.3.2 4个控制寄存器CR0,CR1,CR2,CR3

CR0中包含了6个预定义标志,0位是保护允许位PE(Protedted Enable),用于启动保
护模式,如果PE位置1,则保护模式启动,如果PE=0,则在实模式下运行

CR1是未定义的控制寄存器,供将来的处理器使用。
CR2是页故障线性地址寄存器,保存最后一次出现页故障的全32位线性地址。
CR3是页目录基址寄存器,保存页目录表的物理地址,页目录表总是放在以4K字节
为单位的存储器边界上,因此,它的地址的低12位总为0,不起作用,即使写上内容,也
不会被理会。
这几个寄存器是与分页机制密切相关的,因此,在进程管理及虚拟内存管理中会涉
及到这几个寄存器,读者要记住CR0、CR2及CR3这三个寄存器的内容。


2.1.3.2.1 CR3存放页目录表的地址

2.1.3.2.1.1 与段描述符无关

2.1.3.3 指令指针EIP

指令指针寄存器EIP中存放下一条将要执行指令的偏移量(offset ),这个偏移量
是相对于目前正在运行的代码段寄存器CS而言的。偏移量加上当前代码段的基地址,就
形成了下一条指令的地址。EIP中的低16位可以分开来进行访问,给它起名叫指令指针IP
寄存器,用于16位寻址。


2.1.4 调试寄存器和测试寄存器

2.1.5 系统地址寄存器,4个

2.1.5.1 全局描述符表寄存器GDTR,是48位寄存器,用来保存全局描述符表(GDT)的32位基地址和16为GDT的界限。

2.1.5.2 中断描述符表寄存器IDTR(Interrupt Descriptor Table Register),是48位寄存器,用来保存中断描述符表(IDT)的32位基地址和16为IDT的界限。

2.1.5.3 局部描述符表寄存器LDTR(Global Descriptor Table Register ),是16位寄存器,保存局部描述符表LDT段的选择符(不是基址?因为基址存放在GDT中的描述符中)。

2.1.5.4 任务状态寄存器TR(Task State Register)是16位寄存器,用于保存任务状态段
TSS段的16位选择符(不是基址?)。

2.2 内存寻址

2.2.1 MMU

2.2.1.1 ,MMU是一种硬件电路,它包含两个部件,一个是分段部件,一个

2.2.1.2 是分页部件,在此,我们把它们分别叫做分段机制和分页机制,以利于从逻辑的角度来

2.2.1.3 理解硬件的实现机制。分段机制把一个逻辑地址转换为线性地址;接着,分页机制把一个

2.2.1.4 线性地址转换为物理地址。

2.2.2 地址

2.2.2.1 当使用IA32时,我们必须区分以下三种不同的地址:
逻辑地址:
机器语言指令仍用这种地址指定一个操作数的地址或一条指令的地址。这种寻址方式
在Intel的分段结构中表现得尤为具体,它使得MS-DOS或Windows程序员把程序分为
若干段。每个逻辑地址都由一个段和偏移量组成。
线性地址:
线性地址是一个32位的无符号整数,可以表达高达232(4GB)的地址。通常用16进制
表示线性地址,其取值范围为0x00000000~0xffffffff。
物理地址:
也就是内存单元的实际地址,用于芯片级内存单元寻址。物理地址也由32位无符号整
数表示。

2.3 分段机制

2.3.1 段选择符

2.3.1.1 存放于段寄存器中:CS,DS等

2.3.2 段描述符

2.3.2.1 存放于描述符表中(全局、局部、中断等)

2.3.2.1.1 全局描述符表(GDT)

全局描述符表GDT(Global Descriptor Table),除了任务门,中断门和陷阱门描述
符外,包含着系统中所有任务都共用的那些段的描述符。它的第一个8字节位置没有使用。


2.3.2.1.2 中断描述符表IDT

包含256个门描述符。IDT中只能
包含任务门、中断门和陷阱门描述符,虽然IDT表最长也可以为64K字节,但只能存取2K字
节以内的描述符,即256个描述符,这个数字是为了和8086保持兼容。


2.3.2.1.3 局部描述符表(LDT)

局部描述符表LDT(local Descriptor Table),包含了与一个给定任务有关的描述符,
每个任务各自有一个的LDT。有了LDT,就可以使给定任务的代码、数据与别的任务相隔离。
每一个任务的局部描述符表LDT本身也用一个描述符来表示,称为LDT描述符,它包
含了有关局部描述符表的信息,被放在全局描述符表GDT中。


2.3.3 Linux中的段机制

2.3.3.1 从2.2版开始,Linux让所有的进程(或叫任务)都使用相同的逻辑地址空间,因此
就没有必要使用局部描述符表LDT。但内核中也用到LDT,那只是在VM86模式中运行
Wine,因为就是说在Linux上模拟运行Winodws软件或DOS软件的程序时才使用。

2.3.3.2 所有段基址为0

,Linux的设计人员干脆让段的基地址为0,而段的界限为
4GB,这时任意给出一个偏移量,则等式为“0+偏移量=线性地址”,也就是说“偏移量
=线性地址”。另外由于段机制规定“偏移量 < 4GB”,所以偏移量的范围为0H~
FFFFFFFFH,这恰好是线性地址空间范围,也就是说虚拟地址直接映射到了线性地址,
我们以后所提到的虚拟地址和线性地址指的也就是同一地址。看来,Linux在没有回避段
机制的情况下巧妙地把段机制给绕过去了。


2.3.3.3 Linux必须创建4个段描述符——特权级0的代码段和数据段,特权级3的代码段和数据段。

由于IA32段机制还规定,必须为代码段和数据段创建不同的段,所以Linux必
须为代码段和数据段分别创建一个基地址为0,段界限为4GB的段描述符。不仅如此,由于
Linux内核运行在特权级0,而用户程序运行在特权级别3,根据IA32的段保护机制规定,
特权级3的程序是无法访问特权级为0的段的,所以Linux必须为内核和用户程序分别创建
其代码段和数据段。这就意味着Linux必须创建4个段描述符——特权级0的代码段和数据
段,特权级3的代码段和数据段。
Linux在启动的过程中设置了段寄存器的值和全局描述符表GDT的内容,段的定义在
include/asm-i386/segment.h中:
#define __KERNEL_CS 0x10 /*内核代码段,index=2,TI=0,RPL=0*/
#define __KERNEL_DS 0x18 /*内核数据段, index=3,TI=0,RPL=0*/
#define __USER_CS 0x23 /*用户代码段, index=4,TI=0,RPL=3*/
#define __USER_DS 0x2B /*用户数据段, index=5,TI=0,RPL=3*/


2.3.3.3.1 · 段的基地址全部为0x00000000

2.3.3.3.2 · 段的上限全部为0xffff

2.3.3.3.3 · 段的粒度G为1,即段长单位为4KB

2.3.3.3.4 · 段的D位为1,即对这四个段的访问都为32位指令

2.3.3.3.5 · 段的P位为1,即四个段都在内存。

2.3.3.4 TSS任务状态段,Linux中每个CPU一个

按Intel的规定,每个进程有一个任务状态段(TSS)和局部描述符表LDT,但Linux
也没有完全遵循Intel的设计思路。如前所述,Linux的进程没有使用LDT,而对TSS的使用
也非常有限,每个CPU仅使用一个TSS。


2.4 分页机制

2.4.1 分页机制由CR0中的PG位启用

2.4.2 CR3存放页目录表的地址

2.4.3 理解:针对进程,每个进程有独立的地址空间,每个进程有独立的分页机制、页目录、页表?

2.4.4 为了保持可移植性,Linux采用三级分页模式而不是两级(对于IA32忽略页中间目录),
这是因为许多处理器(如康柏的Alpha,Sun的UltraSPARC,Intel的Itanium)都采用64位结构
的处理器,在这种情况下,两级分页就不适合了,必须采用三级分页。

2.4.5 分页机制是硬件对分页的支持,这是虚拟内存管理的硬件基础。

2.4.6 每当调度程序选择一个进程运行时,内核就要为即将运行的进程设置好控制寄存器CR3,
而MMU的硬件总是从CR3中取得指向当前页目录的指针。

2.5 Linux汇编

2.5.1 使用的是AT&T语法,而非Intel语法,因为源于Unix

2.5.2 GNU汇编程序GAS使用AT&T语法

2.6 实模式和保护模式

2.6.1 实模式:8086开始,支持段式管理,20位地址总线,ALU(算术逻辑单元)还是16位

2.6.2 保护模式。这种模式下内存段的访问受到了限制。访问内存时不能直接从段寄存器中获得段的
起始地址了,而需要经过额外转换和检查(从此你不能再随意存取数据段)

2.6.3 为了和过去兼容,80286内存寻址可以有两种方式,一种是先进的保护模式,另一
种是老式的8086方式,被成为实模式。系统启动时处理器处于实模式,只能访问1M空间,
经过处理可进入保护模式


-------------------------------------------------------------
3 80386的中断和异常
-------------------------------------------------------------


3.1 8086/8088把中断分为内部中断和外部中断两大类。为了支持多任务和虚拟存储器等功能,
80386把外部中断称为“中断”,把内部中断称为“异常”。与8086/8088一样,80386通常
|在两条指令之间响应中断或异常。80386最多处理256种中断或异常。

3.2 中断:对80386而言,中断是由异步的外部事件引起的。外部事件及中断响应与正执行的指令
没有关系。通常,中断用于指示I/O设备的一次操作已完成。

3.3 异常:异常是80386在执行指令期间检测到不正常的或非法的条件所引起的。异常与正执行的
指令有直接的联系。例如,执行除法指令时,除数等于0。再如,执行指令时发现特权级不正确。

3.4 中断是否可以嵌套???--- 硬件上支持,但Linux默认是关闭嵌套的。

3.5 中断或内核态执行路径是否可以被抢占?-- 取决于是否关中断和配置内核抢占

 

阅读(1932) | 评论(0) | 转发(0) |
0

上一篇:TCP收包流程

下一篇:bounce buffer概念

给主人留下些什么吧!~~