首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

IA-64 Linux存储管理(2)

IA-64 Linux存储管理(2)

三 页表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用户空间虚地址格式为
图4  用户空间虚地址格式(8KB页)其中,全局目录索引被分为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区)的地址空间没有用。
图5  页表映射内核段虚地址格式(8KB页)内核使用一个独立的页表来管理页表映射内核段,与用户空间每个进程一个页表不同,该页表属于整个内核,而且与当前正在运行的进程无关。IA-64 Linux用第5区实现页表映射内核段。61位至63位固定值为5,全局目录从33位至42位,没有像用户虚地址空间页表一样分成两部分,而是连续的。
IA-64页表项支持短模式和长模式。短模式每个页表项8个字节,是一个线性页表,短模式可以使用自映射页表。长模式每个页表项32个字节,是一个Hash页表,Hash功能嵌入在硬件中,长模式支持在同一个域内的保护字和多种页尺寸。Linux页表采用短模式,便于将Linux页表与VHPT walker有机结合,而长模式可以为每个页表项指定不同的保护字,因此TLB效率较高,但使用长模式需要额外的内存空间和转换工作保证页表的Cache一致性。
四 TLBLinux/IA-64虚实地址变换由IA-64的TLB(Translation Lookaside Buffer)机制和Linux虚存管理协同工作实现的,高效的虚实地址变换可以极大提高Linux的性能。IA 64 TLB从逻辑上可以分成指令的ITLB和数据的DTLB,ITLB又分为ITC、ITR,DTLB又分为DTC、DTR,如图所示。
图6  IA-64 TLB组织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不命中处理函数处理。
图7  IA-64虚实地址变换4.1 VHPT walkerIA 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不命中的故障处理次数。
4.2 懒惰的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分配会成为潜在的竞争资源。
返回列表