实验指南标准服务器技术是实现网络功能虚拟化(NFV)的关键因素。了解x86架构的一些基础知识,有助于理解电信云的关键技术,尤其是掌握虚拟化技术原理和关键优化方案很有必要。本文主要阐述了x86架构的CPU指令集增强、内存管理、中断与异常、IO架构等,以及一些基本IT概念的讲解。1、增强型x86-64指令集Intel的x86架构是世界上最流行的处理器架构,从1978年8086/8088处理器问世到现在的Corei7和Corei9,以及至强系列处理器,Intelx86架构都有在CPU领域工作了40多年。x86-64是x86架构的扩展产物,是一种64位的微处理器架构及其对应的指令集。在x86-64出现之前,英特尔和惠普联合推出了IA-64架构,不兼容x86,市场反响冷淡。因此,兼容x86的x86-64架构应运而生。1999年,AMD首先发布了64位指令集,为IA-32提供扩展,称为x86-64(后更名为AMD64)。这种架构后来被Intel采用,就是现在的Intel64。x86-64可以有效地将x86架构移植到64位环境中,并且兼容原有的x86应用程序,因此市场前景广阔。外界使用x84-??64或x64来称呼这种64位架构是为了保持中立,不偏袒任何厂商。AMD64指令集的主要特点是:支持64位通用寄存器、64位整数和逻辑运算、64位虚拟地址。英特尔64位架构增加了额外的寄存器和其他改进的指令集,允许处理器直接访问超过4GB的内存,从而允许运行更大的应用程序。通过64位内存地址上限,其理论内存容量上限达到16EB。目前大多数操作系统和应用程序基本都支持完整的64位地址。2.x86内存架构硬件架构中最复杂最核心的部分就是它的内存架构。由于篇幅所限,这部分的细节无法详细展开。人员主要包括CPU架构设计、操作系统开发、内核优化等。参考《手把手教你设计CPU-RISC-V处理器》、《嵌入式操作系统原理》、?等书籍。2.1地址空间地址空间是所有可用资源的集合,我们把它看成一个大数组,那么地址就是这个数组的索引。地址空间可以分为物理地址空间和线性地址空间。2.1.1物理地址空间硬件平台通常分为三部分:CPU、内存和其他硬件设备。其中CPU是整个硬件平台的龙头,内存等硬件设备是CPU可以使用的资源。这些资源组合分布在CPU的物理地址空间中,CPU用物理地址对这些资源进行索引。物理地址空间的大小由CPU实现的物理地址位数决定,物理地址位数由CPU通过MMU(MemoryManagement)转换的外部地址总线的位数决定单元,内存管理单元)。外部地址总线的位数与CPU处理数据的能力(即CPU的位数)没有必然联系。例如,16位的8086CPU有20位的地址空间。一个硬件平台只有一个物理地址空间,但每个程序都认为自己独享整个平台的硬件资源。为了让多个程序能够有效地相互隔离,有效地利用物理地址空间的资源,引入了线性地址空间的概念。2.1.2线性地址空间线性地址空间的大小由CPU实现的线性地址位数决定,线性地址位数由CPU内部地址总线的位数决定。由于CPU的内部地址总线直接与CPU的执行单元相连,因此内部地址总线的位数往往与CPU的位数一致。如果是32位处理器,那么它实现的是32位线性地址,它的线性地址空间是4GB,如果是64位处理器,那么它的线性地址空间是2的64次方,这是16384GB。需要注意的是,线性地址空间的大小与物理地址空间的大小没有必然联系。Intel的PAE平台线性地址空间为4GB,而其物理地址空间为64GB。然而,线性地址空间映射到物理地址空间的一部分或整个物理地址空间。即线性地址空间小于等于物理地址空间。CPU负责将线性地址空间转换为物理地址空间,以保证程序能够正确访问线性地址空间所映射到的物理地址空间。在现代操作系统中,每个进程通常都有自己私有的线性地址空间。典型的线性地址空间结构如下图所示。线性地址空间2.2地址地址是访问地址空间的索引。根据访问地址空间的不同,索引可以分为物理地址和线性地址。但是由于x86特殊的段机制,多了一个地址——逻辑地址。2.2.1逻辑地址逻辑地址是程序直接使用的地址(x86不能关闭段机制,逻辑地址一直存在)。逻辑地址由一个16位段选择符和一个32位偏移量(32位平台)组成。下面以具体过程为例进行说明。例如:我们编写如下c语言代码:inta=100;#定义一个整型变量aint*p=&a;#定义一个整型指针p,指向变量a在内存中的地址上面语句中的指针变量p存放的是变量a的逻辑地址。实际上,p中存放的只是逻辑地址的偏移量部分,偏移量对应的段选择符位于段寄存器中,并不会在程序中显示出来。2.2.2线性地址线性地址也称为虚拟地址。线性地址是逻辑地址转换的结果,用于索引线性地址空间。CPU在使用分页机制时,还需要将线性地址转换成物理地址,才能访问物理平台内存或其他硬件设备;当不启用分页机制时,线性地址与物理地址相同。2.2.3物理地址物理地址是物理地址空间的索引。它是CPU提交给总线以访问物理平台内存或其他硬件设备的最终地址。在x86下,物理地址有时被称为总线地址。根据上面的描述,我们可以总结如下:启用分段机制,不启用分页机制:逻辑地址--->线性地址=物理地址分段机制,同时启用分页机制:逻辑地址-->->线性地址-->物理地址3、x86内存管理机制x86架构的内存管理机制分为两部分:分段机制和分页机制。分段机制为程序提供了隔离的代码区、数据区和堆栈区,从而防止在同一处理器上运行的多个程序相互干扰。分页机制实现了传统的按需分页和虚拟内存机制,可以将程序的执行环境按需映射到物理内存上。另外,分页机制也可以用来提供多个任务的隔离。分段机制和分页机制都可以配置为支持简单的单任务系统、多任务系统或具有共享内存的多处理器系统。需要强调的是,不管处理器的工作模式如何,都不能禁用分段机制,但是分页机制是可选的。3.1分段机制分段机制是x86架构下一种简单的内存管理机制,不能禁用。了解分段机制,有利于深入理解后续的内存虚拟化原理和优化方案。分段机制将内存分成由基地址(Base)和长度(Limit)描述的块。段可以与程序的最基本元素相关联。程序可以简单的分为代码、数据、栈。段机制有相应的代码段、数据段和堆栈段。根据分段机制,一个程序在内存中由四个基本部分组成:逻辑地址、段选择符、段描述符和段描述符表。当程序使用逻辑地址访问内存的某一部分时,CPU通过逻辑地址中的段选择符索引段描述符表,然后获取该内存对应的段描述符(段描述符描述基地址,长度,段的读值)/write,访问权限等属性信息)根据段描述符中的段属性信息检查程序的访问是否合法,合法则转换逻辑地址根据段描述符中的基地址转换成线性地址。这个过程可以用下图来概括:内存分段机制段选择器是逻辑地址的组成部分,用来索引段描述符表,得到段对应的段描述符。段选择器作为逻辑地址的一部分对应用程序可见。但是,如上逻辑地址中所述,在应用程序中只存储和使用了逻辑地址的偏移部分,段选择符的修改和分配是由链接器和加载器完成的。为了使CPU能够快速获取段选择符,x86架构提供了6个段寄存器来存放当前程序中每个段的段选择符。六个段寄存器如下:CS(Code-Segment,代码段):存放代码段的段选择符。DS(Data-Segment,数据段):存储数据段的段选择符。SS(Stack-Segment,栈段):存放栈的段选择符。ES、FS、GS:段选择器,可以存放三个额外的数据段,供程序自由使用。由于段选择符的存在最终是为了在段描述符表中对段描述符进行索引,所以为了加快段描述符的访问速度,x86架构在不同的段寄存器之后增加了一个程序不可见的段描述符寄存器。当一个新的段选择符被添加到相应的段寄存器中时,CPU自动将段选择符索引的段描述符加载到这个不可见的段描述符寄存器中。每个段寄存器的结构如下:段寄存器段描述符描述了某个段的基地址、长度和各种属性(例如读/写属性、访问权限等)。这就是切分机制的核心思想。当CPU通过一个逻辑地址段选择器获得段对应的段描述符后,会使用段描述符中的各种属性域来检查访问。一旦确认访问合法,CPU就会将段描述符中的基地址和程序中逻辑地址的偏移量相加,得到程序的线性地址。前面提到过,x86架构在每个段寄存器之后都增加了一个程序不可见的段描述符寄存器。每当一个新的段选择器被添加到段寄存器时,CPU自动索引段选择器的段描述。描述符被加载到这个段描述符寄存器中。只要没有段寄存器的更新操作,CPU就不再查询段描述符表而是直接使用段描述符寄存器中的值,从而加快CPU的执行效率。x86架构提供了两种段描述符表:GDT(GlobalDescriptorTable)和LDT(LocalDescriptorTable)。具体选择哪个段描述符表是由段选择符中的TI域决定的。当TI=0时,索引为GDT,当TI=1时,索引为LDT。系统中至少有一个GDT可以被所有进程访问。同时,系统中可以有一个或多个LDT,可以为某个进程私有,也可以为多个进程共享。GDT是内存中的数据结构。简单的说,GDT可以看成一个数组,用基址(Base)和长度(Limit)来描述。LDT是一个段,需要用段描述符来描述。LDT的段描述符存放在GDT中。当系统中有多个LDT时,GDT中必须有相应数量的段描述符。x86架构为了加快GDT和LDT的访问速度,提供了GDTR寄存器和LDTR寄存器。这两个寄存器的具体描述如下:GDTR:包括一个32位的基地址(Base)和一个16位的长度(Limit)。LDTR:结构与段寄存器相同(也包含程序不可见的段描述符寄存器)。通过段选择器索引GDT/LDT的过程如下图所示:LDT段描述符并将其加载到LDTR寄存器中。另外,在进程的CS、DS、SS中加入对应的段选择符,CPU根据段选择符的TI字段索引对应的段描述符表,得到对应的段描述符,加载到CS、DS、SS对应程序不可见的段描述符寄存器。2)当程序执行读写内存中的数据时,将程序中对应变量的逻辑地址转换为线性地址:检查必要的属性和访问权限;从DS对应的段描述符寄存器中获取段的基地址;将变量的32位偏移量与段描述符中的基地址相加,得到变量的线性地址。3.2分页机制分段机制的目的是将内存中的线性地址空间划分为多个以基地址和长度描述的段进行管理。程序对应的逻辑地址由基地址和线性地址空间的映射来描述。分页机制以“页”为单位来管理线性地址空间与物理地址空间的映射关系。同时,分页机制可以让一个页面存放在物理内存或者磁盘的交换区(比如Linux下的Swap分区,Windows下的虚拟内存文件),程序可以使用比机器物理内存更大的内存区域,从而实现了现代操作系统中的虚拟内存机制。(注:操作系统的虚拟内存原理和映射关系与后面要讲的计算虚拟化技术中的内存虚拟化技术基本相同,只是VMM实现时多了一层嵌套)。在x86架构下,一个页面的典型大小为4KB,所以一个4GB的线性地址空间被划分为1024×1024个页面,见本文线性地址空间示意图。物理地址空间的划分与此类似。x86架构允许页面大小大于4KB(如2MB、4MB、1GB)等。分页机制的核心思想是通过页表将线性地址转换为物理地址,并配合翻译后备缓冲器(TranslationLookasideBuffer,以下简称TLB)加速地址转换过程。分页机制主要由三部分组成:页表、CR3寄存器和TLB,如下图所示。内存分页机制页表是用于将线性地址转换为物理地址的主要数据结构。一个地址与页边界对齐后的值称为页框号(或pageframe),实际上就是该地址所在页的基地址。例如:一个页面大小为4kB,那么第一个页框号为0,第二个页框号为4097,以此类推。线性地址对应的页框号称为虚拟页框号(VirtualFrameNumber,以下简称VFN),物理地址对应的页框号称为物理页框号(PhysicalFrameNumber,以下简称PFN)或机器页框号。页表实际上是一个存储VFN到PFN映射的数据结构。在传统的32位保护模式下(不启用物理地址扩展PAE功能),x86处理器采用二级转换方案。在这个方案中,CR3寄存器指向一个4KB的页目录表,页目录中有1024页。每条记录的大小为4B,每一项指向一个4KB的页表。页表中也有1024项,每项大小为4B。因此,整个线性地址空间的最终大小为1024页,长度为4KB。即总共有4GB的空间。下图显示了未启用PAE的4KB页面。页表结构一个页目录项(PageDirectoryEntry,以下简称PDE)包括页表??的物理地址,PDE存放在页目录表中。PageTableEntry(以下简称PTE):包含线性地址对应的物理页框号PFN。PTE存储在页表中。加上位移就可以确定线性地址对应的物理地址。虚拟内存实现的关键是PDE和PTE都包含一个P(Present)域:当P=1时,物理页存在于物理内存中,CPU完成地址转换后可以直接访问该页。当P=0时,物理页不在物理内存中(在硬盘的交换分区中),当CPU访问该页时,会产生缺页中断,操作系统的缺页处理机制将存储在硬盘上的页面分页到物理内存中,这样访问才能继续进行。同时,由于程序的局部性,操作系统会将离页较近的页一起调入物理内存,以方便CPU访问。因此,为了减少内存占用,要求程序开发人员尽可能少地使用全局索引或递归调用等机制。当P=0时,PDE和PTE的第1~31位会向操作系统提供硬盘上物理页的信息,这些位存储物理页在硬盘上的位置。启用PhysicalAddressExtension(以下简称PAE)后,页表结构会发生相应变化。页表和页目录的总大小仍然是4KB,但是页表和页目录中的条目从32位扩展到64位以使用额外的地址位。这样,页表和页目录都只有512个表项,是原解的一半,所以又增加了一层:CR3指向页目录指针表,即包含4个页目录指针的表.启用PAE的4KB页使用的三级页表如下图所示:三级页表结构CR3寄存器也称为页目录基地址寄存器(Page-DirectoryBaseRegister,PDBR),它存放页目录的物理地址。一个进程在运行之前,其页目录的基地址必须存放在CR3中,并且页目录的基地址必须对齐到一个4KB的页边界。当启用PAE时,CR3指向页目录指针表,每一项指向一个页目录表,一共有4张页目录表。为了提高地址转换的效率,x86架构使用了TLB来缓存最近使用过的页面映射。从VFN到PFN的转换记录存储在TLB中。当CPU访问某个线性地址时,如果TLB中存在其所在页的映射,则无需查找页表即可得到该线性地址对应的PFN,然后CPU将其转移到Addingto线性地址的偏移量,就可以得到最终的物理地址。x86架构内存管理中心的分页机制总结:1)CPU访问一个线性地址,在TLB中进行匹配。如果地址转换在TLB中,则跳到第6步。否则发生TLBMiss(TLB缺失),继续第2步。2)查找页表,如果该页在物理内存中,则跳到第2步4.3)如果页面不在物理内存中,则发生页面错误,下面的处理由操作系统的页面错误处理程序执行。将页面从磁盘复制到物理内存中。更改对应的PTE,将P位设置为1,其他字段也相应设置。刷新TLB中对应的PTE。从页面错误处理程序返回。4)此时,该页已经存在于物理内存中,页表中已经包含了这个映射。在TLB中重新匹配。如果地址转换在TLB中,则跳到第6步。否则发生TLBMiss(TLB缺失),继续第5步。5)CPU再次检查页表,将相应的映射插入到TLB中。6)此时TLB中已经包含了线性地址对应的PFN。将PFN和线性地址中的偏移量相加,得到对应的物理地址。NFV关键技术:x86架构基础(下)【本文为专栏作者《移动实验室》原创稿件,转载请联系原作者】点此阅读更多本作者好文
