Chinaunix首页 | 论坛 | 博客
  • 博客访问: 996184
  • 博文数量: 186
  • 博客积分: 10020
  • 博客等级: 上将
  • 技术积分: 1676
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-14 17:08
文章存档

2011年(5)

2009年(11)

2008年(2)

2007年(111)

2006年(57)

我的朋友

分类: LINUX

2006-11-26 18:04:39

采用显式并行指令计算(EPIC)结构的安腾处理器是Intel公司新一代64位处理器,HP、SGI、Intel等大公司都纷纷推出了高性能的安腾服务器系统。Linux是目前支持IA-64服务器平台的主流操作系统之一。本文重点描述了IA-64 Linux存储管理,包括IA-64 Linux灵活的地址空间划分、页表、TLB等机制。

Intel公司的IA-64架构是一种经济高效、伸缩自如、性能卓越的64位计算平台。从技术角度看,与一般处理器采用的超标量技术不同,IA-64架构的主要特色是采用EPIC结构。EPIC结构利用编译器挖掘应用程序的指令级并行性,并通过生成的机器语言以显式方式指导硬件执行程序,降低处理器硬件的复杂度,并通过编译软件挖掘出更多、更大范围内的指令级并行,EPIC架构代表了当前处理器设计的新思想。

Intel公司已成功推出安腾和安腾2处理器,安腾2处理器在SPECfp2000测试中的性能表现非常突出,仅在SPECfp2000 Peak测试中略微落后于Alpha21364,在SPECfp2000 Base的测试中则名列榜首。与此同时Intel公司非常注重IA-64架构操作系统的开发,早在1999年,Intel公司就联合HP、SGI、RedHat、VA Linux和IBM启动了Intel IA-64的Trillian项目,该项目旨在完成Linux在IA-64平台的移植和优化,许多成员为该项目做出了贡献,如HP完成内核,IBM完成性能分析工具和评测,Intel完成内核和EFI(Extensible Firmware Interface),RedHat完成GNUPRO开发工具,SGI完成编译器和kdb等。目前,Red Hat、TurboLinux、Caldera和SuSe都已发布了支持IA-64架构的Linux版本,Linux已成为支持IA-64架构的重要操作系统,HP公司的David Mosberger维护和管理IA-64 Linux项目,并已融入到Linux内核版本中。





回页首


从用户角度看,Linux进程的虚地址是线性的,它分为两部分:内核空间和用户空间。用户空间占据地址的低部分,从0到TASK_SIZE(TASK_SIZE的值是与具体的硬件平台相关的,在include/asm/processor.h中定义),剩余部分为内核空间。用户空间对进程是私有的,该地址由进程的页表维护管理,内核空间是所有进程共享的。在用户态下运行时,只可以访问用户空间,对内核空间的读/写/执行都将导致保护冲突故障,这可以防止出错或恶意的用户代码破坏内核;在内核态运行,则可以访问用户和内核空间。

IA-64架构支持64位虚地址空间,它将64位虚地址空间分成8个相等的区,每个区2048P字节大小,用虚地址的高3位(61-63位)表示区号。如图1所示




目前应用对虚地址的需求还没有达到全64位,因此实现时并不需要支持全64位虚地址,IMPL_VA_MSB常量用于决定未实现的虚地址空间范围,它的值可以在50-60,IMPL_VA_MSB+1至60是未实现的虚地址位,未实现的地址位通过虚地址的低地址位符合扩展而成,如果IMPL_VA_MSB值小于60,则符合扩展将某个区的虚地址空间分成两部分,未实现部分在中间,如图2所示(IMPL_VA_MSB=50)。对未实现部分的访问是不允许的,如果是用户态的访问,则产生非法指令错;如果是核心态的访问,则操作系统内核崩溃。



Linux/IA-64用户空间大小仍旧由TASK_SIZE常量所定义,在IA-64中使用0-4区作为用户空间,5-7区作为核心空间,PAGE_OFFSET常量指向第7区,如图3所示。内核空间可以进一步划分为页表映射段和对等映射段。页表映射段是由内核页表映射的,主要用于实现内核的vmalloc区域,内核用vmalloc区域实现虚地址连续的大内存块分配,该区域的地址范围由VMALLOC_START和VMALLOC_END决定的。对等映射段包含Linux的内核,如内核的正文段、数据段和栈段。对等映射是非常特殊的,该段的虚地址可以直接与物理地址映射,映射公式非常简单,通常是虚地址直接减一个基地址(如,PAGE_OFFSET)就得到物理地址。




在核心空间中,7区实现Cache的对等映射,6区实现非Cache的对等映射,5区实现内核页表映射段。5区中的第一页称为guard页,该页不被映射,对该页的任何访问都将产生一次页故障,该页用于在用户空间和核心空间数据拷贝时的快速权限检查。第二页称为gate页,用于支持核心和用户级的转换。第三页称为per-CPU页,它提供每个CPU的本地信息,用于多处理器系统。5区中剩余部分用于vmalloc区,从VMALLOC_START到VMALLOC_END。Linux/IA-64中各区的特性如下表所示,

区号 使用 页大小 范围 映射方式
7 Cache 256MB 全局 对等
6 非Cache 256MB 全局 对等
5 vmalloc, guard, gate 8K 全局 页表
4 栈段 8K 进程 页表
3 数据段 8K 进程 页表
2 正文段 8K 进程 页表
1 共享内存 8K 进程 页表
0 IA-32模拟 8K 进程 页表

Linux/IA-64基于区的地址空间划分与传统的X86体系结构不同,具有以下优势:(1)可以充分利用IA-64提供的支持多种物理页大小特性,通过区号实现不同页大小的区,如,操作系统内核代码和数据在7区,采用256MB大小的页,用户进程的正文段在2区,采用8KB大小的页,从而有效节约系统的硬件资源,提高系统性能。(2)便于应用程序的扩展。用户进程的正文段、数据段、栈段在不同的区,而每个区之间相差2048P字节,因此正文段或数据段的扩展不会引起各段之间的地址重叠。(3)便于实现基于区的共享和保护。





回页首


IA-64 Linux在物理内存中为每个进程维护一个页表并通过第7区的对等映射内核段访问该页表。页表驻留在内存,不能被交换到磁盘,这可以简化内核设计,因为内核不需要考虑嵌套的页故障。目前主流的硬件平台不支持可变的页尺寸,如:X86只支持两种尺寸的页框:4KB或4MB(如果支持PAE,还有2MB),IA-64支持4KB、8KB、16KB、64KB、256KB、1MB、4MB、16MB、64MB和256MB多种页框尺寸,因此页机制更加灵活方便。目前IA-64 Linux仍旧采用三级页表树结构,每个页框8KB,每级目录占据一个页框,每项8字节大小,由全局目录(PGD)、中间目录(PMD)、页表项(PTE)组成。IA-64 Linux用户空间虚地址格式为




其中,全局目录索引被分为pgdh(3位)和pgdl(7位),将全局目录索引分成两部分可以通过虚地址的高3位映射到每个区,ar.k7寄存器指向当前进程的页表树的基地址。第5区至第7区是为内核预留的,用户进程不允许将pgdh大于5的任何地址映射到用户空间,IA-64 Linux通过设置FIRST_USER_PGD_NR为0,USER_PTRS_PER_PGD为640来实现,因此在进程页表的全局目录中有3/8(5区、6区、7区)的地址空间没有用。




内核使用一个独立的页表来管理页表映射内核段,与用户空间每个进程一个页表不同,该页表属于整个内核,而且与当前正在运行的进程无关。IA-64 Linux用第5区实现页表映射内核段。61位至63位固定值为5,全局目录从33位至42位,没有像用户虚地址空间页表一样分成两部分,而是连续的。

IA-64页表项支持短模式和长模式。短模式每个页表项8个字节,是一个线性页表,短模式可以使用自映射页表。长模式每个页表项32个字节,是一个Hash页表,Hash功能嵌入在硬件中,长模式支持在同一个域内的保护字和多种页尺寸。Linux页表采用短模式,便于将Linux页表与VHPT walker有机结合,而长模式可以为每个页表项指定不同的保护字,因此TLB效率较高,但使用长模式需要额外的内存空间和转换工作保证页表的Cache一致性。





回页首


Linux/IA-64虚实地址变换由IA-64的TLB(Translation Lookaside Buffer)机制和Linux虚存管理协同工作实现的,高效的虚实地址变换可以极大提高Linux的性能。IA 64 TLB从逻辑上可以分成指令的ITLB和数据的DTLB,ITLB又分为ITC、ITR,DTLB又分为DTC、DTR,如图所示。




TC(Translation Cache)和TR(Translation Register)的区别是替换策略的不同,TC的替换策略是由硬件控制的,而TR的替换策略是由软件指定的,因此TR具有以下特性:软件在TR中插入一个映射后,除非软件又插入一个新的映射或清除了该映射,否则该映射一直有效。Linux/IA-64用TR完成关键地址的变换,保证对关键地址的内存访问都能命中TLB,减少TLB失效次数。由于处理器中TR资源有限,Linux/IA-64采用一个大页(256MB),通过TR寄存器将内核的代码和数据映射在7区,通过对等映射快速完成虚实地址变换,目前IA-64 Linux中ITR0映射Linux的内核代码,DTR0映射内核只读数据,ITR1映射EFI(Extensible Firmware Interface)需要的PALcode,DTR1映射每个CPU的数据,DTR2映射内核栈。

IA-64架构除了基本的TLB功能外,还提供区(region)寄存器、保护字(protection key)寄存器和VHPT(Virtual Hash Page Table)walker三种硬件结构加速虚实地址变换。图7给出了在IA-64架构下虚地址到实地址的变换。IA-64通过VPN和RID的HASH在TLB表中寻找匹配项,如果匹配且权限和保护字寄存器检查有效,则获得PFN,与虚地址的OFFSET拼接形成物理地址。如果没有匹配项且VHPT walker赋能,则处理器在内存页表中寻找匹配项,如果找到,则自动将它插入到TC中,否则产生TLB不命中故障,由Linux TLB不命中处理函数处理。




IA 64 VHPT walker是硬件实现的,用于加速TLB查找,可有效降低TLB不命中时操作系统的处理开销。当TLB不命中且VHPT walker赋能时,VHPT walker在内存的特殊页表中寻找匹配项,并自动填充不命中的TLB项,而不需要操作系统的参与。如果屏蔽了VHPT walker,则CPU产生TLB不命中故障,然后由Linux内核处理。由于硬件实现VHPT walker,因此它的使用有一定限制,目前只支持两种模式:hash模式和线性页表模式。Linux使用短模式。

VHPT walker的配置是由页表地址控制寄存器PTA决定的。在发生TLB不命中,且该地址所在的区寄存器的VHPT位和PTA的ve位为1,则激活VHPT walker,PTA的vf位确定是长模式还是短模式。PTA的base和size域定义虚拟线性页表在该区的地址范围。每个区的VHPT walker可以分别禁用(通过设置区寄存器的VHPT位),在允许VHPT walker的区内,虚拟线性页表映射在每个区的相同相对位置。虚拟线性页表不能与正常页表映射的地址空间重叠,并且也不能与前面提到的该区中间的地址空洞重叠。Linux/IA-64通过设置PTA寄存器,将虚拟线性页表映射在该区的顶端,操作系统在引导时检查是否有重叠。

当访问虚地址va发生TLB不命中时,VHPT walker计算映射虚地址va的页表项所在虚地址va',使用虚拟映射线性地址页表,该地址计算如下:

VHPT walker去读取存储在该地址的页表项,由于该地址也是一个虚地址,CPU将进行正常的虚实地址变换,如果va'的TLB项存在,则变换成功,walker从物理内存中读取页表项,并安装va的页表项。如果va'的TLB项不存在,则walker产生VHPT TRANSLATION FAULT。VHPT walker不能直接访问Linux页表,因为它不知道Linux的页表结构。采用VHPT主要是从空间局部性上考虑,因为映射某个页表项的TLB项事实上映射了该页表项所在的整个页,在安装完该页表页的TLB项后,访问同一页内页表项的TLB不命中可以由VHPT walker直接处理,有效减少了Linux参与TLB不命中的故障处理次数。

为了避免操作系统每次现场切换时刷新TLB的高额开销,Linux定义了与具体平台无关的抽象ASN(Address Space Number)接口,通过该接口可以实现懒惰的TLB刷新,在现场切换时不需要刷新所有的TLB表项。ASN接口的支持是可选的,如果具体平台不支持,则这些接口函数为空,flush_tlb_mm( )就刷新所有的TLB。Linux/IA-64采用区ID实现ASN接口,虽然IA-64定义了24位的区ID,但安腾处理器只使用了18位。Linux/IA-64中区ID 0是为内核预留的,剩余的ID通过get_mmu_context( )以轮转方式分配,当最后一个可用区ID分配完后,刷新整个TLB,并重新计算可用区ID的范围。

get_mmu_context( )返回的区ID是所有CPU共享的,这种全局区ID分配策略对单处理器和小规模的多处理器系统是十分有效的,它可以使用一条ptc.ga指令清空该机器所有CPU的TLB项,但当机器的CPU数目较多时,全局区ID分配会成为潜在的竞争资源。





回页首


Linux充分利用IA-64架构地址空间划分的灵活性、TLB结构和VHPT等特性,实现了高效的虚拟存储管理,在SGI的Altix3000、HP的rx5670服务器等系统上得到了充分验证。随着IA-64系统规模的不断扩大,大系统的高效内存管理、非一致性内存访问(NUMA)等技术成为IA-64 Linux内存管理新的研究热点。

阅读(1590) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~