32 块大小_IA-32系统总体架构

在看文章前可以先看下这个,

吴海波:专栏的序。

先有个大概的认识会对阅读有所帮助。

在正式的介绍硬件提供的分段,分页,任务管理,中断异常处理,高速缓存控制这些内容之前,我们先对IA-32的整体框架梳理下。看不懂也没有关系,后面每篇文章都会对其中的一部分进行较为细致的分析。

整体来说IA-32架构的可以提供如下几块功能:

1.内存管理;

2.软件模块的保护;

3.多任务处理;

4.异常和中断处理;

5.多核;

6.缓存管理;

7.硬件资源和电源管理;

8.调试和性能监视。

我们这里主要关注前面6块的内容。因为我们的关注点在于面向cpu的编程,那么首先就需要知道IA-32架构的cpu提供给我们什么样的编程环境,换句话说,我们能够操作什么硬件单元来完成我们想要完成的操作?(比如算数和逻辑运算,接受外部输入产生输出,管理外部的硬件等等)。

一:对系统架构的概述

下面的图2-1描述了IA-32提供给我们的一个基本执行环境中包含的硬件单元。

bac4103b546c7dc8e4705c1c97143fea.png

文档中将这些寄存器进行了简单的介绍。名词翻译为中文会有些怪,最好能记住英文名称和简写。

在前面os章节中我们说过几个地址的概念,再重新提下。首先就是逻辑地址(logical address),逻辑地址就是段基址加上段内偏移,将逻辑地址合成以后的地址称为线性地址(linear address)。如果没有分页,线性地址就是最终的物理地址,而如果有分页的存在,则还需要经过分页机制的转换才能得到最终的物理地址。

1.全局和局部描述符表(Global and local Descriptor tables)

如果你想访问内存,那么你肯定要通过全局描述符表(global descriptor table,GDT)或者局部描述符表(local descriptor table , LDT)中的一个来获取内存的信息。GDT和LDT都是简单的数组类型的数据结构,这2个表中的信息称为段描述符(segment descriptor)。段描述符中提供段的基地址,段的大小,访问控制,类型等等信息,通过这些你就可以定位到具体的内存区域了。

每个段描述符都可以通过段选择子(segment selector)来访问。你可以将段选择子当作段描述符的名字,其中包括该段描述符的类型(全局还是局部),权限,对应的GDT或者LDT表中的索引(有了这个索引就可以定位到具体的段描述符了)。

若要访问段中的字节,必须提供段选择子和偏移量。通过段选择子确定了段描述符后,从段描述符中,处理器获得段的线性地址空间的基地址。然后,偏移量提供相对于基地址的偏移位置。这个机制可用于访问任何有效的代码、数据或堆栈段,条件是该段可从处理器的当前权限级别(CPL)访问。CPL就是当前正在执行的代码段的权限级别(总共有4个权限级别,分别为0,1,2,3,数字越大权限越小)。

GDT,LDT这2个数组结构的数据都放在内存的某个地方,至于是哪里你可以自己来定。intel提供了2个寄存器来存储对应的线性基地址,分别为GDTR,LDTR。最后那个R就是寄存器register的缩写。

2.系统段,段描述符,门(System Segments, Segment Descriptors, and Gates )

除了构成程序或过程执行环境的代码、数据和堆栈段之外,处理器的体系结构还定义了两个类型的系统段:任务状态段(task-state segment,TSS)和LDT。GDT不被认为是段,因为它不是通过段选择子和段描述符访问的(从上面你可以知道,访问GDT是通过GDTR中的GDT基地址进行访问的)。而TSS和LDT有为它们定义的段描述符,可以通过段选择子找到段描述符来访问。

另外,处理器架构还定义了一种特别类型的描述符叫做门(gate)。gate提供了一种机制,就是可以跨权限级别的访问。比如一个call命令,如果当前的权限是3(cpu的等级分为4个,分别是0,1,2,3,其中数字越大,权限越小),要想访问权限定义为0的代码,那么就可以通过call命令加上对应的门描述符来完成。关于gate的信息,后面会详细展开来说。这块的内容还是很多的。

3.任务状态段和任务门(Task-State Segments and Task Gates)

TSS中会定义一个任务的执行环境的信息。具体来说包括如下部分:通用寄存器,段寄存器,EFLAGS寄存器,EIP寄存器,栈段对应的段选择子(一个cpu的权限必须对应一个不同的段,也就是说你如果是一个权限等级为3的程序,你会有4个栈,分别对应0,1,2,3这几个权限等级)。TSS还会包括该任务的LDT的段选择子和分页数据结构的信息。

TSS作为一个系统段(如第二点所说),访问它就需要段选择子,这个段选择子保存在任务寄存器TS(task regeiter)中。一个简单的执行任务切换的方式就是通过CALL或者JMP命令加上一个TSS的段选择子来完成。下面是切换任务的时候,处理器完成的几个步骤:

1.将当前任务的状态存储在对应的TSS中。

2.将新任务的段选择子加载到TR中。

3.通过GDT中的段描述符访问新的TSS。

4.将新任务的状态从新的TSS加载到通用寄存器、段寄存器、LDTR、控制寄存器CR3(分页层次结构的基地址)、EFLAGS寄存器和EIP寄存器中。

5.开始执行新任务。

4.中断和异常处理

外部中断、软件中断和异常通过中断描述符表(IDT)处理(这也是一个数组的结构,类似GDT和LDT)。IDT存储一组门描述符,提供对中断和异常处理程序的访问。和GDT一样,IDT也不是一个段。IDT线性基地址存储在IDT寄存器(IDTR)中。IDT中的门描述符类型可以是中断(interrupt)、陷阱(trap)或任务门描述符(TSS)。处理器可以从内部硬件、外部中断控制器或通过int、INT 3或bound等指令接收中断向量。中断向量就是一个索引,根据这个索引就可以对IDT这个数组类型的数据结构进行访问了。如果所选的门描述符是中断门或陷阱门,对应处理程序的访问类似于通过一个调用门(call gate)来访问一个过程。如果描述符是任务门,则通过任务的上下文切换来访问(就像上面第三点的那五个步骤所示)。

5.内存管理

内存管理就2种情况,要不分段,要不分段+分页。也就是说分段是关闭不掉的功能,分页是程序,也就是os来指定是否需要开启的。

6.系统寄存器(System Registers)

剩下的寄存器后面再来说。

二:处理器支持的运行模式

我们先来看下IA-32支持哪几种运行的模式:

1.保护模式(Protected mode)。这个是处理器原生支持的模式,在这种模式下工作,将能够运用处理器提供的非常丰富并且高性能的特性,以及对以前处理器的兼容性。你用电脑的99.99%情况下处理器都是工作在这种模式下的。

2.系统管理模式(System management mode (SMM))。主要供os进行电源管理和OEM差异功能的实现。

3.实模式(Real-address mode)。这个是开机或者重启机器一开始的时候处理器的模式,这种模式只能跑intel8086处理器对应的程序,我们要说的现代操作系统需要的功能大部分都是没有的。

4.虚拟8086模式(Virtual-8086 mode)。就是能在保护模式下跑8086的程序。

Intel64架构支持IA-32的所有模式和IA-32e模式,IA-32e简单来说就是64位对32位的兼容模式。

三:EFLAGS 寄存器

EFLAGS寄存器如下所示,这个寄存器里面有很多的控制位,根据这些控制位会有很多不同的系统工作方式,我们在后面使用到其中内容的时候再介绍。

6bb88fd7b532ea556a0421e53303afbc.png

四:内存管理寄存器

处理器提供了四个内存管理的寄存器(GDTR, LDTR, IDTR, and TR)来指定内存段的地址信息。

e1cee721484fbfba93c351d7a48fc08e.png

五:控制寄存器(contral registers)

控制寄存器有5个,CRO,CR1,CR2,CR3,CR4.下面的图2.7详细的展示了各个控制寄存器的内容。这些寄存器包含的含义我们后面用到的时候再介绍,主要先有个印象,控制寄存器嘛,肯定是控制什么东西的。

699bbdbd6d241c8360c3e0674acfa76d.png

六:Protection Key Right Register(PKRU)(我就不翻译这个名字了。。。)

如果CPUID.(EAX=07H,ECX=0H):ECX.PKU [bit 3] = 1,这句的意思是执行CPUID指令,输入是这个(EAX=07H,ECX=0H),输出是ECX,在ECX的第三个bit位,如果是1,表示处理器支持4级页表下的protection-key特性。这个特性简单的来说就是对页表可以支持更为细致的权限保护。PKRU如下面的图2-9展示的这样。

a9bcef01d86a6f3b6775a3fc440a01ef.png

PKRU包括16个控制对,每个对i都包含2个bit位:

Bit 2i:在图中标记为AD的:如果设置了该位,处理器就会禁止普通用户模式下对该线性地址的访问。

Bit 2i+1:图中标记为WD,如果设置,就是禁止普通用户模式对该线性地址的写操作。

七:系统指令概要(System instruction)

系统指令是用来实现系统层面功能的,比如加载系统寄存器,管理缓存,管理中断,或者设置debug寄存器。这种类型的指令很多都只有在权限为0的情况下才能执行,也有一些是可以在任意的权限级别上执行。下面的表2-3给出了系统指令的执行权限的情况:

c51b8a6d297572d59ad5b8c6cfbf1703.png

6e877122ecefaa3a2097124ae566859a.png

对于前面提到的GDTR,LDTR,IDTR,TR这些寄存器,可以使用下面的指令来加载和修改:

• LGDT (Load GDTR Register) —从内存中加载GDT的基地址和大小到GDTR中

• SGDT (Store GDTR Register) —把GDTR中的基地址和大小保存保存到内存中

• LIDT (Load IDTR Register) —从内存中加载IDT的基地址和大小到IDTR中。

• SIDT (Store IDTR Register)—把IDTR中的基地址和大小保存保存到内存中。

• LLDT (Load LDTR Register) —加载LDT的段选择子和段描述符到LDTR中,段选择子和段描述符的数据是事先保存在内存中的(也可以从通用寄存器加载)。

• SLDT (Store LDTR Register) —保存LDT的段选择子到一个通用寄存器中。

• LTR (Load Task Register) —加载TSS的段选择子和段描述符,段选择子和段描述符的数据是事先保存在内存中的(也可以从通用寄存器加载)。

STR (Store Task Register) —保存TR寄存器中的当前TSS选择子到内存中或者通用寄存器中

LMSW(load machine status word)SMSW(store machine status word)可以操作CRO寄存器的0到15位,这是为了保持和Intel286保持兼容而设置的。对于IA-32的处理器不一样再使用这个指令,相应的应该使用MOV CR指令。

对于控制寄存器,应该使用MOV指令进行操作。通过MOV指令可以加载或者保存控制寄存器,相应的目的操作数是通用寄存器。

对于Debug的支持提供了8个debug 寄存器(DR0-DR7)。MOV指令可以设置和保存这些存储器的值。

存储器提供了一些指令用来显示的将缓存或者TLB置失效。INVD(invalidate cache with no writeback)指令会将内部缓存的所有数据和指令都置为时效,然后给外部缓存发送信息,让它们同样将缓存置为失效。

WBINVD(invalidate cache with writeback)指令的功能和INVD一样,除了会在置失效之前会将已经被修改过的内部缓存的数据写会到主存中。本地内存置为失效后,WBINVD会发送信号,来将在指令执行的过程中被修改的数据写会和置为失效。

需要注意的是,非共享的缓存不会写会也不会置为失效。下面的图2-10中,如果运行WBINVD指令是在LP0或者LP1,那么LPO/LP1的L1和L2缓存会写回并且置为失效,L3也会如此。但是其他的logic processor的L1和L2缓存并不会写会或者置为失效。

3f3d967fd7f0f37b6751a1c5e83e46e9.png

INVLPG(invalidate TLB entry)指令会将TLB中的指定页缓存置为失效。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值